Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
sb_mixer.c
Go to the documentation of this file.
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 <[email protected]> : 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 
225 {
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 
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 
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:
468  break;
469  case SOUND_MASK_CD:
471  break;
472  case SOUND_MASK_SYNTH:
474  break;
475  default: /* Also takes care of SOUND_MASK_MIC case */
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 
607  ret = devc->supported_devices;
608  /* The ESS seems to have stereo mic controls */
609  if (devc->model == MDL_ESS)
611  else if (devc->model != MDL_JAZZ && devc->model != MDL_SMW)
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:
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:
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;
716  if (devc->submodel != SUBMDL_ALS007)
717  {
719  devc->iomap = &sb16_mix;
720  devc->iomap_sz = ARRAY_SIZE(sb16_mix);
721  }
722  else
723  {
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");
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 
763 {
764  if (devc->my_mixerdev == -1)
765  return;
766 
767  kfree(mixer_devs[devc->my_mixerdev]);
769  sbmixnum--;
770 }