ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / sound / oss / sb_mixer.c
1 /*
2  * sound/sb_mixer.c
3  *
4  * The low level mixer driver for the Sound Blaster compatible cards.
5  */
6 /*
7  * Copyright (C) by Hannu Savolainen 1993-1997
8  *
9  * OSS/Free for Linux is distributed under the GNU GENERAL PUBLIC LICENSE (GPL)
10  * Version 2 (June 1991). See the "COPYING" file distributed with this software
11  * for more info.
12  *
13  *
14  * Thomas Sailer                                : ioctl code reworked (vmalloc/vfree removed)
15  * Rolf Fokkens (Dec 20 1998)   : Moved ESS stuff into sb_ess.[ch]
16  * Stanislav Voronyi <stas@esc.kharkov.com>     : Support for AWE 3DSE device (Jun 7 1999)
17  */
18
19 #include "sound_config.h"
20
21 #define __SB_MIXER_C__
22
23 #include "sb.h"
24 #include "sb_mixer.h"
25
26 #include "sb_ess.h"
27
28 #define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
29
30 /* Same as SB Pro, unless I find otherwise */
31 #define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
32
33 #define SBPRO_MIXER_DEVICES             (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
34                                          SOUND_MASK_CD | SOUND_MASK_VOLUME)
35
36 /* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
37  * channel is the COVOX/DisneySoundSource emulation volume control
38  * on the mixer. It does NOT control speaker volume. Should have own
39  * mask eventually?
40  */
41 #define SGNXPRO_MIXER_DEVICES   (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
42                                  SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
43
44 #define SB16_RECORDING_DEVICES          (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
45                                          SOUND_MASK_CD)
46
47 #define SB16_OUTFILTER_DEVICES          (SOUND_MASK_LINE | SOUND_MASK_MIC | \
48                                          SOUND_MASK_CD)
49
50 #define SB16_MIXER_DEVICES              (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
51                                          SOUND_MASK_CD | \
52                                          SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
53                                          SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
54                                         SOUND_MASK_IMIX)
55
56 /* These are the only devices that are working at the moment.  Others could
57  * be added once they are identified and a method is found to control them.
58  */
59 #define ALS007_MIXER_DEVICES    (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
60                                  SOUND_MASK_PCM | SOUND_MASK_MIC | \
61                                  SOUND_MASK_CD | \
62                                  SOUND_MASK_VOLUME)
63
64 static mixer_tab sbpro_mix = {
65 MIX_ENT(SOUND_MIXER_VOLUME,     0x22, 7, 4, 0x22, 3, 4),
66 MIX_ENT(SOUND_MIXER_BASS,       0x00, 0, 0, 0x00, 0, 0),
67 MIX_ENT(SOUND_MIXER_TREBLE,     0x00, 0, 0, 0x00, 0, 0),
68 MIX_ENT(SOUND_MIXER_SYNTH,      0x26, 7, 4, 0x26, 3, 4),
69 MIX_ENT(SOUND_MIXER_PCM,        0x04, 7, 4, 0x04, 3, 4),
70 MIX_ENT(SOUND_MIXER_SPEAKER,    0x00, 0, 0, 0x00, 0, 0),
71 MIX_ENT(SOUND_MIXER_LINE,       0x2e, 7, 4, 0x2e, 3, 4),
72 MIX_ENT(SOUND_MIXER_MIC,        0x0a, 2, 3, 0x00, 0, 0),
73 MIX_ENT(SOUND_MIXER_CD,         0x28, 7, 4, 0x28, 3, 4),
74 MIX_ENT(SOUND_MIXER_IMIX,       0x00, 0, 0, 0x00, 0, 0),
75 MIX_ENT(SOUND_MIXER_ALTPCM,     0x00, 0, 0, 0x00, 0, 0),
76 MIX_ENT(SOUND_MIXER_RECLEV,     0x00, 0, 0, 0x00, 0, 0)
77 };
78
79 static mixer_tab sb16_mix = {
80 MIX_ENT(SOUND_MIXER_VOLUME,     0x30, 7, 5, 0x31, 7, 5),
81 MIX_ENT(SOUND_MIXER_BASS,       0x46, 7, 4, 0x47, 7, 4),
82 MIX_ENT(SOUND_MIXER_TREBLE,     0x44, 7, 4, 0x45, 7, 4),
83 MIX_ENT(SOUND_MIXER_SYNTH,      0x34, 7, 5, 0x35, 7, 5),
84 MIX_ENT(SOUND_MIXER_PCM,        0x32, 7, 5, 0x33, 7, 5),
85 MIX_ENT(SOUND_MIXER_SPEAKER,    0x3b, 7, 2, 0x00, 0, 0),
86 MIX_ENT(SOUND_MIXER_LINE,       0x38, 7, 5, 0x39, 7, 5),
87 MIX_ENT(SOUND_MIXER_MIC,        0x3a, 7, 5, 0x00, 0, 0),
88 MIX_ENT(SOUND_MIXER_CD,         0x36, 7, 5, 0x37, 7, 5),
89 MIX_ENT(SOUND_MIXER_IMIX,       0x3c, 0, 1, 0x00, 0, 0),
90 MIX_ENT(SOUND_MIXER_ALTPCM,     0x00, 0, 0, 0x00, 0, 0),
91 MIX_ENT(SOUND_MIXER_RECLEV,     0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
92 MIX_ENT(SOUND_MIXER_IGAIN,      0x3f, 7, 2, 0x40, 7, 2),
93 MIX_ENT(SOUND_MIXER_OGAIN,      0x41, 7, 2, 0x42, 7, 2)
94 };
95
96 static mixer_tab als007_mix = 
97 {
98 MIX_ENT(SOUND_MIXER_VOLUME,     0x62, 7, 4, 0x62, 3, 4),
99 MIX_ENT(SOUND_MIXER_BASS,       0x00, 0, 0, 0x00, 0, 0),
100 MIX_ENT(SOUND_MIXER_TREBLE,     0x00, 0, 0, 0x00, 0, 0),
101 MIX_ENT(SOUND_MIXER_SYNTH,      0x66, 7, 4, 0x66, 3, 4),
102 MIX_ENT(SOUND_MIXER_PCM,        0x64, 7, 4, 0x64, 3, 4),
103 MIX_ENT(SOUND_MIXER_SPEAKER,    0x00, 0, 0, 0x00, 0, 0),
104 MIX_ENT(SOUND_MIXER_LINE,       0x6e, 7, 4, 0x6e, 3, 4),
105 MIX_ENT(SOUND_MIXER_MIC,        0x6a, 2, 3, 0x00, 0, 0),
106 MIX_ENT(SOUND_MIXER_CD,         0x68, 7, 4, 0x68, 3, 4),
107 MIX_ENT(SOUND_MIXER_IMIX,       0x00, 0, 0, 0x00, 0, 0),
108 MIX_ENT(SOUND_MIXER_ALTPCM,     0x00, 0, 0, 0x00, 0, 0),
109 MIX_ENT(SOUND_MIXER_RECLEV,     0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
110 MIX_ENT(SOUND_MIXER_IGAIN,      0x00, 0, 0, 0x00, 0, 0),
111 MIX_ENT(SOUND_MIXER_OGAIN,      0x00, 0, 0, 0x00, 0, 0)
112 };
113
114
115 /* SM_GAMES          Master volume is lower and PCM & FM volumes
116                              higher than with SB Pro. This improves the
117                              sound quality */
118
119 static int smg_default_levels[32] =
120 {
121   0x2020,                       /* Master Volume */
122   0x4b4b,                       /* Bass */
123   0x4b4b,                       /* Treble */
124   0x6464,                       /* FM */
125   0x6464,                       /* PCM */
126   0x4b4b,                       /* PC Speaker */
127   0x4b4b,                       /* Ext Line */
128   0x0000,                       /* Mic */
129   0x4b4b,                       /* CD */
130   0x4b4b,                       /* Recording monitor */
131   0x4b4b,                       /* SB PCM */
132   0x4b4b,                       /* Recording level */
133   0x4b4b,                       /* Input gain */
134   0x4b4b,                       /* Output gain */
135   0x4040,                       /* Line1 */
136   0x4040,                       /* Line2 */
137   0x1515                        /* Line3 */
138 };
139
140 static int sb_default_levels[32] =
141 {
142   0x5a5a,                       /* Master Volume */
143   0x4b4b,                       /* Bass */
144   0x4b4b,                       /* Treble */
145   0x4b4b,                       /* FM */
146   0x4b4b,                       /* PCM */
147   0x4b4b,                       /* PC Speaker */
148   0x4b4b,                       /* Ext Line */
149   0x1010,                       /* Mic */
150   0x4b4b,                       /* CD */
151   0x0000,                       /* Recording monitor */
152   0x4b4b,                       /* SB PCM */
153   0x4b4b,                       /* Recording level */
154   0x4b4b,                       /* Input gain */
155   0x4b4b,                       /* Output gain */
156   0x4040,                       /* Line1 */
157   0x4040,                       /* Line2 */
158   0x1515                        /* Line3 */
159 };
160
161 static unsigned char sb16_recmasks_L[SOUND_MIXER_NRDEVICES] =
162 {
163         0x00,   /* SOUND_MIXER_VOLUME   */
164         0x00,   /* SOUND_MIXER_BASS     */
165         0x00,   /* SOUND_MIXER_TREBLE   */
166         0x40,   /* SOUND_MIXER_SYNTH    */
167         0x00,   /* SOUND_MIXER_PCM      */
168         0x00,   /* SOUND_MIXER_SPEAKER  */
169         0x10,   /* SOUND_MIXER_LINE     */
170         0x01,   /* SOUND_MIXER_MIC      */
171         0x04,   /* SOUND_MIXER_CD       */
172         0x00,   /* SOUND_MIXER_IMIX     */
173         0x00,   /* SOUND_MIXER_ALTPCM   */
174         0x00,   /* SOUND_MIXER_RECLEV   */
175         0x00,   /* SOUND_MIXER_IGAIN    */
176         0x00    /* SOUND_MIXER_OGAIN    */
177 };
178
179 static unsigned char sb16_recmasks_R[SOUND_MIXER_NRDEVICES] =
180 {
181         0x00,   /* SOUND_MIXER_VOLUME   */
182         0x00,   /* SOUND_MIXER_BASS     */
183         0x00,   /* SOUND_MIXER_TREBLE   */
184         0x20,   /* SOUND_MIXER_SYNTH    */
185         0x00,   /* SOUND_MIXER_PCM      */
186         0x00,   /* SOUND_MIXER_SPEAKER  */
187         0x08,   /* SOUND_MIXER_LINE     */
188         0x01,   /* SOUND_MIXER_MIC      */
189         0x02,   /* SOUND_MIXER_CD       */
190         0x00,   /* SOUND_MIXER_IMIX     */
191         0x00,   /* SOUND_MIXER_ALTPCM   */
192         0x00,   /* SOUND_MIXER_RECLEV   */
193         0x00,   /* SOUND_MIXER_IGAIN    */
194         0x00    /* SOUND_MIXER_OGAIN    */
195 };
196
197 static char     smw_mix_regs[] =        /* Left mixer registers */
198 {
199   0x0b,                         /* SOUND_MIXER_VOLUME */
200   0x0d,                         /* SOUND_MIXER_BASS */
201   0x0d,                         /* SOUND_MIXER_TREBLE */
202   0x05,                         /* SOUND_MIXER_SYNTH */
203   0x09,                         /* SOUND_MIXER_PCM */
204   0x00,                         /* SOUND_MIXER_SPEAKER */
205   0x03,                         /* SOUND_MIXER_LINE */
206   0x01,                         /* SOUND_MIXER_MIC */
207   0x07,                         /* SOUND_MIXER_CD */
208   0x00,                         /* SOUND_MIXER_IMIX */
209   0x00,                         /* SOUND_MIXER_ALTPCM */
210   0x00,                         /* SOUND_MIXER_RECLEV */
211   0x00,                         /* SOUND_MIXER_IGAIN */
212   0x00,                         /* SOUND_MIXER_OGAIN */
213   0x00,                         /* SOUND_MIXER_LINE1 */
214   0x00,                         /* SOUND_MIXER_LINE2 */
215   0x00                          /* SOUND_MIXER_LINE3 */
216 };
217
218 static int      sbmixnum = 1;
219
220 static void     sb_mixer_reset(sb_devc * devc);
221
222 void sb_mixer_set_stereo(sb_devc * devc, int mode)
223 {
224         sb_chgmixer(devc, OUT_FILTER, STEREO_DAC, (mode ? STEREO_DAC : MONO_DAC));
225 }
226
227 static int detect_mixer(sb_devc * devc)
228 {
229         /* Just trust the mixer is there */
230         return 1;
231 }
232
233 static void change_bits(sb_devc * devc, unsigned char *regval, int dev, int chn, int newval)
234 {
235         unsigned char mask;
236         int shift;
237
238         mask = (1 << (*devc->iomap)[dev][chn].nbits) - 1;
239         newval = (int) ((newval * mask) + 50) / 100;    /* Scale */
240
241         shift = (*devc->iomap)[dev][chn].bitoffs - (*devc->iomap)[dev][LEFT_CHN].nbits + 1;
242
243         *regval &= ~(mask << shift);    /* Mask out previous value */
244         *regval |= (newval & mask) << shift;    /* Set the new value */
245 }
246
247 static int sb_mixer_get(sb_devc * devc, int dev)
248 {
249         if (!((1 << dev) & devc->supported_devices))
250                 return -EINVAL;
251         return devc->levels[dev];
252 }
253
254 void smw_mixer_init(sb_devc * devc)
255 {
256         int i;
257
258         sb_setmixer(devc, 0x00, 0x18);  /* Mute unused (Telephone) line */
259         sb_setmixer(devc, 0x10, 0x38);  /* Config register 2 */
260
261         devc->supported_devices = 0;
262         for (i = 0; i < sizeof(smw_mix_regs); i++)
263                 if (smw_mix_regs[i] != 0)
264                         devc->supported_devices |= (1 << i);
265
266         devc->supported_rec_devices = devc->supported_devices &
267                 ~(SOUND_MASK_BASS | SOUND_MASK_TREBLE | SOUND_MASK_PCM | SOUND_MASK_VOLUME);
268         sb_mixer_reset(devc);
269 }
270
271 int sb_common_mixer_set(sb_devc * devc, int dev, int left, int right)
272 {
273         int regoffs;
274         unsigned char val;
275
276         regoffs = (*devc->iomap)[dev][LEFT_CHN].regno;
277
278         if (regoffs == 0)
279                 return -EINVAL;
280
281         if ((dev < 0) || (dev >= devc->iomap_sz))
282             return -EINVAL;
283
284         val = sb_getmixer(devc, regoffs);
285         change_bits(devc, &val, dev, LEFT_CHN, left);
286
287         if ((*devc->iomap)[dev][RIGHT_CHN].regno != regoffs)    /*
288                                                                  * Change register
289                                                                  */
290         {
291                 sb_setmixer(devc, regoffs, val);        /*
292                                                          * Save the old one
293                                                          */
294                 regoffs = (*devc->iomap)[dev][RIGHT_CHN].regno;
295
296                 if (regoffs == 0)
297                         return left | (left << 8);      /*
298                                                          * Just left channel present
299                                                          */
300
301                 val = sb_getmixer(devc, regoffs);       /*
302                                                          * Read the new one
303                                                          */
304         }
305         change_bits(devc, &val, dev, RIGHT_CHN, right);
306
307         sb_setmixer(devc, regoffs, val);
308
309         return left | (right << 8);
310 }
311
312 static int smw_mixer_set(sb_devc * devc, int dev, int left, int right)
313 {
314         int reg, val;
315
316         switch (dev)
317         {
318                 case SOUND_MIXER_VOLUME:
319                         sb_setmixer(devc, 0x0b, 96 - (96 * left / 100));        /* 96=mute, 0=max */
320                         sb_setmixer(devc, 0x0c, 96 - (96 * right / 100));
321                         break;
322
323                 case SOUND_MIXER_BASS:
324                 case SOUND_MIXER_TREBLE:
325                         devc->levels[dev] = left | (right << 8);
326                         /* Set left bass and treble values */
327                         val = ((devc->levels[SOUND_MIXER_TREBLE] & 0xff) * 16 / (unsigned) 100) << 4;
328                         val |= ((devc->levels[SOUND_MIXER_BASS] & 0xff) * 16 / (unsigned) 100) & 0x0f;
329                         sb_setmixer(devc, 0x0d, val);
330
331                         /* Set right bass and treble values */
332                         val = (((devc->levels[SOUND_MIXER_TREBLE] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
333                         val |= (((devc->levels[SOUND_MIXER_BASS] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
334                         sb_setmixer(devc, 0x0e, val);
335                 
336                         break;
337
338                 default:
339                         /* bounds check */
340                         if (dev < 0 || dev >= ARRAY_SIZE(smw_mix_regs))
341                                 return -EINVAL;
342                         reg = smw_mix_regs[dev];
343                         if (reg == 0)
344                                 return -EINVAL;
345                         sb_setmixer(devc, reg, (24 - (24 * left / 100)) | 0x20);        /* 24=mute, 0=max */
346                         sb_setmixer(devc, reg + 1, (24 - (24 * right / 100)) | 0x40);
347         }
348
349         devc->levels[dev] = left | (right << 8);
350         return left | (right << 8);
351 }
352
353 static int sb_mixer_set(sb_devc * devc, int dev, int value)
354 {
355         int left = value & 0x000000ff;
356         int right = (value & 0x0000ff00) >> 8;
357         int retval;
358
359         if (left > 100)
360                 left = 100;
361         if (right > 100)
362                 right = 100;
363
364         if ((dev < 0) || (dev > 31))
365                 return -EINVAL;
366
367         if (!(devc->supported_devices & (1 << dev)))    /*
368                                                          * Not supported
369                                                          */
370                 return -EINVAL;
371
372         /* Differentiate depending on the chipsets */
373         switch (devc->model) {
374         case MDL_SMW:
375                 retval = smw_mixer_set(devc, dev, left, right);
376                 break;
377         case MDL_ESS:
378                 retval = ess_mixer_set(devc, dev, left, right);
379                 break;
380         default:
381                 retval = sb_common_mixer_set(devc, dev, left, right);
382         }
383         if (retval >= 0) devc->levels[dev] = retval;
384
385         return retval;
386 }
387
388 /*
389  * set_recsrc doesn't apply to ES188x
390  */
391 static void set_recsrc(sb_devc * devc, int src)
392 {
393         sb_setmixer(devc, RECORD_SRC, (sb_getmixer(devc, RECORD_SRC) & ~7) | (src & 0x7));
394 }
395
396 static int set_recmask(sb_devc * devc, int mask)
397 {
398         int devmask, i;
399         unsigned char  regimageL, regimageR;
400
401         devmask = mask & devc->supported_rec_devices;
402
403         switch (devc->model)
404         {
405                 case MDL_SBPRO:
406                 case MDL_ESS:
407                 case MDL_JAZZ:
408                 case MDL_SMW:
409                         if (devc->model == MDL_ESS && ess_set_recmask (devc, &devmask)) {
410                                 break;
411                         };
412                         if (devmask != SOUND_MASK_MIC &&
413                                 devmask != SOUND_MASK_LINE &&
414                                 devmask != SOUND_MASK_CD)
415                         {
416                                 /*
417                                  * More than one device selected. Drop the
418                                  * previous selection
419                                  */
420                                 devmask &= ~devc->recmask;
421                         }
422                         if (devmask != SOUND_MASK_MIC &&
423                                 devmask != SOUND_MASK_LINE &&
424                                 devmask != SOUND_MASK_CD)
425                         {
426                                 /*
427                                  * More than one device selected. Default to
428                                  * mic
429                                  */
430                                 devmask = SOUND_MASK_MIC;
431                         }
432                         if (devmask ^ devc->recmask)    /*
433                                                          *      Input source changed
434                                                          */
435                         {
436                                 switch (devmask)
437                                 {
438                                         case SOUND_MASK_MIC:
439                                                 set_recsrc(devc, SRC__MIC);
440                                                 break;
441
442                                         case SOUND_MASK_LINE:
443                                                 set_recsrc(devc, SRC__LINE);
444                                                 break;
445
446                                         case SOUND_MASK_CD:
447                                                 set_recsrc(devc, SRC__CD);
448                                                 break;
449
450                                         default:
451                                                 set_recsrc(devc, SRC__MIC);
452                                 }
453                         }
454                         break;
455
456                 case MDL_SB16:
457                         if (!devmask)
458                                 devmask = SOUND_MASK_MIC;
459
460                         if (devc->submodel == SUBMDL_ALS007) 
461                         {
462                                 switch (devmask) 
463                                 {
464                                         case SOUND_MASK_LINE:
465                                                 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_LINE);
466                                                 break;
467                                         case SOUND_MASK_CD:
468                                                 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_CD);
469                                                 break;
470                                         case SOUND_MASK_SYNTH:
471                                                 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_SYNTH);
472                                                 break;
473                                         default:           /* Also takes care of SOUND_MASK_MIC case */
474                                                 sb_setmixer(devc, ALS007_RECORD_SRC, ALS007_MIC);
475                                                 break;
476                                 }
477                         }
478                         else
479                         {
480                                 regimageL = regimageR = 0;
481                                 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
482                                 {
483                                         if ((1 << i) & devmask)
484                                         {
485                                                 regimageL |= sb16_recmasks_L[i];
486                                                 regimageR |= sb16_recmasks_R[i];
487                                         }
488                                         sb_setmixer (devc, SB16_IMASK_L, regimageL);
489                                         sb_setmixer (devc, SB16_IMASK_R, regimageR);
490                                 }
491                         }
492                         break;
493         }
494         devc->recmask = devmask;
495         return devc->recmask;
496 }
497
498 static int set_outmask(sb_devc * devc, int mask)
499 {
500         int devmask, i;
501         unsigned char  regimage;
502
503         devmask = mask & devc->supported_out_devices;
504
505         switch (devc->model)
506         {
507                 case MDL_SB16:
508                         if (devc->submodel == SUBMDL_ALS007) 
509                                 break;
510                         else
511                         {
512                                 regimage = 0;
513                                 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
514                                 {
515                                         if ((1 << i) & devmask)
516                                         {
517                                                 regimage |= (sb16_recmasks_L[i] | sb16_recmasks_R[i]);
518                                         }
519                                         sb_setmixer (devc, SB16_OMASK, regimage);
520                                 }
521                         }
522                         break;
523                 default:
524                         break;
525         }
526
527         devc->outmask = devmask;
528         return devc->outmask;
529 }
530
531 static int sb_mixer_ioctl(int dev, unsigned int cmd, caddr_t arg)
532 {
533         sb_devc *devc = mixer_devs[dev]->devc;
534         int val, ret;
535
536         /*
537          * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1).
538          * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1)
539          *                                            or mode==2 put 3DSE state to mode.
540          */
541         if (devc->model == MDL_SB16) {
542                 if (cmd == SOUND_MIXER_AGC) 
543                 {
544                         if (get_user(val, (int *)arg))
545                                 return -EFAULT;
546                         sb_setmixer(devc, 0x43, (~val) & 0x01);
547                         return 0;
548                 }
549                 if (cmd == SOUND_MIXER_3DSE) 
550                 {
551                         /* I put here 15, but I don't know the exact version.
552                            At least my 4.13 havn't 3DSE, 4.16 has it. */
553                         if (devc->minor < 15)
554                                 return -EINVAL;
555                         if (get_user(val, (int *)arg))
556                                 return -EFAULT;
557                         if (val == 0 || val == 1)
558                                 sb_chgmixer(devc, AWE_3DSE, 0x01, val);
559                         else if (val == 2)
560                         {
561                                 ret = sb_getmixer(devc, AWE_3DSE)&0x01;
562                                 return put_user(ret, (int *)arg);
563                         }
564                         else
565                                 return -EINVAL;
566                         return 0;
567                 }
568         }
569         if (((cmd >> 8) & 0xff) == 'M') 
570         {
571                 if (_SIOC_DIR(cmd) & _SIOC_WRITE) 
572                 {
573                         if (get_user(val, (int *)arg))
574                                 return -EFAULT;
575                         switch (cmd & 0xff) 
576                         {
577                                 case SOUND_MIXER_RECSRC:
578                                         ret = set_recmask(devc, val);
579                                         break;
580
581                                 case SOUND_MIXER_OUTSRC:
582                                         ret = set_outmask(devc, val);
583                                         break;
584
585                                 default:
586                                         ret = sb_mixer_set(devc, cmd & 0xff, val);
587                         }
588                 }
589                 else switch (cmd & 0xff) 
590                 {
591                         case SOUND_MIXER_RECSRC:
592                                 ret = devc->recmask;
593                                 break;
594                                   
595                         case SOUND_MIXER_OUTSRC:
596                                 ret = devc->outmask;
597                                 break;
598                                   
599                         case SOUND_MIXER_DEVMASK:
600                                 ret = devc->supported_devices;
601                                 break;
602                                   
603                         case SOUND_MIXER_STEREODEVS:
604                                 ret = devc->supported_devices;
605                                 /* The ESS seems to have stereo mic controls */
606                                 if (devc->model == MDL_ESS)
607                                         ret &= ~(SOUND_MASK_SPEAKER|SOUND_MASK_IMIX);
608                                 else if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
609                                         ret &= ~(SOUND_MASK_MIC | SOUND_MASK_SPEAKER | SOUND_MASK_IMIX);
610                                 break;
611                                   
612                         case SOUND_MIXER_RECMASK:
613                                 ret = devc->supported_rec_devices;
614                                 break;
615                                   
616                         case SOUND_MIXER_OUTMASK:
617                                 ret = devc->supported_out_devices;
618                                 break;
619                                   
620                         case SOUND_MIXER_CAPS:
621                                 ret = devc->mixer_caps;
622                                 break;
623                                     
624                         default:
625                                 ret = sb_mixer_get(devc, cmd & 0xff);
626                                 break;
627                 }
628                 return put_user(ret, (int *)arg); 
629         } else
630                 return -EINVAL;
631 }
632
633 static struct mixer_operations sb_mixer_operations =
634 {
635         .owner  = THIS_MODULE,
636         .id     = "SB",
637         .name   = "Sound Blaster",
638         .ioctl  = sb_mixer_ioctl
639 };
640
641 static struct mixer_operations als007_mixer_operations =
642 {
643         .owner  = THIS_MODULE,
644         .id     = "ALS007",
645         .name   = "Avance ALS-007",
646         .ioctl  = sb_mixer_ioctl
647 };
648
649 static void sb_mixer_reset(sb_devc * devc)
650 {
651         char name[32];
652         int i;
653
654         sprintf(name, "SB_%d", devc->sbmixnum);
655
656         if (devc->sbmo.sm_games)
657                 devc->levels = load_mixer_volumes(name, smg_default_levels, 1);
658         else
659                 devc->levels = load_mixer_volumes(name, sb_default_levels, 1);
660
661         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
662                 sb_mixer_set(devc, i, devc->levels[i]);
663
664         if (devc->model != MDL_ESS || !ess_mixer_reset (devc)) {
665                 set_recmask(devc, SOUND_MASK_MIC);
666         };
667 }
668
669 int sb_mixer_init(sb_devc * devc, struct module *owner)
670 {
671         int mixer_type = 0;
672         int m;
673
674         devc->sbmixnum = sbmixnum++;
675         devc->levels = NULL;
676
677         sb_setmixer(devc, 0x00, 0);     /* Reset mixer */
678
679         if (!(mixer_type = detect_mixer(devc)))
680                 return 0;       /* No mixer. Why? */
681
682         switch (devc->model)
683         {
684                 case MDL_ESSPCI:
685                 case MDL_YMPCI:
686                 case MDL_SBPRO:
687                 case MDL_AZTECH:
688                 case MDL_JAZZ:
689                         devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
690                         devc->supported_devices = SBPRO_MIXER_DEVICES;
691                         devc->supported_rec_devices = SBPRO_RECORDING_DEVICES;
692                         devc->iomap = &sbpro_mix;
693                         devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
694                         break;
695
696                 case MDL_ESS:
697                         ess_mixer_init (devc);
698                         break;
699
700                 case MDL_SMW:
701                         devc->mixer_caps = SOUND_CAP_EXCL_INPUT;
702                         devc->supported_devices = 0;
703                         devc->supported_rec_devices = 0;
704                         devc->iomap = &sbpro_mix;
705                         devc->iomap_sz = ARRAY_SIZE(sbpro_mix);
706                         smw_mixer_init(devc);
707                         break;
708
709                 case MDL_SB16:
710                         devc->mixer_caps = 0;
711                         devc->supported_rec_devices = SB16_RECORDING_DEVICES;
712                         devc->supported_out_devices = SB16_OUTFILTER_DEVICES;
713                         if (devc->submodel != SUBMDL_ALS007)
714                         {
715                                 devc->supported_devices = SB16_MIXER_DEVICES;
716                                 devc->iomap = &sb16_mix;
717                                 devc->iomap_sz = ARRAY_SIZE(sb16_mix);
718                         }
719                         else
720                         {
721                                 devc->supported_devices = ALS007_MIXER_DEVICES;
722                                 devc->iomap = &als007_mix;
723                                 devc->iomap_sz = ARRAY_SIZE(als007_mix);
724                         }
725                         break;
726
727                 default:
728                         printk(KERN_WARNING "sb_mixer: Unsupported mixer type %d\n", devc->model);
729                         return 0;
730         }
731
732         m = sound_alloc_mixerdev();
733         if (m == -1)
734                 return 0;
735
736         mixer_devs[m] = (struct mixer_operations *)kmalloc(sizeof(struct mixer_operations), GFP_KERNEL);
737         if (mixer_devs[m] == NULL)
738         {
739                 printk(KERN_ERR "sb_mixer: Can't allocate memory\n");
740                 sound_unload_mixerdev(m);
741                 return 0;
742         }
743
744         if (devc->submodel != SUBMDL_ALS007)
745                 memcpy ((char *) mixer_devs[m], (char *) &sb_mixer_operations, sizeof (struct mixer_operations));
746         else
747                 memcpy ((char *) mixer_devs[m], (char *) &als007_mixer_operations, sizeof (struct mixer_operations));
748
749         mixer_devs[m]->devc = devc;
750
751         if (owner)
752                          mixer_devs[m]->owner = owner;
753         
754         devc->my_mixerdev = m;
755         sb_mixer_reset(devc);
756         return 1;
757 }
758
759 void sb_mixer_unload(sb_devc *devc)
760 {
761         if (devc->my_mixerdev == -1)
762                 return;
763
764         kfree(mixer_devs[devc->my_mixerdev]);
765         sound_unload_mixerdev(devc->my_mixerdev);
766         sbmixnum--;
767 }