23 #include <linux/slab.h>
24 #include <linux/time.h>
25 #include <linux/string.h>
26 #include <linux/module.h>
32 #include <linux/soundcard.h>
34 #define OSS_ALSAEMULVER _SIOR ('M', 249, int)
44 struct snd_mixer_oss_file *fmixer;
51 card = snd_lookup_oss_minor_data(iminor(inode),
52 SNDRV_OSS_DEVICE_TYPE_MIXER);
55 if (card->mixer_oss ==
NULL) {
71 fmixer->mixer = card->mixer_oss;
73 if (!try_module_get(card->
module)) {
83 static int snd_mixer_oss_release(
struct inode *inode,
struct file *file)
85 struct snd_mixer_oss_file *fmixer;
89 module_put(fmixer->card->module);
96 static int snd_mixer_oss_info(
struct snd_mixer_oss_file *fmixer,
99 struct snd_card *card = fmixer->card;
100 struct snd_mixer_oss *mixer = fmixer->mixer;
106 info.modify_counter = card->mixer_oss_change_count;
112 static int snd_mixer_oss_info_obsolete(
struct snd_mixer_oss_file *fmixer,
115 struct snd_card *card = fmixer->card;
116 struct snd_mixer_oss *mixer = fmixer->mixer;
119 memset(&info, 0,
sizeof(info));
120 strlcpy(info.
id, mixer && mixer->id[0] ? mixer->id : card->
driver,
sizeof(info.
id));
127 static int snd_mixer_oss_caps(
struct snd_mixer_oss_file *fmixer)
129 struct snd_mixer_oss *mixer = fmixer->mixer;
134 if (mixer->get_recsrc && mixer->put_recsrc)
139 static int snd_mixer_oss_devmask(
struct snd_mixer_oss_file *fmixer)
141 struct snd_mixer_oss *mixer = fmixer->mixer;
142 struct snd_mixer_oss_slot *pslot;
148 pslot = &mixer->slots[
chn];
149 if (pslot->put_volume || pslot->put_recsrc)
155 static int snd_mixer_oss_stereodevs(
struct snd_mixer_oss_file *fmixer)
157 struct snd_mixer_oss *mixer = fmixer->mixer;
158 struct snd_mixer_oss_slot *pslot;
164 pslot = &mixer->slots[
chn];
165 if (pslot->put_volume && pslot->stereo)
171 static int snd_mixer_oss_recmask(
struct snd_mixer_oss_file *fmixer)
173 struct snd_mixer_oss *mixer = fmixer->mixer;
178 if (mixer->put_recsrc && mixer->get_recsrc) {
179 result = mixer->mask_recsrc;
181 struct snd_mixer_oss_slot *pslot;
183 for (chn = 0; chn < 31; chn++) {
184 pslot = &mixer->slots[
chn];
185 if (pslot->put_recsrc)
192 static int snd_mixer_oss_get_recsrc(
struct snd_mixer_oss_file *fmixer)
194 struct snd_mixer_oss *mixer = fmixer->mixer;
199 if (mixer->put_recsrc && mixer->get_recsrc) {
202 if ((err = mixer->get_recsrc(fmixer, &index)) < 0)
206 struct snd_mixer_oss_slot *pslot;
208 for (chn = 0; chn < 31; chn++) {
209 pslot = &mixer->slots[
chn];
210 if (pslot->get_recsrc) {
212 pslot->get_recsrc(fmixer, pslot, &active);
218 return mixer->oss_recsrc =
result;
221 static int snd_mixer_oss_set_recsrc(
struct snd_mixer_oss_file *fmixer,
int recsrc)
223 struct snd_mixer_oss *mixer = fmixer->mixer;
224 struct snd_mixer_oss_slot *pslot;
231 if (mixer->get_recsrc && mixer->put_recsrc) {
232 if (recsrc & ~mixer->oss_recsrc)
233 recsrc &= ~mixer->oss_recsrc;
234 mixer->put_recsrc(fmixer,
ffz(~recsrc));
235 mixer->get_recsrc(fmixer, &index);
238 for (chn = 0; chn < 31; chn++) {
239 pslot = &mixer->slots[
chn];
240 if (pslot->put_recsrc) {
241 active = (recsrc & (1 <<
chn)) ? 1 : 0;
242 pslot->put_recsrc(fmixer, pslot, active);
246 for (chn = 0; chn < 31; chn++) {
247 pslot = &mixer->slots[
chn];
248 if (pslot->get_recsrc) {
250 pslot->get_recsrc(fmixer, pslot, &active);
259 static int snd_mixer_oss_get_volume(
struct snd_mixer_oss_file *fmixer,
int slot)
261 struct snd_mixer_oss *mixer = fmixer->mixer;
262 struct snd_mixer_oss_slot *pslot;
265 if (mixer ==
NULL || slot > 30)
267 pslot = &mixer->slots[
slot];
268 left = pslot->volume[0];
269 right = pslot->volume[1];
270 if (pslot->get_volume)
271 result = pslot->get_volume(fmixer, pslot, &
left, &right);
279 pslot->volume[0] =
left;
280 pslot->volume[1] =
right;
281 result = (
left & 0xff) | ((right & 0xff) << 8);
286 static int snd_mixer_oss_set_volume(
struct snd_mixer_oss_file *fmixer,
289 struct snd_mixer_oss *mixer = fmixer->mixer;
290 struct snd_mixer_oss_slot *pslot;
291 int result = 0,
left = volume & 0xff, right = (volume >> 8) & 0xff;
293 if (mixer ==
NULL || slot > 30)
295 pslot = &mixer->slots[
slot];
302 if (pslot->put_volume)
303 result = pslot->put_volume(fmixer, pslot,
left, right);
306 pslot->volume[0] =
left;
307 pslot->volume[1] =
right;
308 return (
left & 0xff) | ((right & 0xff) << 8);
311 static int snd_mixer_oss_ioctl1(
struct snd_mixer_oss_file *fmixer,
unsigned int cmd,
unsigned long arg)
319 if (((cmd >> 8) & 0xff) ==
'M') {
322 return snd_mixer_oss_info(fmixer, argp);
324 return snd_mixer_oss_info_obsolete(fmixer, argp);
328 tmp = snd_mixer_oss_set_recsrc(fmixer, tmp);
337 tmp = snd_mixer_oss_devmask(fmixer);
342 tmp = snd_mixer_oss_stereodevs(fmixer);
347 tmp = snd_mixer_oss_recmask(fmixer);
352 tmp = snd_mixer_oss_caps(fmixer);
357 tmp = snd_mixer_oss_get_recsrc(fmixer);
366 tmp = snd_mixer_oss_set_volume(fmixer, cmd & 0xff, tmp);
371 tmp = snd_mixer_oss_get_volume(fmixer, cmd & 0xff);
379 static long snd_mixer_oss_ioctl(
struct file *file,
unsigned int cmd,
unsigned long arg)
381 return snd_mixer_oss_ioctl1(file->
private_data, cmd, arg);
386 struct snd_mixer_oss_file fmixer;
390 if (card->mixer_oss ==
NULL)
392 memset(&fmixer, 0,
sizeof(fmixer));
394 fmixer.mixer = card->mixer_oss;
395 return snd_mixer_oss_ioctl1(&fmixer, cmd, arg);
400 #define snd_mixer_oss_ioctl_compat snd_mixer_oss_ioctl
402 #define snd_mixer_oss_ioctl_compat NULL
412 .open = snd_mixer_oss_open,
413 .release = snd_mixer_oss_release,
415 .unlocked_ioctl = snd_mixer_oss_ioctl,
423 static long snd_mixer_oss_conv(
long val,
long omin,
long omax,
long nmin,
long nmax)
425 long orange = omax - omin, nrange = nmax - nmin;
429 return ((nrange * (val - omin)) + (orange / 2)) / orange + nmin;
433 static long snd_mixer_oss_conv1(
long val,
long min,
long max,
int *old)
435 if (val == snd_mixer_oss_conv(*old, 0, 100, min, max))
437 return snd_mixer_oss_conv(val, min, max, 0, 100);
441 static long snd_mixer_oss_conv2(
long val,
long min,
long max)
443 return snd_mixer_oss_conv(val, 0, 100, min, max);
447 static void snd_mixer_oss_recsrce_set(
struct snd_card *card,
int slot)
449 struct snd_mixer_oss *mixer = card->mixer_oss;
451 mixer->mask_recsrc |= 1 <<
slot;
454 static int snd_mixer_oss_recsrce_get(
struct snd_card *card,
int slot)
456 struct snd_mixer_oss *mixer = card->mixer_oss;
457 if (mixer && (mixer->mask_recsrc & (1 << slot)))
463 #define SNDRV_MIXER_OSS_SIGNATURE 0x65999250
465 #define SNDRV_MIXER_OSS_ITEM_GLOBAL 0
466 #define SNDRV_MIXER_OSS_ITEM_GSWITCH 1
467 #define SNDRV_MIXER_OSS_ITEM_GROUTE 2
468 #define SNDRV_MIXER_OSS_ITEM_GVOLUME 3
469 #define SNDRV_MIXER_OSS_ITEM_PSWITCH 4
470 #define SNDRV_MIXER_OSS_ITEM_PROUTE 5
471 #define SNDRV_MIXER_OSS_ITEM_PVOLUME 6
472 #define SNDRV_MIXER_OSS_ITEM_CSWITCH 7
473 #define SNDRV_MIXER_OSS_ITEM_CROUTE 8
474 #define SNDRV_MIXER_OSS_ITEM_CVOLUME 9
475 #define SNDRV_MIXER_OSS_ITEM_CAPTURE 10
477 #define SNDRV_MIXER_OSS_ITEM_COUNT 11
479 #define SNDRV_MIXER_OSS_PRESENT_GLOBAL (1<<0)
480 #define SNDRV_MIXER_OSS_PRESENT_GSWITCH (1<<1)
481 #define SNDRV_MIXER_OSS_PRESENT_GROUTE (1<<2)
482 #define SNDRV_MIXER_OSS_PRESENT_GVOLUME (1<<3)
483 #define SNDRV_MIXER_OSS_PRESENT_PSWITCH (1<<4)
484 #define SNDRV_MIXER_OSS_PRESENT_PROUTE (1<<5)
485 #define SNDRV_MIXER_OSS_PRESENT_PVOLUME (1<<6)
486 #define SNDRV_MIXER_OSS_PRESENT_CSWITCH (1<<7)
487 #define SNDRV_MIXER_OSS_PRESENT_CROUTE (1<<8)
488 #define SNDRV_MIXER_OSS_PRESENT_CVOLUME (1<<9)
489 #define SNDRV_MIXER_OSS_PRESENT_CAPTURE (1<<10)
501 #define ID_UNKNOWN ((unsigned int)-1)
503 static struct snd_kcontrol *snd_mixer_oss_test_id(
struct snd_mixer_oss *mixer,
const char *
name,
int index)
505 struct snd_card *card = mixer->card;
508 memset(&
id, 0,
sizeof(
id));
510 strlcpy(
id.name, name,
sizeof(
id.name));
515 static void snd_mixer_oss_get_volume1_vol(
struct snd_mixer_oss_file *fmixer,
516 struct snd_mixer_oss_slot *pslot,
518 int *
left,
int *right)
523 struct snd_card *card = fmixer->card;
536 if (kctl->
info(kctl, uinfo))
538 if (kctl->
get(kctl, uctl))
544 if (uinfo->
count > 1)
552 static void snd_mixer_oss_get_volume1_sw(
struct snd_mixer_oss_file *fmixer,
553 struct snd_mixer_oss_slot *pslot,
555 int *left,
int *right,
561 struct snd_card *card = fmixer->card;
574 if (kctl->
info(kctl, uinfo))
576 if (kctl->
get(kctl, uctl))
578 if (!uctl->
value.integer.value[0]) {
580 if (uinfo->
count == 1)
583 if (uinfo->
count > 1 && !uctl->
value.integer.value[route ? 3 : 1])
591 static int snd_mixer_oss_get_volume1(
struct snd_mixer_oss_file *fmixer,
592 struct snd_mixer_oss_slot *pslot,
593 int *left,
int *right)
595 struct slot *slot = pslot->private_data;
597 *left = *right = 100;
617 static void snd_mixer_oss_put_volume1_vol(
struct snd_mixer_oss_file *fmixer,
618 struct snd_mixer_oss_slot *pslot,
625 struct snd_card *card = fmixer->card;
639 if (kctl->
info(kctl, uinfo))
645 if (uinfo->
count > 1)
647 if ((res = kctl->
put(kctl, uctl)) < 0)
657 static void snd_mixer_oss_put_volume1_sw(
struct snd_mixer_oss_file *fmixer,
658 struct snd_mixer_oss_slot *pslot,
666 struct snd_card *card = fmixer->card;
680 if (kctl->
info(kctl, uinfo))
682 if (uinfo->
count > 1) {
683 uctl->
value.integer.value[0] = left > 0 ? 1 : 0;
684 uctl->
value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0;
686 uctl->
value.integer.value[1] =
687 uctl->
value.integer.value[2] = 0;
690 uctl->
value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0;
692 if ((res = kctl->
put(kctl, uctl)) < 0)
702 static int snd_mixer_oss_put_volume1(
struct snd_mixer_oss_file *fmixer,
703 struct snd_mixer_oss_slot *pslot,
706 struct slot *slot = pslot->private_data;
713 snd_mixer_oss_put_volume1_vol(fmixer, pslot,
751 static int snd_mixer_oss_get_recsrc1_sw(
struct snd_mixer_oss_file *fmixer,
752 struct snd_mixer_oss_slot *pslot,
755 struct slot *slot = pslot->private_data;
760 *active = (left ||
right) ? 1 : 0;
764 static int snd_mixer_oss_get_recsrc1_route(
struct snd_mixer_oss_file *fmixer,
765 struct snd_mixer_oss_slot *pslot,
768 struct slot *slot = pslot->private_data;
773 *active = (left ||
right) ? 1 : 0;
777 static int snd_mixer_oss_put_recsrc1_sw(
struct snd_mixer_oss_file *fmixer,
778 struct snd_mixer_oss_slot *pslot,
781 struct slot *slot = pslot->private_data;
787 static int snd_mixer_oss_put_recsrc1_route(
struct snd_mixer_oss_file *fmixer,
788 struct snd_mixer_oss_slot *pslot,
791 struct slot *slot = pslot->private_data;
797 static int snd_mixer_oss_get_recsrc2(
struct snd_mixer_oss_file *fmixer,
unsigned int *active_index)
799 struct snd_card *card = fmixer->card;
800 struct snd_mixer_oss *mixer = fmixer->mixer;
802 struct snd_mixer_oss_slot *pslot;
810 if (uinfo ==
NULL || uctl ==
NULL) {
815 kctl = snd_mixer_oss_test_id(mixer,
"Capture Source", 0);
820 if ((err = kctl->
info(kctl, uinfo)) < 0)
822 if ((err = kctl->
get(kctl, uctl)) < 0)
824 for (idx = 0; idx < 32; idx++) {
825 if (!(mixer->mask_recsrc & (1 << idx)))
827 pslot = &mixer->slots[
idx];
828 slot = pslot->private_data;
847 static int snd_mixer_oss_put_recsrc2(
struct snd_mixer_oss_file *fmixer,
unsigned int active_index)
849 struct snd_card *card = fmixer->card;
850 struct snd_mixer_oss *mixer = fmixer->mixer;
852 struct snd_mixer_oss_slot *pslot;
853 struct slot *slot =
NULL;
861 if (uinfo ==
NULL || uctl ==
NULL) {
866 kctl = snd_mixer_oss_test_id(mixer,
"Capture Source", 0);
871 if ((err = kctl->
info(kctl, uinfo)) < 0)
873 for (idx = 0; idx < 32; idx++) {
874 if (!(mixer->mask_recsrc & (1 << idx)))
876 pslot = &mixer->slots[
idx];
877 slot = pslot->private_data;
882 if (idx == active_index)
888 for (idx = 0; idx < uinfo->
count; idx++)
890 err = kctl->
put(kctl, uctl);
908 static int snd_mixer_oss_build_test(
struct snd_mixer_oss *mixer,
struct slot *slot,
const char *
name,
int index,
int item)
912 struct snd_card *card = mixer->card;
916 kcontrol = snd_mixer_oss_test_id(mixer, name, index);
917 if (kcontrol ==
NULL) {
926 if ((err = kcontrol->
info(kcontrol, info)) < 0) {
940 static void snd_mixer_oss_slot_free(
struct snd_mixer_oss_slot *chn)
942 struct slot *p = chn->private_data;
952 static void mixer_slot_clear(
struct snd_mixer_oss_slot *rslot)
954 int idx = rslot->number;
955 if (rslot->private_free)
956 rslot->private_free(rslot);
957 memset(rslot, 0,
sizeof(*rslot));
963 static int snd_mixer_oss_build_test_all(
struct snd_mixer_oss *mixer,
970 err = snd_mixer_oss_build_test(mixer, slot, ptr->
name, ptr->
index,
975 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
980 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
985 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
990 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
995 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
1000 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
1005 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
1010 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
1015 err = snd_mixer_oss_build_test(mixer, slot, str, ptr->
index,
1028 static int snd_mixer_oss_build_input(
struct snd_mixer_oss *mixer,
struct snd_mixer_oss_assign_table *ptr,
int ptr_allocated,
int replace_old)
1033 struct snd_mixer_oss_slot *rslot;
1037 if (mixer->slots[ptr->
oss_id].get_volume && ! replace_old)
1040 memset(&slot, 0,
sizeof(slot));
1042 if (snd_mixer_oss_build_test_all(mixer, ptr, &slot))
1044 down_read(&mixer->card->controls_rwsem);
1045 if (ptr->
index == 0 && (kctl = snd_mixer_oss_test_id(mixer,
"Capture Source", 0)) !=
NULL) {
1050 up_read(&mixer->card->controls_rwsem);
1054 if (kctl->
info(kctl, uinfo)) {
1055 up_read(&mixer->card->controls_rwsem);
1060 if (!
strcmp(str,
"Master"))
1062 if (!
strcmp(str,
"Master Mono"))
1070 if (kctl->
info(kctl, uinfo)) {
1071 up_read(&mixer->card->controls_rwsem);
1083 up_read(&mixer->card->controls_rwsem);
1092 rslot = &mixer->slots[ptr->
oss_id];
1093 mixer_slot_clear(rslot);
1094 rslot->stereo = slot.
channels > 1 ? 1 : 0;
1095 rslot->get_volume = snd_mixer_oss_get_volume1;
1096 rslot->put_volume = snd_mixer_oss_put_volume1;
1099 rslot->get_recsrc = snd_mixer_oss_get_recsrc1_sw;
1100 rslot->put_recsrc = snd_mixer_oss_put_recsrc1_sw;
1102 rslot->get_recsrc = snd_mixer_oss_get_recsrc1_route;
1103 rslot->put_recsrc = snd_mixer_oss_put_recsrc1_route;
1105 mixer->mask_recsrc |= 1 << ptr->
oss_id;
1107 rslot->private_data = pslot;
1108 rslot->private_free = snd_mixer_oss_slot_free;
1114 #ifdef CONFIG_PROC_FS
1117 #define MIXER_VOL(name) [SOUND_MIXER_##name] = #name
1118 static char *oss_mixer_names[SNDRV_OSS_MAX_MIXERS] = {
1136 MIXER_VOL(DIGITAL1),
1137 MIXER_VOL(DIGITAL2),
1138 MIXER_VOL(DIGITAL3),
1140 MIXER_VOL(PHONEOUT),
1157 for (i = 0; i < SNDRV_OSS_MAX_MIXERS; i++) {
1160 if (! oss_mixer_names[i])
1162 p = (
struct slot *)mixer->slots[i].private_data;
1163 snd_iprintf(buffer,
"%s ", oss_mixer_names[i]);
1165 snd_iprintf(buffer,
"\"%s\" %d\n",
1169 snd_iprintf(buffer,
"\"\" 0\n");
1174 static void snd_mixer_oss_proc_write(
struct snd_info_entry *entry,
1178 char line[128], str[32], idxstr[16];
1184 while (!snd_info_get_line(buffer, line,
sizeof(line))) {
1185 cptr = snd_info_get_str(str, line,
sizeof(str));
1186 for (ch = 0; ch < SNDRV_OSS_MAX_MIXERS; ch++)
1187 if (oss_mixer_names[ch] &&
strcmp(oss_mixer_names[ch], str) == 0)
1189 if (ch >= SNDRV_OSS_MAX_MIXERS) {
1193 cptr = snd_info_get_str(str, cptr,
sizeof(str));
1197 mixer_slot_clear(&mixer->slots[ch]);
1201 snd_info_get_str(idxstr, cptr,
sizeof(idxstr));
1203 if (idx >= 0x4000) {
1208 slot = (
struct slot *)mixer->slots[ch].private_data;
1225 if (snd_mixer_oss_build_input(mixer, tbl, 1, 1) <= 0) {
1238 entry = snd_info_create_card_entry(mixer->card,
"oss_mixer",
1239 mixer->card->proc_root);
1244 entry->
c.
text.read = snd_mixer_oss_proc_read;
1245 entry->
c.
text.write = snd_mixer_oss_proc_write;
1247 if (snd_info_register(entry) < 0) {
1248 snd_info_free_entry(entry);
1251 mixer->proc_entry =
entry;
1256 snd_info_free_entry(mixer->proc_entry);
1257 mixer->proc_entry =
NULL;
1260 #define snd_mixer_oss_proc_init(mix)
1261 #define snd_mixer_oss_proc_done(mix)
1264 static void snd_mixer_oss_build(
struct snd_mixer_oss *mixer)
1308 for (idx = 0; idx <
ARRAY_SIZE(table); idx++)
1309 snd_mixer_oss_build_input(mixer, &table[idx], 0, 0);
1310 if (mixer->mask_recsrc) {
1311 mixer->get_recsrc = snd_mixer_oss_get_recsrc2;
1312 mixer->put_recsrc = snd_mixer_oss_put_recsrc2;
1320 static int snd_mixer_oss_free1(
void *
private)
1322 struct snd_mixer_oss *mixer =
private;
1331 card->mixer_oss =
NULL;
1332 for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++) {
1333 struct snd_mixer_oss_slot *chn = &mixer->slots[
idx];
1334 if (chn->private_free)
1335 chn->private_free(chn);
1341 static int snd_mixer_oss_notify_handler(
struct snd_card *card,
int cmd)
1343 struct snd_mixer_oss *mixer;
1345 if (cmd == SND_MIXER_OSS_NOTIFY_REGISTER) {
1349 mixer = kcalloc(2,
sizeof(*mixer),
GFP_KERNEL);
1354 if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER,
1356 &snd_mixer_oss_f_ops, card,
1363 mixer->oss_dev_alloc = 1;
1368 strlcpy(mixer->name, name,
sizeof(mixer->name));
1369 #ifdef SNDRV_OSS_INFO_DEV_MIXERS
1370 snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS,
1374 for (idx = 0; idx < SNDRV_OSS_MAX_MIXERS; idx++)
1375 mixer->slots[idx].number = idx;
1376 card->mixer_oss = mixer;
1377 snd_mixer_oss_build(mixer);
1380 mixer = card->mixer_oss;
1383 if (mixer->oss_dev_alloc) {
1384 #ifdef SNDRV_OSS_INFO_DEV_MIXERS
1385 snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number);
1387 snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0);
1388 mixer->oss_dev_alloc = 0;
1390 if (cmd == SND_MIXER_OSS_NOTIFY_DISCONNECT)
1393 return snd_mixer_oss_free1(mixer);
1398 static int __init alsa_mixer_oss_init(
void)
1402 snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler;
1405 snd_mixer_oss_notify_handler(
snd_cards[idx], SND_MIXER_OSS_NOTIFY_REGISTER);
1410 static void __exit alsa_mixer_oss_exit(
void)
1414 snd_mixer_oss_notify_callback =
NULL;
1417 snd_mixer_oss_notify_handler(
snd_cards[idx], SND_MIXER_OSS_NOTIFY_FREE);