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]
16 * Stanislav Voronyi <stas@esc.kharkov.com> : Support for AWE 3DSE device (Jun 7 1999)
19 #include "sound_config.h"
21 #define __SB_MIXER_C__
28 #define SBPRO_RECORDING_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD)
30 /* Same as SB Pro, unless I find otherwise */
31 #define SGNXPRO_RECORDING_DEVICES SBPRO_RECORDING_DEVICES
33 #define SBPRO_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_LINE | SOUND_MASK_MIC | \
34 SOUND_MASK_CD | SOUND_MASK_VOLUME)
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
41 #define SGNXPRO_MIXER_DEVICES (SBPRO_MIXER_DEVICES|SOUND_MASK_BASS| \
42 SOUND_MASK_TREBLE|SOUND_MASK_SPEAKER )
44 #define SB16_RECORDING_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | SOUND_MASK_MIC | \
47 #define SB16_OUTFILTER_DEVICES (SOUND_MASK_LINE | SOUND_MASK_MIC | \
50 #define SB16_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_PCM | SOUND_MASK_SPEAKER | SOUND_MASK_LINE | SOUND_MASK_MIC | \
52 SOUND_MASK_IGAIN | SOUND_MASK_OGAIN | \
53 SOUND_MASK_VOLUME | SOUND_MASK_BASS | SOUND_MASK_TREBLE | \
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.
59 #define ALS007_MIXER_DEVICES (SOUND_MASK_SYNTH | SOUND_MASK_LINE | \
60 SOUND_MASK_PCM | SOUND_MASK_MIC | \
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)
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)
96 static mixer_tab als007_mix
=
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)
115 /* SM_GAMES Master volume is lower and PCM & FM volumes
116 higher than with SB Pro. This improves the
119 static int smg_default_levels
[32] =
121 0x2020, /* Master Volume */
126 0x4b4b, /* PC Speaker */
127 0x4b4b, /* Ext Line */
130 0x4b4b, /* Recording monitor */
132 0x4b4b, /* Recording level */
133 0x4b4b, /* Input gain */
134 0x4b4b, /* Output gain */
140 static int sb_default_levels
[32] =
142 0x5a5a, /* Master Volume */
147 0x4b4b, /* PC Speaker */
148 0x4b4b, /* Ext Line */
151 0x0000, /* Recording monitor */
153 0x4b4b, /* Recording level */
154 0x4b4b, /* Input gain */
155 0x4b4b, /* Output gain */
161 static unsigned char sb16_recmasks_L
[SOUND_MIXER_NRDEVICES
] =
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 */
179 static unsigned char sb16_recmasks_R
[SOUND_MIXER_NRDEVICES
] =
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 */
197 static char smw_mix_regs
[] = /* Left mixer registers */
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 */
218 static int sbmixnum
= 1;
220 static void sb_mixer_reset(sb_devc
* devc
);
222 void sb_mixer_set_stereo(sb_devc
* devc
, int mode
)
224 sb_chgmixer(devc
, OUT_FILTER
, STEREO_DAC
, (mode
? STEREO_DAC
: MONO_DAC
));
227 static int detect_mixer(sb_devc
* devc
)
229 /* Just trust the mixer is there */
233 static void change_bits(sb_devc
* devc
, unsigned char *regval
, int dev
, int chn
, int newval
)
238 mask
= (1 << (*devc
->iomap
)[dev
][chn
].nbits
) - 1;
239 newval
= (int) ((newval
* mask
) + 50) / 100; /* Scale */
241 shift
= (*devc
->iomap
)[dev
][chn
].bitoffs
- (*devc
->iomap
)[dev
][LEFT_CHN
].nbits
+ 1;
243 *regval
&= ~(mask
<< shift
); /* Mask out previous value */
244 *regval
|= (newval
& mask
) << shift
; /* Set the new value */
247 static int sb_mixer_get(sb_devc
* devc
, int dev
)
249 if (!((1 << dev
) & devc
->supported_devices
))
251 return devc
->levels
[dev
];
254 void smw_mixer_init(sb_devc
* devc
)
258 sb_setmixer(devc
, 0x00, 0x18); /* Mute unused (Telephone) line */
259 sb_setmixer(devc
, 0x10, 0x38); /* Config register 2 */
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
);
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
);
271 int sb_common_mixer_set(sb_devc
* devc
, int dev
, int left
, int right
)
276 regoffs
= (*devc
->iomap
)[dev
][LEFT_CHN
].regno
;
281 val
= sb_getmixer(devc
, regoffs
);
282 change_bits(devc
, &val
, dev
, LEFT_CHN
, left
);
284 if ((*devc
->iomap
)[dev
][RIGHT_CHN
].regno
!= regoffs
) /*
288 sb_setmixer(devc
, regoffs
, val
); /*
291 regoffs
= (*devc
->iomap
)[dev
][RIGHT_CHN
].regno
;
294 return left
| (left
<< 8); /*
295 * Just left channel present
298 val
= sb_getmixer(devc
, regoffs
); /*
302 change_bits(devc
, &val
, dev
, RIGHT_CHN
, right
);
304 sb_setmixer(devc
, regoffs
, val
);
306 return left
| (right
<< 8);
309 static int smw_mixer_set(sb_devc
* devc
, int dev
, int left
, int right
)
315 case SOUND_MIXER_VOLUME
:
316 sb_setmixer(devc
, 0x0b, 96 - (96 * left
/ 100)); /* 96=mute, 0=max */
317 sb_setmixer(devc
, 0x0c, 96 - (96 * right
/ 100));
320 case SOUND_MIXER_BASS
:
321 case SOUND_MIXER_TREBLE
:
322 devc
->levels
[dev
] = left
| (right
<< 8);
323 /* Set left bass and treble values */
324 val
= ((devc
->levels
[SOUND_MIXER_TREBLE
] & 0xff) * 16 / (unsigned) 100) << 4;
325 val
|= ((devc
->levels
[SOUND_MIXER_BASS
] & 0xff) * 16 / (unsigned) 100) & 0x0f;
326 sb_setmixer(devc
, 0x0d, val
);
328 /* Set right bass and treble values */
329 val
= (((devc
->levels
[SOUND_MIXER_TREBLE
] >> 8) & 0xff) * 16 / (unsigned) 100) << 4;
330 val
|= (((devc
->levels
[SOUND_MIXER_BASS
] >> 8) & 0xff) * 16 / (unsigned) 100) & 0x0f;
331 sb_setmixer(devc
, 0x0e, val
);
336 reg
= smw_mix_regs
[dev
];
339 sb_setmixer(devc
, reg
, (24 - (24 * left
/ 100)) | 0x20); /* 24=mute, 0=max */
340 sb_setmixer(devc
, reg
+ 1, (24 - (24 * right
/ 100)) | 0x40);
343 devc
->levels
[dev
] = left
| (right
<< 8);
344 return left
| (right
<< 8);
347 static int sb_mixer_set(sb_devc
* devc
, int dev
, int value
)
349 int left
= value
& 0x000000ff;
350 int right
= (value
& 0x0000ff00) >> 8;
361 if (!(devc
->supported_devices
& (1 << dev
))) /*
366 /* Differentiate depending on the chipsets */
367 switch (devc
->model
) {
369 retval
= smw_mixer_set(devc
, dev
, left
, right
);
372 retval
= ess_mixer_set(devc
, dev
, left
, right
);
375 retval
= sb_common_mixer_set(devc
, dev
, left
, right
);
377 if (retval
>= 0) devc
->levels
[dev
] = retval
;
383 * set_recsrc doesn't apply to ES188x
385 static void set_recsrc(sb_devc
* devc
, int src
)
387 sb_setmixer(devc
, RECORD_SRC
, (sb_getmixer(devc
, RECORD_SRC
) & ~7) | (src
& 0x7));
390 static int set_recmask(sb_devc
* devc
, int mask
)
393 unsigned char regimageL
, regimageR
;
395 devmask
= mask
& devc
->supported_rec_devices
;
403 if (devc
->model
== MDL_ESS
&& ess_set_recmask (devc
, &devmask
)) {
406 if (devmask
!= SOUND_MASK_MIC
&&
407 devmask
!= SOUND_MASK_LINE
&&
408 devmask
!= SOUND_MASK_CD
)
411 * More than one device selected. Drop the
414 devmask
&= ~devc
->recmask
;
416 if (devmask
!= SOUND_MASK_MIC
&&
417 devmask
!= SOUND_MASK_LINE
&&
418 devmask
!= SOUND_MASK_CD
)
421 * More than one device selected. Default to
424 devmask
= SOUND_MASK_MIC
;
426 if (devmask
^ devc
->recmask
) /*
427 * Input source changed
433 set_recsrc(devc
, SRC__MIC
);
436 case SOUND_MASK_LINE
:
437 set_recsrc(devc
, SRC__LINE
);
441 set_recsrc(devc
, SRC__CD
);
445 set_recsrc(devc
, SRC__MIC
);
452 devmask
= SOUND_MASK_MIC
;
454 if (devc
->submodel
== SUBMDL_ALS007
)
458 case SOUND_MASK_LINE
:
459 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_LINE
);
462 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_CD
);
464 case SOUND_MASK_SYNTH
:
465 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_SYNTH
);
467 default: /* Also takes care of SOUND_MASK_MIC case */
468 sb_setmixer(devc
, ALS007_RECORD_SRC
, ALS007_MIC
);
474 regimageL
= regimageR
= 0;
475 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++)
477 if ((1 << i
) & devmask
)
479 regimageL
|= sb16_recmasks_L
[i
];
480 regimageR
|= sb16_recmasks_R
[i
];
482 sb_setmixer (devc
, SB16_IMASK_L
, regimageL
);
483 sb_setmixer (devc
, SB16_IMASK_R
, regimageR
);
488 devc
->recmask
= devmask
;
489 return devc
->recmask
;
492 static int set_outmask(sb_devc
* devc
, int mask
)
495 unsigned char regimage
;
497 devmask
= mask
& devc
->supported_out_devices
;
502 if (devc
->submodel
== SUBMDL_ALS007
)
507 for (i
= 0; i
< SOUND_MIXER_NRDEVICES
; i
++)
509 if ((1 << i
) & devmask
)
511 regimage
|= (sb16_recmasks_L
[i
] | sb16_recmasks_R
[i
]);
513 sb_setmixer (devc
, SB16_OMASK
, regimage
);
521 devc
->outmask
= devmask
;
522 return devc
->outmask
;
525 static int sb_mixer_ioctl(int dev
, unsigned int cmd
, caddr_t arg
)
527 sb_devc
*devc
= mixer_devs
[dev
]->devc
;
531 * Use ioctl(fd, SOUND_MIXER_AGC, &mode) to turn AGC off (0) or on (1).
532 * Use ioctl(fd, SOUND_MIXER_3DSE, &mode) to turn 3DSE off (0) or on (1)
533 * or mode==2 put 3DSE state to mode.
535 if (devc
->model
== MDL_SB16
) {
536 if (cmd
== SOUND_MIXER_AGC
)
538 if (get_user(val
, (int *)arg
))
540 sb_setmixer(devc
, 0x43, (~val
) & 0x01);
543 if (cmd
== SOUND_MIXER_3DSE
)
545 /* I put here 15, but I don't know the exact version.
546 At least my 4.13 havn't 3DSE, 4.16 has it. */
547 if (devc
->minor
< 15)
549 if (get_user(val
, (int *)arg
))
551 if (val
== 0 || val
== 1)
552 sb_chgmixer(devc
, AWE_3DSE
, 0x01, val
);
555 ret
= sb_getmixer(devc
, AWE_3DSE
)&0x01;
556 return put_user(ret
, (int *)arg
);
563 if (((cmd
>> 8) & 0xff) == 'M')
565 if (_SIOC_DIR(cmd
) & _SIOC_WRITE
)
567 if (get_user(val
, (int *)arg
))
571 case SOUND_MIXER_RECSRC
:
572 ret
= set_recmask(devc
, val
);
575 case SOUND_MIXER_OUTSRC
:
576 ret
= set_outmask(devc
, val
);
580 ret
= sb_mixer_set(devc
, cmd
& 0xff, val
);
583 else switch (cmd
& 0xff)
585 case SOUND_MIXER_RECSRC
:
589 case SOUND_MIXER_OUTSRC
:
593 case SOUND_MIXER_DEVMASK
:
594 ret
= devc
->supported_devices
;
597 case SOUND_MIXER_STEREODEVS
:
598 ret
= devc
->supported_devices
;
599 /* The ESS seems to have stereo mic controls */
600 if (devc
->model
== MDL_ESS
)
601 ret
&= ~(SOUND_MASK_SPEAKER
|SOUND_MASK_IMIX
);
602 else if (devc
->model
!= MDL_JAZZ
&& devc
->model
!= MDL_SMW
)
603 ret
&= ~(SOUND_MASK_MIC
| SOUND_MASK_SPEAKER
| SOUND_MASK_IMIX
);
606 case SOUND_MIXER_RECMASK
:
607 ret
= devc
->supported_rec_devices
;
610 case SOUND_MIXER_OUTMASK
:
611 ret
= devc
->supported_out_devices
;
614 case SOUND_MIXER_CAPS
:
615 ret
= devc
->mixer_caps
;
619 ret
= sb_mixer_get(devc
, cmd
& 0xff);
622 return put_user(ret
, (int *)arg
);
627 static struct mixer_operations sb_mixer_operations
=
634 static struct mixer_operations als007_mixer_operations
=
641 static void sb_mixer_reset(sb_devc
* devc
)
646 sprintf(name
, "SB_%d", devc
->sbmixnum
);
648 if (devc
->sbmo
.sm_games
)
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? */
681 devc
->mixer_caps
= SOUND_CAP_EXCL_INPUT
;
682 devc
->supported_devices
= SBPRO_MIXER_DEVICES
;
683 devc
->supported_rec_devices
= SBPRO_RECORDING_DEVICES
;
684 devc
->iomap
= &sbpro_mix
;
688 ess_mixer_init (devc
);
692 devc
->mixer_caps
= SOUND_CAP_EXCL_INPUT
;
693 devc
->supported_devices
= 0;
694 devc
->supported_rec_devices
= 0;
695 devc
->iomap
= &sbpro_mix
;
696 smw_mixer_init(devc
);
700 devc
->mixer_caps
= 0;
701 devc
->supported_rec_devices
= SB16_RECORDING_DEVICES
;
702 devc
->supported_out_devices
= SB16_OUTFILTER_DEVICES
;
703 if (devc
->submodel
!= SUBMDL_ALS007
)
705 devc
->supported_devices
= SB16_MIXER_DEVICES
;
706 devc
->iomap
= &sb16_mix
;
710 devc
->supported_devices
= ALS007_MIXER_DEVICES
;
711 devc
->iomap
= &als007_mix
;
716 printk(KERN_WARNING
"sb_mixer: Unsupported mixer type %d\n", devc
->model
);
720 m
= sound_alloc_mixerdev();
724 mixer_devs
[m
] = (struct mixer_operations
*)kmalloc(sizeof(struct mixer_operations
), GFP_KERNEL
);
725 if (mixer_devs
[m
] == NULL
)
727 printk(KERN_ERR
"sb_mixer: Can't allocate memory\n");
728 sound_unload_mixerdev(m
);
732 if (devc
->submodel
!= SUBMDL_ALS007
)
733 memcpy ((char *) mixer_devs
[m
], (char *) &sb_mixer_operations
, sizeof (struct mixer_operations
));
735 memcpy ((char *) mixer_devs
[m
], (char *) &als007_mixer_operations
, sizeof (struct mixer_operations
));
737 mixer_devs
[m
]->devc
= devc
;
738 devc
->my_mixerdev
= m
;
739 sb_mixer_reset(devc
);
743 void sb_mixer_unload(sb_devc
*devc
)
745 sound_unload_mixerdev(devc
->my_mixerdev
);