4 * The low level mixer driver for the Sound Blaster compatible cards.
7 * Copyright (C) by Hannu Savolainen 1993-1997
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
14 * Thomas Sailer : ioctl code reworked (vmalloc/vfree removed)
15 * Rolf Fokkens (Dec 20 1998) : Moved ESS stuff into sb_ess.[ch]
18 #include <linux/config.h>
19 #include "sound_config.h"
22 #define __SB_MIXER_C__
29 #define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
31 /* Same as SB Pro, unless I find otherwise */
32 #define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
34 #define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
35 SOUND_MASK_CD | SOUND_MASK_VOLUME)
37 /* SG NX Pro has treble and bass settings on the mixer. The 'speaker'
38 * channel is the COVOX/DisneySoundSource emulation volume control
39 * on the mixer. It does NOT control speaker volume. Should have own
42 #define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
43 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
45 #define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
48 #define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
51 #define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
53 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
54 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
57 /* These are the only devices that are working at the moment. Others could
58 * be added once they are identified and a method is found to control them.
60 #define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
61 SOUND_MASK_PCM | SOUND_MASK_MIC | \
65 static mixer_tab sbpro_mix
= {
66 MIX_ENT(SOUND_MIXER_VOLUME
, 0x22, 7, 4, 0x22, 3, 4),
67 MIX_ENT(SOUND_MIXER_BASS
, 0x00, 0, 0, 0x00, 0, 0),
68 MIX_ENT(SOUND_MIXER_TREBLE
, 0x00, 0, 0, 0x00, 0, 0),
69 MIX_ENT(SOUND_MIXER_SYNTH
, 0x26, 7, 4, 0x26, 3, 4),
70 MIX_ENT(SOUND_MIXER_PCM
, 0x04, 7, 4, 0x04, 3, 4),
71 MIX_ENT(SOUND_MIXER_SPEAKER
, 0x00, 0, 0, 0x00, 0, 0),
72 MIX_ENT(SOUND_MIXER_LINE
, 0x2e, 7, 4, 0x2e, 3, 4),
73 MIX_ENT(SOUND_MIXER_MIC
, 0x0a, 2, 3, 0x00, 0, 0),
74 MIX_ENT(SOUND_MIXER_CD
, 0x28, 7, 4, 0x28, 3, 4),
75 MIX_ENT(SOUND_MIXER_IMIX
, 0x00, 0, 0, 0x00, 0, 0),
76 MIX_ENT(SOUND_MIXER_ALTPCM
, 0x00, 0, 0, 0x00, 0, 0),
77 MIX_ENT(SOUND_MIXER_RECLEV
, 0x00, 0, 0, 0x00, 0, 0)
82 static mixer_tab sgnxpro_mix
= { /* not used anywhere */
83 MIX_ENT(SOUND_MIXER_VOLUME
, 0x22, 7, 4, 0x22, 3, 4),
84 MIX_ENT(SOUND_MIXER_BASS
, 0x46, 2, 3, 0x00, 0, 0),
85 MIX_ENT(SOUND_MIXER_TREBLE
, 0x44, 2, 3, 0x00, 0, 0),
86 MIX_ENT(SOUND_MIXER_SYNTH
, 0x26, 7, 4, 0x26, 3, 4),
87 MIX_ENT(SOUND_MIXER_PCM
, 0x04, 7, 4, 0x04, 3, 4),
88 MIX_ENT(SOUND_MIXER_SPEAKER
, 0x42, 2, 3, 0x00, 0, 0),
89 MIX_ENT(SOUND_MIXER_LINE
, 0x2e, 7, 4, 0x2e, 3, 4),
90 MIX_ENT(SOUND_MIXER_MIC
, 0x0a, 2, 3, 0x00, 0, 0),
91 MIX_ENT(SOUND_MIXER_CD
, 0x28, 7, 4, 0x28, 3, 4),
92 MIX_ENT(SOUND_MIXER_IMIX
, 0x00, 0, 0, 0x00, 0, 0),
93 MIX_ENT(SOUND_MIXER_ALTPCM
, 0x00, 0, 0, 0x00, 0, 0),
94 MIX_ENT(SOUND_MIXER_RECLEV
, 0x00, 0, 0, 0x00, 0, 0),
95 MIX_ENT(SOUND_MIXER_IGAIN
, 0x00, 0, 0, 0x00, 0, 0),
96 MIX_ENT(SOUND_MIXER_OGAIN
, 0x00, 0, 0, 0x00, 0, 0)
101 static mixer_tab sb16_mix
= {
102 MIX_ENT(SOUND_MIXER_VOLUME
, 0x30, 7, 5, 0x31, 7, 5),
103 MIX_ENT(SOUND_MIXER_BASS
, 0x46, 7, 4, 0x47, 7, 4),
104 MIX_ENT(SOUND_MIXER_TREBLE
, 0x44, 7, 4, 0x45, 7, 4),
105 MIX_ENT(SOUND_MIXER_SYNTH
, 0x34, 7, 5, 0x35, 7, 5),
106 MIX_ENT(SOUND_MIXER_PCM
, 0x32, 7, 5, 0x33, 7, 5),
107 MIX_ENT(SOUND_MIXER_SPEAKER
, 0x3b, 7, 2, 0x00, 0, 0),
108 MIX_ENT(SOUND_MIXER_LINE
, 0x38, 7, 5, 0x39, 7, 5),
109 MIX_ENT(SOUND_MIXER_MIC
, 0x3a, 7, 5, 0x00, 0, 0),
110 MIX_ENT(SOUND_MIXER_CD
, 0x36, 7, 5, 0x37, 7, 5),
111 MIX_ENT(SOUND_MIXER_IMIX
, 0x3c, 0, 1, 0x00, 0, 0),
112 MIX_ENT(SOUND_MIXER_ALTPCM
, 0x00, 0, 0, 0x00, 0, 0),
113 MIX_ENT(SOUND_MIXER_RECLEV
, 0x3f, 7, 2, 0x40, 7, 2), /* Obsolete. Use IGAIN */
114 MIX_ENT(SOUND_MIXER_IGAIN
, 0x3f, 7, 2, 0x40, 7, 2),
115 MIX_ENT(SOUND_MIXER_OGAIN
, 0x41, 7, 2, 0x42, 7, 2)
118 static mixer_tab als007_mix
=
120 MIX_ENT(SOUND_MIXER_VOLUME
, 0x62, 7, 4, 0x62, 3, 4),
121 MIX_ENT(SOUND_MIXER_BASS
, 0x00, 0, 0, 0x00, 0, 0),
122 MIX_ENT(SOUND_MIXER_TREBLE
, 0x00, 0, 0, 0x00, 0, 0),
123 MIX_ENT(SOUND_MIXER_SYNTH
, 0x66, 7, 4, 0x66, 3, 4),
124 MIX_ENT(SOUND_MIXER_PCM
, 0x64, 7, 4, 0x64, 3, 4),
125 MIX_ENT(SOUND_MIXER_SPEAKER
, 0x00, 0, 0, 0x00, 0, 0),
126 MIX_ENT(SOUND_MIXER_LINE
, 0x6e, 7, 4, 0x6e, 3, 4),
127 MIX_ENT(SOUND_MIXER_MIC
, 0x6a, 2, 3, 0x00, 0, 0),
128 MIX_ENT(SOUND_MIXER_CD
, 0x68, 7, 4, 0x68, 3, 4),
129 MIX_ENT(SOUND_MIXER_IMIX
, 0x00, 0, 0, 0x00, 0, 0),
130 MIX_ENT(SOUND_MIXER_ALTPCM
, 0x00, 0, 0, 0x00, 0, 0),
131 MIX_ENT(SOUND_MIXER_RECLEV
, 0x00, 0, 0, 0x00, 0, 0), /* Obsolete. Use IGAIN */
132 MIX_ENT(SOUND_MIXER_IGAIN
, 0x00, 0, 0, 0x00, 0, 0),
133 MIX_ENT(SOUND_MIXER_OGAIN
, 0x00, 0, 0, 0x00, 0, 0)
137 /* SM_GAMES Master volume is lower and PCM & FM volumes
138 higher than with SB Pro. This improves the
141 static int smg_default_levels
[32] =
143 0x2020, /* Master Volume */
148 0x4b4b, /* PC Speaker */
149 0x4b4b, /* Ext Line */
152 0x4b4b, /* Recording monitor */
154 0x4b4b, /* Recording level */
155 0x4b4b, /* Input gain */
156 0x4b4b, /* Output gain */
162 static int sb_default_levels
[32] =
164 0x5a5a, /* Master Volume */
169 0x4b4b, /* PC Speaker */
170 0x4b4b, /* Ext Line */
173 0x0000, /* Recording monitor */
175 0x4b4b, /* Recording level */
176 0x4b4b, /* Input gain */
177 0x4b4b, /* Output gain */
183 static unsigned char sb16_recmasks_L
[SOUND_MIXER_NRDEVICES
] =
185 0x00, /* SOUND_MIXER_VOLUME */
186 0x00, /* SOUND_MIXER_BASS */
187 0x00, /* SOUND_MIXER_TREBLE */
188 0x40, /* SOUND_MIXER_SYNTH */
189 0x00, /* SOUND_MIXER_PCM */
190 0x00, /* SOUND_MIXER_SPEAKER */
191 0x10, /* SOUND_MIXER_LINE */
192 0x01, /* SOUND_MIXER_MIC */
193 0x04, /* SOUND_MIXER_CD */
194 0x00, /* SOUND_MIXER_IMIX */
195 0x00, /* SOUND_MIXER_ALTPCM */
196 0x00, /* SOUND_MIXER_RECLEV */
197 0x00, /* SOUND_MIXER_IGAIN */
198 0x00 /* SOUND_MIXER_OGAIN */
201 static unsigned char sb16_recmasks_R
[SOUND_MIXER_NRDEVICES
] =
203 0x00, /* SOUND_MIXER_VOLUME */
204 0x00, /* SOUND_MIXER_BASS */
205 0x00, /* SOUND_MIXER_TREBLE */
206 0x20, /* SOUND_MIXER_SYNTH */
207 0x00, /* SOUND_MIXER_PCM */
208 0x00, /* SOUND_MIXER_SPEAKER */
209 0x08, /* SOUND_MIXER_LINE */
210 0x01, /* SOUND_MIXER_MIC */
211 0x02, /* SOUND_MIXER_CD */
212 0x00, /* SOUND_MIXER_IMIX */
213 0x00, /* SOUND_MIXER_ALTPCM */
214 0x00, /* SOUND_MIXER_RECLEV */
215 0x00, /* SOUND_MIXER_IGAIN */
216 0x00 /* SOUND_MIXER_OGAIN */
219 static char smw_mix_regs
[] = /* Left mixer registers */
221 0x0b, /* SOUND_MIXER_VOLUME */
222 0x0d, /* SOUND_MIXER_BASS */
223 0x0d, /* SOUND_MIXER_TREBLE */
224 0x05, /* SOUND_MIXER_SYNTH */
225 0x09, /* SOUND_MIXER_PCM */
226 0x00, /* SOUND_MIXER_SPEAKER */
227 0x03, /* SOUND_MIXER_LINE */
228 0x01, /* SOUND_MIXER_MIC */
229 0x07, /* SOUND_MIXER_CD */
230 0x00, /* SOUND_MIXER_IMIX */
231 0x00, /* SOUND_MIXER_ALTPCM */
232 0x00, /* SOUND_MIXER_RECLEV */
233 0x00, /* SOUND_MIXER_IGAIN */
234 0x00, /* SOUND_MIXER_OGAIN */
235 0x00, /* SOUND_MIXER_LINE1 */
236 0x00, /* SOUND_MIXER_LINE2 */
237 0x00 /* SOUND_MIXER_LINE3 */
240 static int sbmixnum
= 1;
242 static void sb_mixer_reset(sb_devc
* devc
);
244 void sb_mixer_set_stereo(sb_devc
* devc
, int mode
)
246 sb_chgmixer(devc
, OUT_FILTER
, STEREO_DAC
, (mode
? STEREO_DAC
: MONO_DAC
));
249 static int detect_mixer(sb_devc
* devc
)
251 /* Just trust the mixer is there */
255 static void change_bits(sb_devc
* devc
, unsigned char *regval
, int dev
, int chn
, int newval
)
260 mask
= (1 << (*devc
->iomap
)[dev
][chn
].nbits
) - 1;
261 newval
= (int) ((newval
* mask
) + 50) / 100; /* Scale */
263 shift
= (*devc
->iomap
)[dev
][chn
].bitoffs
- (*devc
->iomap
)[dev
][LEFT_CHN
].nbits
+ 1;
265 *regval
&= ~(mask
<< shift
); /* Mask out previous value */
266 *regval
|= (newval
& mask
) << shift
; /* Set the new value */
269 static int sb_mixer_get(sb_devc
* devc
, int dev
)
271 if (!((1 << dev
) & devc
->supported_devices
))
273 return devc
->levels
[dev
];
276 void smw_mixer_init(sb_devc
* devc
)
280 sb_setmixer(devc
, 0x00, 0x18); /* Mute unused (Telephone) line */
281 sb_setmixer(devc
, 0x10, 0x38); /* Config register 2 */
283 devc
->supported_devices
= 0;
284 for (i
= 0; i
< sizeof(smw_mix_regs
); i
++)
285 if (smw_mix_regs
[i
] != 0)
286 devc
->supported_devices
|= (1 << i
);
288 devc
->supported_rec_devices
= devc
->supported_devices
&
289 ~(SOUND_MASK_BASS
| SOUND_MASK_TREBLE
| SOUND_MASK_PCM
| SOUND_MASK_VOLUME
);
290 sb_mixer_reset(devc
);
293 int sb_common_mixer_set(sb_devc
* devc
, int dev
, int left
, int right
)
298 regoffs
= (*devc
->iomap
)[dev
][LEFT_CHN
].regno
;
303 val
= sb_getmixer(devc
, regoffs
);
304 change_bits(devc
, &val
, dev
, LEFT_CHN
, left
);
306 if ((*devc
->iomap
)[dev
][RIGHT_CHN
].regno
!= regoffs
) /*
310 sb_setmixer(devc
, regoffs
, val
); /*
313 regoffs
= (*devc
->iomap
)[dev
][RIGHT_CHN
].regno
;
316 return left
| (left
<< 8); /*
317 * Just left channel present
320 val
= sb_getmixer(devc
, regoffs
); /*
324 change_bits(devc
, &val
, dev
, RIGHT_CHN
, right
);
326 sb_setmixer(devc
, regoffs
, val
);
328 return left
| (right
<< 8);
331 static int smw_mixer_set(sb_devc
* devc
, int dev
, int left
, int right
)
337 case SOUND_MIXER_VOLUME
:
338 sb_setmixer(devc
, 0x0b, 96 - (96 * left
/ 100)); /* 96=mute, 0=max */
339 sb_setmixer(devc
, 0x0c, 96 - (96 * right
/ 100));
342 case SOUND_MIXER_BASS
:
343 case SOUND_MIXER_TREBLE
:
344 devc
->levels
[dev
] = left
| (right
<< 8);
345 /* Set left bass and treble values */
346 val
= ((devc
->levels
[SOUND_MIXER_TREBLE
] & 0xff) * 16 / (unsigned) 100) << 4;
347 val
|= ((devc
->levels
[SOUND_MIXER_BASS
] & 0xff) * 16 / (unsigned) 100) & 0x0f;
348 sb_setmixer(devc
, 0x0d, val
);
350 /* Set right bass and treble values */
351 val
= (((devc
->levels
[SOUND_MIXER_TREBLE
] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
352 val
|= (((devc
->levels
[SOUND_MIXER_BASS
] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
353 sb_setmixer(devc
, 0x0e, val
);
358 reg
= smw_mix_regs
[dev
];
361 sb_setmixer(devc
, reg
, (24 - (24 * left
/ 100)) | 0x20); /* 24=mute, 0=max */
362 sb_setmixer(devc
, reg
+ 1, (24 - (24 * right
/ 100)) | 0x40);
365 devc
->levels
[dev
] = left
| (right
<< 8);
366 return left
| (right
<< 8);
369 static int sb_mixer_set(sb_devc
* devc
, int dev
, int value
)
371 int left
= value
& 0x000000ff;
372 int right
= (value
& 0x0000ff00) >> 8;
383 if (!(devc
->supported_devices
& (1 << dev
))) /*
388 /* Differentiate depending on the chipsets */
389 switch (devc
->model
) {
391 retval
= smw_mixer_set(devc
, dev
, left
, right
);
394 retval
= ess_mixer_set(devc
, dev
, left
, right
);
397 retval
= sb_common_mixer_set(devc
, dev
, left
, right
);
399 if (retval
>= 0) devc
->levels
[dev
] = retval
;
405 * set_recsrc doesn't apply to ES188x
407 static void set_recsrc(sb_devc
* devc
, int src
)
409 sb_setmixer(devc
, RECORD_SRC
, (sb_getmixer(devc
, RECORD_SRC
) & ~7) | (src
& 0x7));
412 static int set_recmask(sb_devc
* devc
, int mask
)
415 unsigned char regimageL
, regimageR
;
417 devmask
= mask
& devc
->supported_rec_devices
;
425 if (devc
->model
== MDL_ESS
&& ess_set_recmask (devc
, &devmask
)) {
428 if (devmask
!= SOUND_MASK_MIC
&&
429 devmask
!= SOUND_MASK_LINE
&&
430 devmask
!= SOUND_MASK_CD
)
433 * More than one device selected. Drop the
436 devmask
&= ~devc
->recmask
;
438 if (devmask
!= SOUND_MASK_MIC
&&
439 devmask
!= SOUND_MASK_LINE
&&
440 devmask
!= SOUND_MASK_CD
)
443 * More than one device selected. Default to
446 devmask
= SOUND_MASK_MIC
;
448 if (devmask
^ devc
->recmask
) /*
449 * Input source changed
455 set_recsrc(devc
, SRC__MIC
);
458 case SOUND_MASK_LINE
:
459 set_recsrc(devc
, SRC__LINE
);
463 set_recsrc(devc
, SRC__CD
);
467 set_recsrc(devc
, SRC__MIC
);
474 devmask
= SOUND_MASK_MIC
;
476 if (devc
->submodel
== SUBMDL_ALS007
)
480 case SOUND_MASK_LINE
:
481 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_LINE
);
484 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_CD
);
486 case SOUND_MASK_SYNTH
:
487 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_SYNTH
);
489 default: /* Also takes care of SOUND_MASK_MIC case */
490 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_MIC
);
496 regimageL
= regimageR
= 0;
497 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++)
499 if ((1 << i
) & devmask
)
501 regimageL
|= sb16_recmasks_L
[i
];
502 regimageR
|= sb16_recmasks_R
[i
];
504 sb_setmixer (devc
, SB16_IMASK_L
, regimageL
);
505 sb_setmixer (devc
, SB16_IMASK_R
, regimageR
);
510 devc
->recmask
= devmask
;
511 return devc
->recmask
;
514 static int set_outmask(sb_devc
* devc
, int mask
)
517 unsigned char regimage
;
519 devmask
= mask
& devc
->supported_out_devices
;
524 if (devc
->submodel
== SUBMDL_ALS007
)
529 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++)
531 if ((1 << i
) & devmask
)
533 regimage
|= (sb16_recmasks_L
[i
] | sb16_recmasks_R
[i
]);
535 sb_setmixer (devc
, SB16_OMASK
, regimage
);
543 devc
->outmask
= devmask
;
544 return devc
->outmask
;
547 static int sb_mixer_ioctl(int dev
, unsigned int cmd
, caddr_t arg
)
549 sb_devc
*devc
= mixer_devs
[dev
]->devc
;
553 * Use ioctl(fd, SOUND_MIXER_PRIVATE1, &mode) to turn AGC off (0) or on (1).
555 if (cmd
== SOUND_MIXER_PRIVATE1
&& devc
->model
== MDL_SB16
)
557 if (get_user(val
, (int *)arg
))
559 sb_setmixer(devc
, 0x43, (~val
) & 0x01);
562 if (((cmd
>> 8) & 0xff) == 'M')
564 if (_SIOC_DIR(cmd
) & _SIOC_WRITE
)
566 if (get_user(val
, (int *)arg
))
570 case SOUND_MIXER_RECSRC
:
571 ret
= set_recmask(devc
, val
);
574 case SOUND_MIXER_OUTSRC
:
575 ret
= set_outmask(devc
, val
);
579 ret
= sb_mixer_set(devc
, cmd
& 0xff, val
);
582 else switch (cmd
& 0xff)
584 case SOUND_MIXER_RECSRC
:
588 case SOUND_MIXER_OUTSRC
:
592 case SOUND_MIXER_DEVMASK
:
593 ret
= devc
->supported_devices
;
596 case SOUND_MIXER_STEREODEVS
:
597 ret
= devc
->supported_devices
;
598 /* The ESS seems to have stereo mic controls */
599 if (devc
->model
== MDL_ESS
)
600 ret
&= ~(SOUND_MASK_SPEAKER
|SOUND_MASK_IMIX
);
601 else if (devc
->model
!= MDL_JAZZ
&& devc
->model
!= MDL_SMW
)
602 ret
&= ~(SOUND_MASK_MIC
| SOUND_MASK_SPEAKER
| SOUND_MASK_IMIX
);
605 case SOUND_MIXER_RECMASK
:
606 ret
= devc
->supported_rec_devices
;
609 case SOUND_MIXER_OUTMASK
:
610 ret
= devc
->supported_out_devices
;
613 case SOUND_MIXER_CAPS
:
614 ret
= devc
->mixer_caps
;
618 ret
= sb_mixer_get(devc
, cmd
& 0xff);
621 return put_user(ret
, (int *)arg
);
626 static struct mixer_operations sb_mixer_operations
=
633 static struct mixer_operations als007_mixer_operations
=
640 static void sb_mixer_reset(sb_devc
* devc
)
646 sprintf(name
, "SB_%d", devc
->sbmixnum
);
649 devc
->levels
= load_mixer_volumes(name
, smg_default_levels
, 1);
651 devc
->levels
= load_mixer_volumes(name
, sb_default_levels
, 1);
653 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++)
654 sb_mixer_set(devc
, i
, devc
->levels
[i
]);
656 if (devc
->model
!= MDL_ESS
|| !ess_mixer_reset (devc
)) {
657 set_recmask(devc
, SOUND_MASK_MIC
);
661 int sb_mixer_init(sb_devc
* devc
)
666 devc
->sbmixnum
= sbmixnum
++;
669 sb_setmixer(devc
, 0x00, 0); /* Reset mixer */
671 if (!(mixer_type
= detect_mixer(devc
)))
672 return 0; /* No mixer. Why? */
679 devc
->mixer_caps
= SOUND_CAP_EXCL_INPUT
;
680 devc
->supported_devices
= SBPRO_MIXER_DEVICES
;
681 devc
->supported_rec_devices
= SBPRO_RECORDING_DEVICES
;
682 devc
->iomap
= &sbpro_mix
;
686 ess_mixer_init (devc
);
690 devc
->mixer_caps
= SOUND_CAP_EXCL_INPUT
;
691 devc
->supported_devices
= 0;
692 devc
->supported_rec_devices
= 0;
693 devc
->iomap
= &sbpro_mix
;
694 smw_mixer_init(devc
);
698 devc
->mixer_caps
= 0;
699 devc
->supported_rec_devices
= SB16_RECORDING_DEVICES
;
700 devc
->supported_out_devices
= SB16_OUTFILTER_DEVICES
;
701 if (devc
->submodel
!= SUBMDL_ALS007
)
703 devc
->supported_devices
= SB16_MIXER_DEVICES
;
704 devc
->iomap
= &sb16_mix
;
708 devc
->supported_devices
= ALS007_MIXER_DEVICES
;
709 devc
->iomap
= &als007_mix
;
714 printk(KERN_WARNING
"sb_mixer: Unsupported mixer type %d\n", devc
->model
);
718 m
= sound_alloc_mixerdev();
722 mixer_devs
[m
] = (struct mixer_operations
*)kmalloc(sizeof(struct mixer_operations
), GFP_KERNEL
);
723 if (mixer_devs
[m
] == NULL
)
725 printk(KERN_ERR
"sb_mixer: Can't allocate memory\n");
726 sound_unload_mixerdev(m
);
730 if (devc
->submodel
!= SUBMDL_ALS007
)
731 memcpy ((char *) mixer_devs
[m
], (char *) &sb_mixer_operations
, sizeof (struct mixer_operations
));
733 memcpy ((char *) mixer_devs
[m
], (char *) &als007_mixer_operations
, sizeof (struct mixer_operations
));
735 mixer_devs
[m
]->devc
= devc
;
736 devc
->my_mixerdev
= m
;
737 sb_mixer_reset(devc
);