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