This source file includes following definitions.
- mix_write
- mixer_output
- set_mode
- pas_mixer_set
- pas_mixer_reset
- pas_mixer_ioctl
- pas_init_mixer
1 #define _PAS2_MIXER_C_
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
31 #include <linux/config.h>
32
33
34 #include "sound_config.h"
35
36 #if defined(CONFIG_PAS)
37
38 #include "pas.h"
39
40 #define TRACE(what)
41
42 extern int translat_code;
43 extern char pas_model;
44 extern int *pas_osp;
45
46 static int rec_devices = (SOUND_MASK_MIC);
47 static int mode_control = 0;
48
49 #define POSSIBLE_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
50 SOUND_MASK_CD | SOUND_MASK_ALTPCM)
51
52 #define SUPPORTED_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
53 SOUND_MASK_CD | SOUND_MASK_ALTPCM | SOUND_MASK_IMIX | \
54 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_RECLEV | \
55 SOUND_MASK_MUTE | SOUND_MASK_ENHANCE | SOUND_MASK_LOUD)
56
57 static unsigned short levels[SOUND_MIXER_NRDEVICES] =
58 {
59 0x3232,
60 0x3232,
61 0x3232,
62 0x5050,
63 0x4b4b,
64 0x3232,
65 0x4b4b,
66 0x4b4b,
67 0x4b4b,
68 0x6464,
69 0x4b4b,
70 0x6464
71 };
72
73 void
74 mix_write (unsigned char data, int ioaddr)
75 {
76
77
78
79
80
81
82
83
84 if (pas_model == PAS_16D)
85 {
86 outw (data | (data << 8), (ioaddr ^ translat_code) - 1);
87 outb (0x80, 0);
88 }
89 else
90 pas_write (data, ioaddr);
91 }
92
93 static int
94 mixer_output (int right_vol, int left_vol, int div, int bits,
95 int mixer)
96 {
97 int left = left_vol * div / 100;
98 int right = right_vol * div / 100;
99
100
101 if (bits & P_M_MV508_MIXER)
102 {
103
104
105 left |= mixer;
106 right |= mixer;
107 }
108
109 if (bits == P_M_MV508_BASS || bits == P_M_MV508_TREBLE)
110 {
111
112
113 mix_write (P_M_MV508_ADDRESS | bits, PARALLEL_MIXER);
114 mix_write (left, PARALLEL_MIXER);
115 right_vol = left_vol;
116 }
117 else
118 {
119 mix_write (P_M_MV508_ADDRESS | P_M_MV508_LEFT | bits, PARALLEL_MIXER);
120 mix_write (left, PARALLEL_MIXER);
121 mix_write (P_M_MV508_ADDRESS | P_M_MV508_RIGHT | bits, PARALLEL_MIXER);
122 mix_write (right, PARALLEL_MIXER);
123 }
124
125 return (left_vol | (right_vol << 8));
126 }
127
128 void
129 set_mode (int new_mode)
130 {
131 mix_write (P_M_MV508_ADDRESS | P_M_MV508_MODE, PARALLEL_MIXER);
132 mix_write (new_mode, PARALLEL_MIXER);
133
134 mode_control = new_mode;
135 }
136
137 static int
138 pas_mixer_set (int whichDev, unsigned int level)
139 {
140 int left, right, devmask, changed, i, mixer = 0;
141
142 TRACE (printk ("static int pas_mixer_set(int whichDev = %d, unsigned int level = %X)\n", whichDev, level));
143
144 left = level & 0x7f;
145 right = (level & 0x7f00) >> 8;
146
147 if (whichDev < SOUND_MIXER_NRDEVICES)
148 if ((1 << whichDev) & rec_devices)
149 mixer = P_M_MV508_INPUTMIX;
150 else
151 mixer = P_M_MV508_OUTPUTMIX;
152
153 switch (whichDev)
154 {
155 case SOUND_MIXER_VOLUME:
156 levels[whichDev] = mixer_output (right, left, 63, P_M_MV508_MASTER_A, 0);
157 break;
158
159
160
161
162
163 case SOUND_MIXER_BASS:
164 levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_BASS, 0);
165 break;
166 case SOUND_MIXER_TREBLE:
167 levels[whichDev] = mixer_output (right, left, 12, P_M_MV508_TREBLE, 0);
168 break;
169
170 case SOUND_MIXER_SYNTH:
171 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_FM, mixer);
172 break;
173 case SOUND_MIXER_PCM:
174 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_PCM, mixer);
175 break;
176 case SOUND_MIXER_ALTPCM:
177 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SB, mixer);
178 break;
179 case SOUND_MIXER_SPEAKER:
180 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_SPEAKER, mixer);
181 break;
182 case SOUND_MIXER_LINE:
183 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_LINE, mixer);
184 break;
185 case SOUND_MIXER_CD:
186 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_CDROM, mixer);
187 break;
188 case SOUND_MIXER_MIC:
189 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_MIC, mixer);
190 break;
191 case SOUND_MIXER_IMIX:
192 levels[whichDev] = mixer_output (right, left, 31, P_M_MV508_MIXER | P_M_MV508_IMIXER,
193 P_M_MV508_OUTPUTMIX);
194 break;
195 case SOUND_MIXER_RECLEV:
196 levels[whichDev] = mixer_output (right, left, 15, P_M_MV508_MASTER_B, 0);
197 break;
198
199 case SOUND_MIXER_MUTE:
200 return 0;
201 break;
202
203 case SOUND_MIXER_ENHANCE:
204 i = 0;
205 level &= 0x7f;
206 if (level)
207 i = (level / 20) - 1;
208
209 mode_control &= ~P_M_MV508_ENHANCE_BITS;
210 mode_control |= P_M_MV508_ENHANCE_BITS;
211 set_mode (mode_control);
212
213 if (i)
214 i = (i + 1) * 20;
215 return i;
216 break;
217
218 case SOUND_MIXER_LOUD:
219 mode_control &= ~P_M_MV508_LOUDNESS;
220 if (level)
221 mode_control |= P_M_MV508_LOUDNESS;
222 set_mode (mode_control);
223 return !!level;
224 break;
225
226 case SOUND_MIXER_RECSRC:
227 devmask = level & POSSIBLE_RECORDING_DEVICES;
228
229 changed = devmask ^ rec_devices;
230 rec_devices = devmask;
231
232 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
233 if (changed & (1 << i))
234 {
235 pas_mixer_set (i, levels[i]);
236 }
237 return rec_devices;
238 break;
239
240 default:
241 return -EINVAL;
242 }
243
244 return (levels[whichDev]);
245 }
246
247
248
249 static void
250 pas_mixer_reset (void)
251 {
252 int foo;
253
254 TRACE (printk ("pas2_mixer.c: void pas_mixer_reset(void)\n"));
255
256 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
257 pas_mixer_set (foo, levels[foo]);
258
259 set_mode (P_M_MV508_LOUDNESS | P_M_MV508_ENHANCE_40);
260 }
261
262 int
263 pas_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
264 {
265 TRACE (printk ("pas2_mixer.c: int pas_mixer_ioctl(unsigned int cmd = %X, unsigned int arg = %X)\n", cmd, arg));
266
267 if (((cmd >> 8) & 0xff) == 'M')
268 {
269 if (_IOC_DIR (cmd) & _IOC_WRITE)
270 return snd_ioctl_return ((int *) arg, pas_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
271 else
272 {
273
274
275
276 switch (cmd & 0xff)
277 {
278
279 case SOUND_MIXER_RECSRC:
280 return snd_ioctl_return ((int *) arg, rec_devices);
281 break;
282
283 case SOUND_MIXER_STEREODEVS:
284 return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES & ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE));
285 break;
286
287 case SOUND_MIXER_DEVMASK:
288 return snd_ioctl_return ((int *) arg, SUPPORTED_MIXER_DEVICES);
289 break;
290
291 case SOUND_MIXER_RECMASK:
292 return snd_ioctl_return ((int *) arg, POSSIBLE_RECORDING_DEVICES & SUPPORTED_MIXER_DEVICES);
293 break;
294
295 case SOUND_MIXER_CAPS:
296 return snd_ioctl_return ((int *) arg, 0);
297 break;
298
299 case SOUND_MIXER_MUTE:
300 return snd_ioctl_return ((int *) arg, 0);
301 break;
302
303 case SOUND_MIXER_ENHANCE:
304 if (!(mode_control & P_M_MV508_ENHANCE_BITS))
305 return snd_ioctl_return ((int *) arg, 0);
306 return snd_ioctl_return ((int *) arg, ((mode_control & P_M_MV508_ENHANCE_BITS) + 1) * 20);
307 break;
308
309 case SOUND_MIXER_LOUD:
310 if (mode_control & P_M_MV508_LOUDNESS)
311 return snd_ioctl_return ((int *) arg, 1);
312 return snd_ioctl_return ((int *) arg, 0);
313 break;
314
315 default:
316 return snd_ioctl_return ((int *) arg, levels[cmd & 0xff]);
317 }
318 }
319 }
320 return -EINVAL;
321 }
322
323 static struct mixer_operations pas_mixer_operations =
324 {
325 "Pro Audio Spectrum 16",
326 pas_mixer_ioctl
327 };
328
329 int
330 pas_init_mixer (void)
331 {
332 pas_mixer_reset ();
333
334 if (num_mixers < MAX_MIXER_DEV)
335 mixer_devs[num_mixers++] = &pas_mixer_operations;
336 return 1;
337 }
338
339 #endif