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(CONFIGURE_SOUNDCARD) && !defined(EXCLUDE_SB) && !defined(EXCLUDE_SBPRO)
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
48 static int mixer_initialized = 0;
49
50 static int supported_rec_devices;
51 static int supported_devices;
52 static int recmask = 0;
53 static int mixer_model;
54 static int mixer_caps;
55 static mixer_tab *iomap;
56
57 void
58 sb_setmixer (unsigned int port, unsigned int value)
59 {
60 unsigned long flags;
61
62 save_flags (flags);
63 cli ();
64 outb ((unsigned char) (port & 0xff), MIXER_ADDR);
65
66
67 tenmicrosec ();
68 outb ((unsigned char) (value & 0xff), MIXER_DATA);
69 tenmicrosec ();
70 restore_flags (flags);
71 }
72
73 int
74 sb_getmixer (unsigned int port)
75 {
76 int val;
77 unsigned long flags;
78
79 save_flags (flags);
80 cli ();
81 outb ((unsigned char) (port & 0xff), MIXER_ADDR);
82
83
84 tenmicrosec ();
85 val = inb (MIXER_DATA);
86 tenmicrosec ();
87 restore_flags (flags);
88
89 return val;
90 }
91
92 void
93 sb_mixer_set_stereo (int mode)
94 {
95 if (!mixer_initialized)
96 return;
97
98 sb_setmixer (OUT_FILTER, ((sb_getmixer (OUT_FILTER) & ~STEREO_DAC)
99 | (mode ? STEREO_DAC : MONO_DAC)));
100 }
101
102
103
104
105
106
107
108 static int
109 detect_mixer (void)
110 {
111 #ifdef __SGNXPRO__
112 int oldbass, oldtreble;
113 extern int sbc_major;
114
115 #endif
116 int retcode = 1;
117
118
119
120
121
122
123 sb_setmixer (FM_VOL, 0xff);
124 sb_setmixer (VOC_VOL, 0x33);
125
126 if (sb_getmixer (FM_VOL) != 0xff)
127 return 0;
128
129
130 if (sb_getmixer (VOC_VOL) != 0x33)
131 return 0;
132
133 #ifdef __SGNXPRO__
134
135
136
137 oldbass = sb_getmixer (BASS_LVL);
138 oldtreble = sb_getmixer (TREBLE_LVL);
139
140 sb_setmixer (BASS_LVL, 0xaa);
141 sb_setmixer (TREBLE_LVL, 0x55);
142
143 if ((sb_getmixer (BASS_LVL) != 0xaa) ||
144 (sb_getmixer (TREBLE_LVL) != 0x55))
145 {
146 retcode = 1;
147 }
148 else
149 retcode = 2;
150
151
152
153 sb_setmixer (BASS_LVL, oldbass);
154 sb_setmixer (TREBLE_LVL, oldtreble);
155
156
157
158
159
160
161
162
163
164 if (sbc_major == 3)
165 {
166 outb (0x01, sbc_base + 0x1c);
167 outb (0x00, sbc_base + 0x1a);
168 }
169
170 #endif
171 return retcode;
172 }
173
174 static void
175 change_bits (unsigned char *regval, int dev, int chn, int newval)
176 {
177 unsigned char mask;
178 int shift;
179
180 mask = (1 << (*iomap)[dev][chn].nbits) - 1;
181 newval = (int) ((newval * mask) + 50) / 100;
182
183
184
185 shift = (*iomap)[dev][chn].bitoffs - (*iomap)[dev][LEFT_CHN].nbits + 1;
186
187 *regval &= ~(mask << shift);
188
189
190 *regval |= (newval & mask) << shift;
191
192
193 }
194
195 static int
196 sb_mixer_get (int dev)
197 {
198 if (!((1 << dev) & supported_devices))
199 return -EINVAL;
200
201 return levels[dev];
202 }
203
204 #ifdef JAZZ16
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 #endif
297
298 static int
299 sb_mixer_set (int dev, int value)
300 {
301 int left = value & 0x000000ff;
302 int right = (value & 0x0000ff00) >> 8;
303
304 int regoffs;
305 unsigned char val;
306
307 #ifdef JAZZ16
308 if (Jazz16_detected == 2)
309 return smw_mixer_set (dev, value);
310 #endif
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, ioctl_arg arg)
449 {
450 if (((cmd >> 8) & 0xff) == 'M')
451 {
452 if (cmd & IOC_IN)
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 static 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 #ifdef JAZZ16
543 if (Jazz16_detected == 2)
544 {
545 supported_devices = 0;
546 supported_rec_devices = 0;
547 iomap = &sbpro_mix;
548 smw_mixer_init ();
549 mixer_type = 1;
550 }
551 else
552 #endif
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