ALSA: usb - Creative USB X-Fi Pro SB1095 volume knob support
[pandora-kernel.git] / sound / usb / mixer_quirks.c
1 /*
2  *   USB Audio Driver for ALSA
3  *
4  *   Quirks and vendor-specific extensions for mixer interfaces
5  *
6  *   Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
7  *
8  *   Many codes borrowed from audio.c by
9  *          Alan Cox (alan@lxorguk.ukuu.org.uk)
10  *          Thomas Sailer (sailer@ife.ee.ethz.ch)
11  *
12  *
13  *   This program is free software; you can redistribute it and/or modify
14  *   it under the terms of the GNU General Public License as published by
15  *   the Free Software Foundation; either version 2 of the License, or
16  *   (at your option) any later version.
17  *
18  *   This program is distributed in the hope that it will be useful,
19  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  *   GNU General Public License for more details.
22  *
23  *   You should have received a copy of the GNU General Public License
24  *   along with this program; if not, write to the Free Software
25  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
26  */
27
28 #include <linux/init.h>
29 #include <linux/slab.h>
30 #include <linux/usb.h>
31 #include <linux/usb/audio.h>
32
33 #include <sound/core.h>
34 #include <sound/control.h>
35 #include <sound/hwdep.h>
36 #include <sound/info.h>
37
38 #include "usbaudio.h"
39 #include "mixer.h"
40 #include "mixer_quirks.h"
41 #include "helper.h"
42
43 extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
44
45 /*
46  * Sound Blaster remote control configuration
47  *
48  * format of remote control data:
49  * Extigy:       xx 00
50  * Audigy 2 NX:  06 80 xx 00 00 00
51  * Live! 24-bit: 06 80 xx yy 22 83
52  */
53 static const struct rc_config {
54         u32 usb_id;
55         u8  offset;
56         u8  length;
57         u8  packet_length;
58         u8  min_packet_length; /* minimum accepted length of the URB result */
59         u8  mute_mixer_id;
60         u32 mute_code;
61 } rc_configs[] = {
62         { USB_ID(0x041e, 0x3000), 0, 1, 2, 1,  18, 0x0013 }, /* Extigy       */
63         { USB_ID(0x041e, 0x3020), 2, 1, 6, 6,  18, 0x0013 }, /* Audigy 2 NX  */
64         { USB_ID(0x041e, 0x3040), 2, 2, 6, 6,  2,  0x6e91 }, /* Live! 24-bit */
65         { USB_ID(0x041e, 0x3042), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 */
66         { USB_ID(0x041e, 0x30df), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
67         { USB_ID(0x041e, 0x3237), 0, 1, 1, 1,  1,  0x000d }, /* Usb X-Fi S51 Pro */
68         { USB_ID(0x041e, 0x3048), 2, 2, 6, 6,  2,  0x6e91 }, /* Toshiba SB0500 */
69 };
70
71 static void snd_usb_soundblaster_remote_complete(struct urb *urb)
72 {
73         struct usb_mixer_interface *mixer = urb->context;
74         const struct rc_config *rc = mixer->rc_cfg;
75         u32 code;
76
77         if (urb->status < 0 || urb->actual_length < rc->min_packet_length)
78                 return;
79
80         code = mixer->rc_buffer[rc->offset];
81         if (rc->length == 2)
82                 code |= mixer->rc_buffer[rc->offset + 1] << 8;
83
84         /* the Mute button actually changes the mixer control */
85         if (code == rc->mute_code)
86                 snd_usb_mixer_notify_id(mixer, rc->mute_mixer_id);
87         mixer->rc_code = code;
88         wmb();
89         wake_up(&mixer->rc_waitq);
90 }
91
92 static long snd_usb_sbrc_hwdep_read(struct snd_hwdep *hw, char __user *buf,
93                                      long count, loff_t *offset)
94 {
95         struct usb_mixer_interface *mixer = hw->private_data;
96         int err;
97         u32 rc_code;
98
99         if (count != 1 && count != 4)
100                 return -EINVAL;
101         err = wait_event_interruptible(mixer->rc_waitq,
102                                        (rc_code = xchg(&mixer->rc_code, 0)) != 0);
103         if (err == 0) {
104                 if (count == 1)
105                         err = put_user(rc_code, buf);
106                 else
107                         err = put_user(rc_code, (u32 __user *)buf);
108         }
109         return err < 0 ? err : count;
110 }
111
112 static unsigned int snd_usb_sbrc_hwdep_poll(struct snd_hwdep *hw, struct file *file,
113                                             poll_table *wait)
114 {
115         struct usb_mixer_interface *mixer = hw->private_data;
116
117         poll_wait(file, &mixer->rc_waitq, wait);
118         return mixer->rc_code ? POLLIN | POLLRDNORM : 0;
119 }
120
121 static int snd_usb_soundblaster_remote_init(struct usb_mixer_interface *mixer)
122 {
123         struct snd_hwdep *hwdep;
124         int err, len, i;
125
126         for (i = 0; i < ARRAY_SIZE(rc_configs); ++i)
127                 if (rc_configs[i].usb_id == mixer->chip->usb_id)
128                         break;
129         if (i >= ARRAY_SIZE(rc_configs))
130                 return 0;
131         mixer->rc_cfg = &rc_configs[i];
132
133         len = mixer->rc_cfg->packet_length;
134
135         init_waitqueue_head(&mixer->rc_waitq);
136         err = snd_hwdep_new(mixer->chip->card, "SB remote control", 0, &hwdep);
137         if (err < 0)
138                 return err;
139         snprintf(hwdep->name, sizeof(hwdep->name),
140                  "%s remote control", mixer->chip->card->shortname);
141         hwdep->iface = SNDRV_HWDEP_IFACE_SB_RC;
142         hwdep->private_data = mixer;
143         hwdep->ops.read = snd_usb_sbrc_hwdep_read;
144         hwdep->ops.poll = snd_usb_sbrc_hwdep_poll;
145         hwdep->exclusive = 1;
146
147         mixer->rc_urb = usb_alloc_urb(0, GFP_KERNEL);
148         if (!mixer->rc_urb)
149                 return -ENOMEM;
150         mixer->rc_setup_packet = kmalloc(sizeof(*mixer->rc_setup_packet), GFP_KERNEL);
151         if (!mixer->rc_setup_packet) {
152                 usb_free_urb(mixer->rc_urb);
153                 mixer->rc_urb = NULL;
154                 return -ENOMEM;
155         }
156         mixer->rc_setup_packet->bRequestType =
157                 USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
158         mixer->rc_setup_packet->bRequest = UAC_GET_MEM;
159         mixer->rc_setup_packet->wValue = cpu_to_le16(0);
160         mixer->rc_setup_packet->wIndex = cpu_to_le16(0);
161         mixer->rc_setup_packet->wLength = cpu_to_le16(len);
162         usb_fill_control_urb(mixer->rc_urb, mixer->chip->dev,
163                              usb_rcvctrlpipe(mixer->chip->dev, 0),
164                              (u8*)mixer->rc_setup_packet, mixer->rc_buffer, len,
165                              snd_usb_soundblaster_remote_complete, mixer);
166         return 0;
167 }
168
169 #define snd_audigy2nx_led_info          snd_ctl_boolean_mono_info
170
171 static int snd_audigy2nx_led_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
172 {
173         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
174         int index = kcontrol->private_value;
175
176         ucontrol->value.integer.value[0] = mixer->audigy2nx_leds[index];
177         return 0;
178 }
179
180 static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
181 {
182         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
183         int index = kcontrol->private_value;
184         int value = ucontrol->value.integer.value[0];
185         int err, changed;
186
187         if (value > 1)
188                 return -EINVAL;
189         changed = value != mixer->audigy2nx_leds[index];
190         down_read(&mixer->chip->shutdown_rwsem);
191         if (mixer->chip->shutdown) {
192                 err = -ENODEV;
193                 goto out;
194         }
195         if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042))
196                 err = snd_usb_ctl_msg(mixer->chip->dev,
197                               usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
198                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
199                               !value, 0, NULL, 0);
200         /* USB X-Fi S51 Pro */
201         if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
202                 err = snd_usb_ctl_msg(mixer->chip->dev,
203                               usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
204                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
205                               !value, 0, NULL, 0);
206         else
207                 err = snd_usb_ctl_msg(mixer->chip->dev,
208                               usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
209                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
210                               value, index + 2, NULL, 0);
211  out:
212         up_read(&mixer->chip->shutdown_rwsem);
213         if (err < 0)
214                 return err;
215         mixer->audigy2nx_leds[index] = value;
216         return changed;
217 }
218
219 static struct snd_kcontrol_new snd_audigy2nx_controls[] = {
220         {
221                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
222                 .name = "CMSS LED Switch",
223                 .info = snd_audigy2nx_led_info,
224                 .get = snd_audigy2nx_led_get,
225                 .put = snd_audigy2nx_led_put,
226                 .private_value = 0,
227         },
228         {
229                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
230                 .name = "Power LED Switch",
231                 .info = snd_audigy2nx_led_info,
232                 .get = snd_audigy2nx_led_get,
233                 .put = snd_audigy2nx_led_put,
234                 .private_value = 1,
235         },
236         {
237                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
238                 .name = "Dolby Digital LED Switch",
239                 .info = snd_audigy2nx_led_info,
240                 .get = snd_audigy2nx_led_get,
241                 .put = snd_audigy2nx_led_put,
242                 .private_value = 2,
243         },
244 };
245
246 static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer)
247 {
248         int i, err;
249
250         for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) {
251                 /* USB X-Fi S51 doesn't have a CMSS LED */
252                 if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0)
253                         continue;
254                 /* USB X-Fi S51 Pro doesn't have one either */
255                 if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0)
256                         continue;
257                 if (i > 1 && /* Live24ext has 2 LEDs only */
258                         (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
259                          mixer->chip->usb_id == USB_ID(0x041e, 0x3042) ||
260                          mixer->chip->usb_id == USB_ID(0x041e, 0x30df) ||
261                          mixer->chip->usb_id == USB_ID(0x041e, 0x3048)))
262                         break; 
263                 err = snd_ctl_add(mixer->chip->card,
264                                   snd_ctl_new1(&snd_audigy2nx_controls[i], mixer));
265                 if (err < 0)
266                         return err;
267         }
268         mixer->audigy2nx_leds[1] = 1; /* Power LED is on by default */
269         return 0;
270 }
271
272 static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
273                                     struct snd_info_buffer *buffer)
274 {
275         static const struct sb_jack {
276                 int unitid;
277                 const char *name;
278         }  jacks_audigy2nx[] = {
279                 {4,  "dig in "},
280                 {7,  "line in"},
281                 {19, "spk out"},
282                 {20, "hph out"},
283                 {-1, NULL}
284         }, jacks_live24ext[] = {
285                 {4,  "line in"}, /* &1=Line, &2=Mic*/
286                 {3,  "hph out"}, /* headphones */
287                 {0,  "RC     "}, /* last command, 6 bytes see rc_config above */
288                 {-1, NULL}
289         };
290         const struct sb_jack *jacks;
291         struct usb_mixer_interface *mixer = entry->private_data;
292         int i, err;
293         u8 buf[3];
294
295         snd_iprintf(buffer, "%s jacks\n\n", mixer->chip->card->shortname);
296         if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020))
297                 jacks = jacks_audigy2nx;
298         else if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
299                  mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
300                 jacks = jacks_live24ext;
301         else
302                 return;
303
304         for (i = 0; jacks[i].name; ++i) {
305                 snd_iprintf(buffer, "%s: ", jacks[i].name);
306                 down_read(&mixer->chip->shutdown_rwsem);
307                 if (mixer->chip->shutdown)
308                         err = 0;
309                 else
310                         err = snd_usb_ctl_msg(mixer->chip->dev,
311                                       usb_rcvctrlpipe(mixer->chip->dev, 0),
312                                       UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
313                                       USB_RECIP_INTERFACE, 0,
314                                       jacks[i].unitid << 8, buf, 3);
315                 up_read(&mixer->chip->shutdown_rwsem);
316                 if (err == 3 && (buf[0] == 3 || buf[0] == 6))
317                         snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
318                 else
319                         snd_iprintf(buffer, "?\n");
320         }
321 }
322
323 static int snd_xonar_u1_switch_get(struct snd_kcontrol *kcontrol,
324                                    struct snd_ctl_elem_value *ucontrol)
325 {
326         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
327
328         ucontrol->value.integer.value[0] = !!(mixer->xonar_u1_status & 0x02);
329         return 0;
330 }
331
332 static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
333                                    struct snd_ctl_elem_value *ucontrol)
334 {
335         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
336         u8 old_status, new_status;
337         int err, changed;
338
339         old_status = mixer->xonar_u1_status;
340         if (ucontrol->value.integer.value[0])
341                 new_status = old_status | 0x02;
342         else
343                 new_status = old_status & ~0x02;
344         changed = new_status != old_status;
345         down_read(&mixer->chip->shutdown_rwsem);
346         if (mixer->chip->shutdown)
347                 err = -ENODEV;
348         else
349                 err = snd_usb_ctl_msg(mixer->chip->dev,
350                               usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
351                               USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
352                               50, 0, &new_status, 1);
353         up_read(&mixer->chip->shutdown_rwsem);
354         if (err < 0)
355                 return err;
356         mixer->xonar_u1_status = new_status;
357         return changed;
358 }
359
360 static struct snd_kcontrol_new snd_xonar_u1_output_switch = {
361         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
362         .name = "Digital Playback Switch",
363         .info = snd_ctl_boolean_mono_info,
364         .get = snd_xonar_u1_switch_get,
365         .put = snd_xonar_u1_switch_put,
366 };
367
368 static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer)
369 {
370         int err;
371
372         err = snd_ctl_add(mixer->chip->card,
373                           snd_ctl_new1(&snd_xonar_u1_output_switch, mixer));
374         if (err < 0)
375                 return err;
376         mixer->xonar_u1_status = 0x05;
377         return 0;
378 }
379
380 /* Native Instruments device quirks */
381
382 #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex))
383
384 static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol,
385                                              struct snd_ctl_elem_value *ucontrol)
386 {
387         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
388         struct usb_device *dev = mixer->chip->dev;
389         u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
390         u16 wIndex = kcontrol->private_value & 0xffff;
391         u8 tmp;
392         int ret;
393
394         down_read(&mixer->chip->shutdown_rwsem);
395         if (mixer->chip->shutdown)
396                 ret = -ENODEV;
397         else
398                 ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest,
399                                   USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
400                                   0, wIndex,
401                                   &tmp, sizeof(tmp), 1000);
402         up_read(&mixer->chip->shutdown_rwsem);
403
404         if (ret < 0) {
405                 snd_printk(KERN_ERR
406                            "unable to issue vendor read request (ret = %d)", ret);
407                 return ret;
408         }
409
410         ucontrol->value.integer.value[0] = tmp;
411
412         return 0;
413 }
414
415 static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
416                                              struct snd_ctl_elem_value *ucontrol)
417 {
418         struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol);
419         struct usb_device *dev = mixer->chip->dev;
420         u8 bRequest = (kcontrol->private_value >> 16) & 0xff;
421         u16 wIndex = kcontrol->private_value & 0xffff;
422         u16 wValue = ucontrol->value.integer.value[0];
423         int ret;
424
425         down_read(&mixer->chip->shutdown_rwsem);
426         if (mixer->chip->shutdown)
427                 ret = -ENODEV;
428         else
429                 ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest,
430                                   USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT,
431                                   wValue, wIndex,
432                                   NULL, 0, 1000);
433         up_read(&mixer->chip->shutdown_rwsem);
434
435         if (ret < 0) {
436                 snd_printk(KERN_ERR
437                            "unable to issue vendor write request (ret = %d)", ret);
438                 return ret;
439         }
440
441         return 0;
442 }
443
444 static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
445         {
446                 .name = "Direct Thru Channel A",
447                 .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
448         },
449         {
450                 .name = "Direct Thru Channel B",
451                 .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
452         },
453         {
454                 .name = "Phono Input Channel A",
455                 .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
456         },
457         {
458                 .name = "Phono Input Channel B",
459                 .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
460         },
461 };
462
463 static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = {
464         {
465                 .name = "Direct Thru Channel A",
466                 .private_value = _MAKE_NI_CONTROL(0x01, 0x03),
467         },
468         {
469                 .name = "Direct Thru Channel B",
470                 .private_value = _MAKE_NI_CONTROL(0x01, 0x05),
471         },
472         {
473                 .name = "Direct Thru Channel C",
474                 .private_value = _MAKE_NI_CONTROL(0x01, 0x07),
475         },
476         {
477                 .name = "Direct Thru Channel D",
478                 .private_value = _MAKE_NI_CONTROL(0x01, 0x09),
479         },
480         {
481                 .name = "Phono Input Channel A",
482                 .private_value = _MAKE_NI_CONTROL(0x02, 0x03),
483         },
484         {
485                 .name = "Phono Input Channel B",
486                 .private_value = _MAKE_NI_CONTROL(0x02, 0x05),
487         },
488         {
489                 .name = "Phono Input Channel C",
490                 .private_value = _MAKE_NI_CONTROL(0x02, 0x07),
491         },
492         {
493                 .name = "Phono Input Channel D",
494                 .private_value = _MAKE_NI_CONTROL(0x02, 0x09),
495         },
496 };
497
498 static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
499                                               const struct snd_kcontrol_new *kc,
500                                               unsigned int count)
501 {
502         int i, err = 0;
503         struct snd_kcontrol_new template = {
504                 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
505                 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
506                 .get = snd_nativeinstruments_control_get,
507                 .put = snd_nativeinstruments_control_put,
508                 .info = snd_ctl_boolean_mono_info,
509         };
510
511         for (i = 0; i < count; i++) {
512                 struct snd_kcontrol *c;
513
514                 template.name = kc[i].name;
515                 template.private_value = kc[i].private_value;
516
517                 c = snd_ctl_new1(&template, mixer);
518                 err = snd_ctl_add(mixer->chip->card, c);
519
520                 if (err < 0)
521                         break;
522         }
523
524         return err;
525 }
526
527 /* M-Audio FastTrack Ultra quirks */
528
529 /* private_free callback */
530 static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
531 {
532         kfree(kctl->private_data);
533         kctl->private_data = NULL;
534 }
535
536 static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
537                                      int in, int out, const char *name)
538 {
539         struct usb_mixer_elem_info *cval;
540         struct snd_kcontrol *kctl;
541
542         cval = kzalloc(sizeof(*cval), GFP_KERNEL);
543         if (!cval)
544                 return -ENOMEM;
545
546         cval->id = 5;
547         cval->mixer = mixer;
548         cval->val_type = USB_MIXER_S16;
549         cval->channels = 1;
550         cval->control = out + 1;
551         cval->cmask = 1 << in;
552
553         kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
554         if (!kctl) {
555                 kfree(cval);
556                 return -ENOMEM;
557         }
558
559         snprintf(kctl->id.name, sizeof(kctl->id.name), name);
560         kctl->private_free = usb_mixer_elem_free;
561         return snd_usb_mixer_add_control(mixer, kctl);
562 }
563
564 static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer)
565 {
566         char name[64];
567         int in, out, err;
568
569         for (out = 0; out < 8; out++) {
570                 for (in = 0; in < 8; in++) {
571                         snprintf(name, sizeof(name),
572                                  "AIn%d - Out%d Capture Volume", in  + 1, out + 1);
573                         err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
574                         if (err < 0)
575                                 return err;
576                 }
577
578                 for (in = 8; in < 16; in++) {
579                         snprintf(name, sizeof(name),
580                                  "DIn%d - Out%d Playback Volume", in - 7, out + 1);
581                         err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
582                         if (err < 0)
583                                 return err;
584                 }
585         }
586
587         return 0;
588 }
589
590 void snd_emuusb_set_samplerate(struct snd_usb_audio *chip,
591                                unsigned char samplerate_id)
592 {
593         struct usb_mixer_interface *mixer;
594         struct usb_mixer_elem_info *cval;
595         int unitid = 12; /* SamleRate ExtensionUnit ID */
596
597         list_for_each_entry(mixer, &chip->mixer_list, list) {
598                 cval = mixer->id_elems[unitid];
599                 if (cval) {
600                         snd_usb_mixer_set_ctl_value(cval, UAC_SET_CUR,
601                                                     cval->control << 8,
602                                                     samplerate_id);
603                         snd_usb_mixer_notify_id(mixer, unitid);
604                 }
605                 break;
606         }
607 }
608
609 int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
610 {
611         int err = 0;
612         struct snd_info_entry *entry;
613
614         if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0)
615                 return err;
616
617         switch (mixer->chip->usb_id) {
618         case USB_ID(0x041e, 0x3020):
619         case USB_ID(0x041e, 0x3040):
620         case USB_ID(0x041e, 0x3042):
621         case USB_ID(0x041e, 0x30df):
622         case USB_ID(0x041e, 0x3048):
623                 err = snd_audigy2nx_controls_create(mixer);
624                 if (err < 0)
625                         break;
626                 if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry))
627                         snd_info_set_text_ops(entry, mixer,
628                                               snd_audigy2nx_proc_read);
629                 break;
630
631         case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
632         case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
633                 err = snd_maudio_ftu_create_mixer(mixer);
634                 break;
635
636         case USB_ID(0x0b05, 0x1739):
637         case USB_ID(0x0b05, 0x1743):
638                 err = snd_xonar_u1_controls_create(mixer);
639                 break;
640
641         case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */
642                 err = snd_nativeinstruments_create_mixer(mixer,
643                                 snd_nativeinstruments_ta6_mixers,
644                                 ARRAY_SIZE(snd_nativeinstruments_ta6_mixers));
645                 break;
646
647         case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */
648                 err = snd_nativeinstruments_create_mixer(mixer,
649                                 snd_nativeinstruments_ta10_mixers,
650                                 ARRAY_SIZE(snd_nativeinstruments_ta10_mixers));
651                 break;
652         }
653
654         return err;
655 }
656
657 void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer,
658                                     int unitid)
659 {
660         if (!mixer->rc_cfg)
661                 return;
662         /* unit ids specific to Extigy/Audigy 2 NX: */
663         switch (unitid) {
664         case 0: /* remote control */
665                 mixer->rc_urb->dev = mixer->chip->dev;
666                 usb_submit_urb(mixer->rc_urb, GFP_ATOMIC);
667                 break;
668         case 4: /* digital in jack */
669         case 7: /* line in jacks */
670         case 19: /* speaker out jacks */
671         case 20: /* headphones out jack */
672                 break;
673         /* live24ext: 4 = line-in jack */
674         case 3: /* hp-out jack (may actuate Mute) */
675                 if (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) ||
676                     mixer->chip->usb_id == USB_ID(0x041e, 0x3048))
677                         snd_usb_mixer_notify_id(mixer, mixer->rc_cfg->mute_mixer_id);
678                 break;
679         default:
680                 snd_printd(KERN_DEBUG "memory change in unknown unit %d\n", unitid);
681                 break;
682         }
683 }
684