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