This source file includes following definitions.
- sb_setmixer
- sb_getmixer
- sb_mixer_set_stereo
- detect_mixer
- change_bits
- sb_mixer_get
- smw_mixer_init
- smw_mixer_set
- sb_mixer_set
- set_recsrc
- set_recmask
- sb_mixer_ioctl
- sb_mixer_reset
- sb_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 <linux/config.h>
31
32
33
34
35
36
37
38
39 #include "sound_config.h"
40
41 #if defined(CONFIG_SB)
42 #define __SB_MIXER_C__
43
44 #include "sb.h"
45 #include "sb_mixer.h"
46 #undef SB_TEST_IRQ
47
48 extern int sbc_base;
49 extern int Jazz16_detected;
50 extern int *sb_osp;
51 extern int AudioDrive;
52
53 static int mixer_initialized = 0;
54
55 static int supported_rec_devices;
56 static int supported_devices;
57 static int recmask = 0;
58 static int mixer_model;
59 static int mixer_caps;
60 static mixer_tab *iomap;
61
62 void
63 sb_setmixer (unsigned int port, unsigned int value)
64 {
65 unsigned long flags;
66
67 save_flags (flags);
68 cli ();
69 outb ((unsigned char) (port & 0xff), MIXER_ADDR);
70
71
72 tenmicrosec (sb_osp);
73 outb ((unsigned char) (value & 0xff), MIXER_DATA);
74 tenmicrosec (sb_osp);
75 restore_flags (flags);
76 }
77
78 int
79 sb_getmixer (unsigned int port)
80 {
81 int val;
82 unsigned long flags;
83
84 save_flags (flags);
85 cli ();
86 outb ((unsigned char) (port & 0xff), MIXER_ADDR);
87
88
89 tenmicrosec (sb_osp);
90 val = inb (MIXER_DATA);
91 tenmicrosec (sb_osp);
92 restore_flags (flags);
93
94 return val;
95 }
96
97 void
98 sb_mixer_set_stereo (int mode)
99 {
100 if (!mixer_initialized)
101 return;
102
103 sb_setmixer (OUT_FILTER, ((sb_getmixer (OUT_FILTER) & ~STEREO_DAC)
104 | (mode ? STEREO_DAC : MONO_DAC)));
105 }
106
107
108
109
110
111
112
113 static int
114 detect_mixer (void)
115 {
116 #ifdef __SGNXPRO__
117 int oldbass, oldtreble;
118 extern int sbc_major;
119
120 #endif
121 int retcode = 1;
122
123
124
125
126
127
128 sb_setmixer (FM_VOL, 0xff);
129 sb_setmixer (VOC_VOL, 0x33);
130
131 if (sb_getmixer (FM_VOL) != 0xff)
132 return 0;
133
134
135 if (sb_getmixer (VOC_VOL) != 0x33)
136 return 0;
137
138 #ifdef __SGNXPRO__
139
140
141
142 oldbass = sb_getmixer (BASS_LVL);
143 oldtreble = sb_getmixer (TREBLE_LVL);
144
145 sb_setmixer (BASS_LVL, 0xaa);
146 sb_setmixer (TREBLE_LVL, 0x55);
147
148 if ((sb_getmixer (BASS_LVL) != 0xaa) ||
149 (sb_getmixer (TREBLE_LVL) != 0x55))
150 {
151 retcode = 1;
152 }
153 else
154 retcode = 2;
155
156
157
158 sb_setmixer (BASS_LVL, oldbass);
159 sb_setmixer (TREBLE_LVL, oldtreble);
160
161
162
163
164
165
166
167
168
169 if (sbc_major == 3)
170 {
171 outb (0x01, sbc_base + 0x1c);
172 outb (0x00, sbc_base + 0x1a);
173 }
174
175 #endif
176 return retcode;
177 }
178
179 static void
180 change_bits (unsigned char *regval, int dev, int chn, int newval)
181 {
182 unsigned char mask;
183 int shift;
184
185 mask = (1 << (*iomap)[dev][chn].nbits) - 1;
186 newval = (int) ((newval * mask) + 50) / 100;
187
188
189
190 shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1;
191
192 *regval &= ~(mask << shift);
193
194
195 *regval |= (newval & mask) << shift;
196
197
198 }
199
200 static int
201 sb_mixer_get (int dev)
202 {
203 if (!((1 << dev) & supported_devices))
204 return -EINVAL;
205
206 return levels[dev];
207 }
208
209 static char smw_mix_regs[] =
210 {
211 0x0b,
212 0x0d,
213 0x0d,
214 0x05,
215 0x09,
216 0x00,
217 0x03,
218 0x01,
219 0x07,
220 0x00,
221 0x00,
222 0x00,
223 0x00,
224 0x00,
225 0x00,
226 0x00,
227 0x00
228 };
229
230 void
231 smw_mixer_init (void)
232 {
233 int i;
234
235 sb_setmixer (0x00, 0x18);
236 sb_setmixer (0x10, 0x38);
237
238 supported_devices = 0;
239 for (i = 0; i < sizeof (smw_mix_regs); i++)
240 if (smw_mix_regs[i] != 0)
241 supported_devices |= (1 << i);
242
243 supported_rec_devices = supported_devices &
244 ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM |
245 SOUND_MASK_VOLUME);
246 }
247
248 static int
249 smw_mixer_set (int dev, int value)
250 {
251 int left = value & 0x000000ff;
252 int right = (value & 0x0000ff00) >> 8;
253 int reg, val;
254
255 if (left > 100)
256 left = 100;
257 if (right > 100)
258 right = 100;
259
260 if (dev > 31)
261 return -EINVAL;
262
263 if (!(supported_devices & (1 << dev)))
264 return -EINVAL;
265
266 switch (dev)
267 {
268 case SOUND_MIXER_VOLUME:
269 sb_setmixer (0x0b, 96 - (96 * left / 100));
270 sb_setmixer (0x0c, 96 - (96 * right / 100));
271 break;
272
273 case SOUND_MIXER_BASS:
274 case SOUND_MIXER_TREBLE:
275 levels[dev] = left | (right << 8);
276
277
278 val = ((levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
279 val |= ((levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
280 sb_setmixer (0x0d, val);
281
282
283 val = (((levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
284 val |= (((levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
285 sb_setmixer (0x0e, val);
286 break;
287
288 default:
289 reg = smw_mix_regs[dev];
290 if (reg == 0)
291 return -EINVAL;
292 sb_setmixer (reg, (24 - (24 * left / 100)) | 0x20);
293 sb_setmixer (reg + 1, (24 - (24 * right / 100)) | 0x40);
294 }
295
296 levels[dev] = left | (right << 8);
297 return left | (right << 8);
298 }
299
300 static int
301 sb_mixer_set (int dev, int value)
302 {
303 int left = value & 0x000000ff;
304 int right = (value & 0x0000ff00) >> 8;
305
306 int regoffs;
307 unsigned char val;
308
309 if (Jazz16_detected == 2)
310 return smw_mixer_set (dev, value);
311
312 if (left > 100)
313 left = 100;
314 if (right > 100)
315 right = 100;
316
317 if (dev > 31)
318 return -EINVAL;
319
320 if (!(supported_devices & (1 << dev)))
321
322
323 return -EINVAL;
324
325 regoffs = (*iomap)[dev][LEFT_CHN].regno;
326
327 if (regoffs == 0)
328 return -EINVAL;
329
330 val = sb_getmixer (regoffs);
331 change_bits (&val, dev, LEFT_CHN, left);
332
333 levels[dev] = left | (left << 8);
334
335 if ((*iomap)[dev][RIGHT_CHN].regno != regoffs)
336
337
338 {
339 sb_setmixer (regoffs, val);
340
341
342 regoffs = (*iomap)[dev][RIGHT_CHN].regno;
343
344 if (regoffs == 0)
345 return left | (left << 8);
346
347
348
349 val = sb_getmixer (regoffs);
350
351
352 }
353
354 change_bits (&val, dev, RIGHT_CHN, right);
355
356 sb_setmixer (regoffs, val);
357
358 levels[dev] = left | (right << 8);
359 return left | (right << 8);
360 }
361
362 static void
363 set_recsrc (int src)
364 {
365 sb_setmixer (RECORD_SRC, (sb_getmixer (RECORD_SRC) & ~7) | (src & 0x7));
366 }
367
368 static int
369 set_recmask (int mask)
370 {
371 int devmask, i;
372 unsigned char regimageL, regimageR;
373
374 devmask = mask & supported_rec_devices;
375
376 switch (mixer_model)
377 {
378 case 3:
379
380 if (devmask != SOUND_MASK_MIC &&
381 devmask != SOUND_MASK_LINE &&
382 devmask != SOUND_MASK_CD)
383 {
384
385
386
387 devmask &= ~recmask;
388 }
389
390 if (devmask != SOUND_MASK_MIC &&
391 devmask != SOUND_MASK_LINE &&
392 devmask != SOUND_MASK_CD)
393 {
394
395
396
397 devmask = SOUND_MASK_MIC;
398 }
399
400
401 if (devmask ^ recmask)
402
403
404 {
405 switch (devmask)
406 {
407
408 case SOUND_MASK_MIC:
409 set_recsrc (SRC_MIC);
410 break;
411
412 case SOUND_MASK_LINE:
413 set_recsrc (SRC_LINE);
414 break;
415
416 case SOUND_MASK_CD:
417 set_recsrc (SRC_CD);
418 break;
419
420 default:
421 set_recsrc (SRC_MIC);
422 }
423 }
424
425 break;
426
427 case 4:
428 if (!devmask)
429 devmask = SOUND_MASK_MIC;
430
431 regimageL = regimageR = 0;
432 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
433 if ((1 << i) & devmask)
434 {
435 regimageL |= sb16_recmasks_L[i];
436 regimageR |= sb16_recmasks_R[i];
437 }
438 sb_setmixer (SB16_IMASK_L, regimageL);
439 sb_setmixer (SB16_IMASK_R, regimageR);
440 break;
441 }
442
443 recmask = devmask;
444 return recmask;
445 }
446
447 static int
448 sb_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
449 {
450 if (((cmd >> 8) & 0xff) == 'M')
451 {
452 if (_IOC_DIR (cmd) & _IOC_WRITE)
453 switch (cmd & 0xff)
454 {
455 case SOUND_MIXER_RECSRC:
456 return snd_ioctl_return ((int *) arg, set_recmask (get_fs_long ((long *) arg)));
457 break;
458
459 default:
460
461 return snd_ioctl_return ((int *) arg, sb_mixer_set (cmd & 0xff, get_fs_long ((long *) arg)));
462 }
463 else
464 switch (cmd & 0xff)
465
466
467 {
468
469 case SOUND_MIXER_RECSRC:
470 return snd_ioctl_return ((int *) arg, recmask);
471 break;
472
473 case SOUND_MIXER_DEVMASK:
474 return snd_ioctl_return ((int *) arg, supported_devices);
475 break;
476
477 case SOUND_MIXER_STEREODEVS:
478 if (Jazz16_detected)
479 return snd_ioctl_return ((int *) arg, supported_devices);
480 else
481 return snd_ioctl_return ((int *) arg, supported_devices & ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER));
482 break;
483
484 case SOUND_MIXER_RECMASK:
485 return snd_ioctl_return ((int *) arg, supported_rec_devices);
486 break;
487
488 case SOUND_MIXER_CAPS:
489 return snd_ioctl_return ((int *) arg, mixer_caps);
490 break;
491
492 default:
493 return snd_ioctl_return ((int *) arg, sb_mixer_get (cmd & 0xff));
494 }
495 }
496 else
497 return -EINVAL;
498 }
499
500 static struct mixer_operations sb_mixer_operations =
501 {
502 "SoundBlaster",
503 sb_mixer_ioctl
504 };
505
506 void
507 sb_mixer_reset (void)
508 {
509 int i;
510
511 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
512 sb_mixer_set (i, levels[i]);
513 set_recmask (SOUND_MASK_MIC);
514 }
515
516
517
518
519
520
521
522
523
524 int
525 sb_mixer_init (int major_model)
526 {
527 int mixer_type = 0;
528
529 sb_setmixer (0x00, 0);
530
531 if (!(mixer_type = detect_mixer ()))
532 return 0;
533
534 mixer_initialized = 1;
535 mixer_model = major_model;
536
537 switch (major_model)
538 {
539 case 3:
540 mixer_caps = SOUND_CAP_EXCL_INPUT;
541
542 if (AudioDrive)
543 {
544 supported_devices = ES688_MIXER_DEVICES;
545 supported_rec_devices = ES688_RECORDING_DEVICES;
546 iomap = &es688_mix;
547 }
548 else if (Jazz16_detected == 2)
549 {
550 supported_devices = 0;
551 supported_rec_devices = 0;
552 iomap = &sbpro_mix;
553 smw_mixer_init ();
554 mixer_type = 1;
555 }
556 else
557 #ifdef __SGNXPRO__
558 if (mixer_type == 2)
559 {
560 supported_devices = SGNXPRO_MIXER_DEVICES;
561 supported_rec_devices = SGNXPRO_RECORDING_DEVICES;
562 iomap = &sgnxpro_mix;
563 }
564 else
565 #endif
566 {
567 supported_devices = SBPRO_MIXER_DEVICES;
568 supported_rec_devices = SBPRO_RECORDING_DEVICES;
569 iomap = &sbpro_mix;
570 mixer_type = 1;
571 }
572 break;
573
574 case 4:
575 mixer_caps = 0;
576 supported_devices = SB16_MIXER_DEVICES;
577 supported_rec_devices = SB16_RECORDING_DEVICES;
578 iomap = &sb16_mix;
579 mixer_type = 3;
580 break;
581
582 default:
583 printk ("SB Warning: Unsupported mixer type\n");
584 return 0;
585 }
586
587 if (num_mixers < MAX_MIXER_DEV)
588 mixer_devs[num_mixers++] = &sb_mixer_operations;
589 sb_mixer_reset ();
590 return mixer_type;
591 }
592
593 #endif