This source file includes following definitions.
- scale_vol
- write_mix
- set_volumes
- ics2101_mixer_ioctl
- ics2101_mixer_init
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #include "sound_config.h"
31 #if defined(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_GUS)
32
33 #include <linux/ultrasound.h>
34 #include "gus_hw.h"
35
36 #define MIX_DEVS (SOUND_MASK_MIC|SOUND_MASK_LINE| \
37 SOUND_MASK_SYNTH| \
38 SOUND_MASK_CD | SOUND_MASK_VOLUME)
39
40 extern int gus_base;
41 static int volumes[ICS_MIXDEVS];
42 static int left_fix[ICS_MIXDEVS] =
43 {1, 1, 1, 2, 1, 2};
44 static int right_fix[ICS_MIXDEVS] =
45 {2, 2, 2, 1, 2, 1};
46
47 static int
48 scale_vol (int vol)
49 {
50
51
52
53
54
55 int e;
56
57 if (vol < 0)
58 vol = 0;
59 if (vol > 100)
60 vol = 100;
61 vol = (31 * vol + 50) / 100;
62 e = 0;
63 if (vol)
64 {
65 while (vol < 16)
66 {
67 vol <<= 1;
68 e--;
69 }
70 vol -= 16;
71 e += 7;
72 }
73 return ((e << 4) + vol);
74 }
75
76 static void
77 write_mix (int dev, int chn, int vol)
78 {
79 int *selector;
80 unsigned long flags;
81 int ctrl_addr = dev << 3;
82 int attn_addr = dev << 3;
83
84 vol = scale_vol (vol);
85
86 if (chn == CHN_LEFT)
87 {
88 selector = left_fix;
89 ctrl_addr |= 0x00;
90 attn_addr |= 0x02;
91 }
92 else
93 {
94 selector = right_fix;
95 ctrl_addr |= 0x01;
96 attn_addr |= 0x03;
97 }
98
99 save_flags (flags);
100 cli ();
101 outb (ctrl_addr, u_MixSelect);
102 outb (selector[dev], u_MixData);
103 outb (attn_addr, u_MixSelect);
104 outb ((unsigned char) vol, u_MixData);
105 restore_flags (flags);
106 }
107
108 static int
109 set_volumes (int dev, int vol)
110 {
111 int left = vol & 0x00ff;
112 int right = (vol >> 8) & 0x00ff;
113
114 if (left < 0)
115 left = 0;
116 if (left > 100)
117 left = 100;
118 if (right < 0)
119 right = 0;
120 if (right > 100)
121 right = 100;
122
123 write_mix (dev, CHN_LEFT, left);
124 write_mix (dev, CHN_RIGHT, right);
125
126 vol = left + (right << 8);
127 volumes[dev] = vol;
128 return vol;
129 }
130
131 static int
132 ics2101_mixer_ioctl (int dev, unsigned int cmd, ioctl_arg arg)
133 {
134 if (((cmd >> 8) & 0xff) == 'M')
135 {
136 if (cmd & IOC_IN)
137 switch (cmd & 0xff)
138 {
139 case SOUND_MIXER_RECSRC:
140 return gus_default_mixer_ioctl (dev, cmd, arg);
141 break;
142
143 case SOUND_MIXER_MIC:
144 return snd_ioctl_return ((int *) arg, set_volumes (DEV_MIC, get_fs_long ((long *) arg)));
145 break;
146
147 case SOUND_MIXER_CD:
148 return snd_ioctl_return ((int *) arg, set_volumes (DEV_CD, get_fs_long ((long *) arg)));
149 break;
150
151 case SOUND_MIXER_LINE:
152 return snd_ioctl_return ((int *) arg, set_volumes (DEV_LINE, get_fs_long ((long *) arg)));
153 break;
154
155 case SOUND_MIXER_SYNTH:
156 return snd_ioctl_return ((int *) arg, set_volumes (DEV_GF1, get_fs_long ((long *) arg)));
157 break;
158
159 case SOUND_MIXER_VOLUME:
160 return snd_ioctl_return ((int *) arg, set_volumes (DEV_VOL, get_fs_long ((long *) arg)));
161 break;
162
163 default:
164 return -EINVAL;
165 }
166 else
167 switch (cmd & 0xff)
168
169
170 {
171
172 case SOUND_MIXER_RECSRC:
173 return gus_default_mixer_ioctl (dev, cmd, arg);
174 break;
175
176 case SOUND_MIXER_DEVMASK:
177 return snd_ioctl_return ((int *) arg, MIX_DEVS);
178 break;
179
180 case SOUND_MIXER_STEREODEVS:
181 return snd_ioctl_return ((int *) arg, SOUND_MASK_LINE | SOUND_MASK_CD | SOUND_MASK_SYNTH | SOUND_MASK_VOLUME | SOUND_MASK_MIC);
182 break;
183
184 case SOUND_MIXER_RECMASK:
185 return snd_ioctl_return ((int *) arg, SOUND_MASK_MIC | SOUND_MASK_LINE);
186 break;
187
188 case SOUND_MIXER_CAPS:
189 return snd_ioctl_return ((int *) arg, 0);
190 break;
191
192 case SOUND_MIXER_MIC:
193 return snd_ioctl_return ((int *) arg, volumes[DEV_MIC]);
194 break;
195
196 case SOUND_MIXER_LINE:
197 return snd_ioctl_return ((int *) arg, volumes[DEV_LINE]);
198 break;
199
200 case SOUND_MIXER_CD:
201 return snd_ioctl_return ((int *) arg, volumes[DEV_CD]);
202 break;
203
204 case SOUND_MIXER_VOLUME:
205 return snd_ioctl_return ((int *) arg, volumes[DEV_VOL]);
206 break;
207
208 case SOUND_MIXER_SYNTH:
209 return snd_ioctl_return ((int *) arg, volumes[DEV_GF1]);
210 break;
211
212 default:
213 return -EINVAL;
214 }
215 }
216
217 return -EINVAL;
218 }
219
220 static struct mixer_operations ics2101_mixer_operations =
221 {
222 "ICS2101 Multimedia Mixer",
223 ics2101_mixer_ioctl
224 };
225
226 long
227 ics2101_mixer_init (long mem_start)
228 {
229 int i;
230
231 if (num_mixers < MAX_MIXER_DEV)
232 {
233 mixer_devs[num_mixers++] = &ics2101_mixer_operations;
234
235
236
237
238
239
240 if (inb (u_MixSelect) != 5)
241 {
242 for (i = 0; i < ICS_MIXDEVS; i++)
243 left_fix[i] = 1;
244 for (i = 0; i < ICS_MIXDEVS; i++)
245 right_fix[i] = 2;
246 }
247
248 set_volumes (DEV_GF1, 0x5a5a);
249 set_volumes (DEV_CD, 0x5a5a);
250 set_volumes (DEV_MIC, 0x0000);
251 set_volumes (DEV_LINE, 0x5a5a);
252 set_volumes (DEV_VOL, 0x5a5a);
253 set_volumes (DEV_UNUSED, 0x0000);
254 }
255
256 return mem_start;
257 }
258
259 #endif