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