diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /sound/usb/mixer_quirks.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'sound/usb/mixer_quirks.c')
-rw-r--r-- | sound/usb/mixer_quirks.c | 268 |
1 files changed, 255 insertions, 13 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e7df1e5e3f2e..3d0f4873112b 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -40,6 +40,8 @@ | |||
40 | #include "mixer_quirks.h" | 40 | #include "mixer_quirks.h" |
41 | #include "helper.h" | 41 | #include "helper.h" |
42 | 42 | ||
43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; | ||
44 | |||
43 | /* | 45 | /* |
44 | * Sound Blaster remote control configuration | 46 | * Sound Blaster remote control configuration |
45 | * | 47 | * |
@@ -60,6 +62,8 @@ static const struct rc_config { | |||
60 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ | 62 | { USB_ID(0x041e, 0x3000), 0, 1, 2, 1, 18, 0x0013 }, /* Extigy */ |
61 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ | 63 | { USB_ID(0x041e, 0x3020), 2, 1, 6, 6, 18, 0x0013 }, /* Audigy 2 NX */ |
62 | { USB_ID(0x041e, 0x3040), 2, 2, 6, 6, 2, 0x6e91 }, /* Live! 24-bit */ | 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 */ | ||
63 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ | 67 | { USB_ID(0x041e, 0x3048), 2, 2, 6, 6, 2, 0x6e91 }, /* Toshiba SB0500 */ |
64 | }; | 68 | }; |
65 | 69 | ||
@@ -182,7 +186,19 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e | |||
182 | if (value > 1) | 186 | if (value > 1) |
183 | return -EINVAL; | 187 | return -EINVAL; |
184 | changed = value != mixer->audigy2nx_leds[index]; | 188 | changed = value != mixer->audigy2nx_leds[index]; |
185 | err = snd_usb_ctl_msg(mixer->chip->dev, | 189 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) |
190 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
191 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | ||
192 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | ||
193 | !value, 0, NULL, 0, 100); | ||
194 | /* USB X-Fi S51 Pro */ | ||
195 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) | ||
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, 100); | ||
200 | else | ||
201 | err = snd_usb_ctl_msg(mixer->chip->dev, | ||
186 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, | 202 | usb_sndctrlpipe(mixer->chip->dev, 0), 0x24, |
187 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, | 203 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER, |
188 | value, index + 2, NULL, 0, 100); | 204 | value, index + 2, NULL, 0, 100); |
@@ -224,8 +240,16 @@ static int snd_audigy2nx_controls_create(struct usb_mixer_interface *mixer) | |||
224 | int i, err; | 240 | int i, err; |
225 | 241 | ||
226 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { | 242 | for (i = 0; i < ARRAY_SIZE(snd_audigy2nx_controls); ++i) { |
243 | /* USB X-Fi S51 doesn't have a CMSS LED */ | ||
244 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x3042)) && i == 0) | ||
245 | continue; | ||
246 | /* USB X-Fi S51 Pro doesn't have one either */ | ||
247 | if ((mixer->chip->usb_id == USB_ID(0x041e, 0x30df)) && i == 0) | ||
248 | continue; | ||
227 | if (i > 1 && /* Live24ext has 2 LEDs only */ | 249 | if (i > 1 && /* Live24ext has 2 LEDs only */ |
228 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 250 | (mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || |
251 | mixer->chip->usb_id == USB_ID(0x041e, 0x3042) || | ||
252 | mixer->chip->usb_id == USB_ID(0x041e, 0x30df) || | ||
229 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) | 253 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048))) |
230 | break; | 254 | break; |
231 | err = snd_ctl_add(mixer->chip->card, | 255 | err = snd_ctl_add(mixer->chip->card, |
@@ -335,6 +359,204 @@ static int snd_xonar_u1_controls_create(struct usb_mixer_interface *mixer) | |||
335 | return 0; | 359 | return 0; |
336 | } | 360 | } |
337 | 361 | ||
362 | /* Native Instruments device quirks */ | ||
363 | |||
364 | #define _MAKE_NI_CONTROL(bRequest,wIndex) ((bRequest) << 16 | (wIndex)) | ||
365 | |||
366 | static int snd_nativeinstruments_control_get(struct snd_kcontrol *kcontrol, | ||
367 | struct snd_ctl_elem_value *ucontrol) | ||
368 | { | ||
369 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
370 | struct usb_device *dev = mixer->chip->dev; | ||
371 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
372 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
373 | u8 tmp; | ||
374 | |||
375 | int ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), bRequest, | ||
376 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, | ||
377 | 0, cpu_to_le16(wIndex), | ||
378 | &tmp, sizeof(tmp), 1000); | ||
379 | |||
380 | if (ret < 0) { | ||
381 | snd_printk(KERN_ERR | ||
382 | "unable to issue vendor read request (ret = %d)", ret); | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | ucontrol->value.integer.value[0] = tmp; | ||
387 | |||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol, | ||
392 | struct snd_ctl_elem_value *ucontrol) | ||
393 | { | ||
394 | struct usb_mixer_interface *mixer = snd_kcontrol_chip(kcontrol); | ||
395 | struct usb_device *dev = mixer->chip->dev; | ||
396 | u8 bRequest = (kcontrol->private_value >> 16) & 0xff; | ||
397 | u16 wIndex = kcontrol->private_value & 0xffff; | ||
398 | u16 wValue = ucontrol->value.integer.value[0]; | ||
399 | |||
400 | int ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), bRequest, | ||
401 | USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, | ||
402 | cpu_to_le16(wValue), cpu_to_le16(wIndex), | ||
403 | NULL, 0, 1000); | ||
404 | |||
405 | if (ret < 0) { | ||
406 | snd_printk(KERN_ERR | ||
407 | "unable to issue vendor write request (ret = %d)", ret); | ||
408 | return ret; | ||
409 | } | ||
410 | |||
411 | return 0; | ||
412 | } | ||
413 | |||
414 | static struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = { | ||
415 | { | ||
416 | .name = "Direct Thru Channel A", | ||
417 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
418 | }, | ||
419 | { | ||
420 | .name = "Direct Thru Channel B", | ||
421 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
422 | }, | ||
423 | { | ||
424 | .name = "Phono Input Channel A", | ||
425 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
426 | }, | ||
427 | { | ||
428 | .name = "Phono Input Channel B", | ||
429 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
430 | }, | ||
431 | }; | ||
432 | |||
433 | static struct snd_kcontrol_new snd_nativeinstruments_ta10_mixers[] = { | ||
434 | { | ||
435 | .name = "Direct Thru Channel A", | ||
436 | .private_value = _MAKE_NI_CONTROL(0x01, 0x03), | ||
437 | }, | ||
438 | { | ||
439 | .name = "Direct Thru Channel B", | ||
440 | .private_value = _MAKE_NI_CONTROL(0x01, 0x05), | ||
441 | }, | ||
442 | { | ||
443 | .name = "Direct Thru Channel C", | ||
444 | .private_value = _MAKE_NI_CONTROL(0x01, 0x07), | ||
445 | }, | ||
446 | { | ||
447 | .name = "Direct Thru Channel D", | ||
448 | .private_value = _MAKE_NI_CONTROL(0x01, 0x09), | ||
449 | }, | ||
450 | { | ||
451 | .name = "Phono Input Channel A", | ||
452 | .private_value = _MAKE_NI_CONTROL(0x02, 0x03), | ||
453 | }, | ||
454 | { | ||
455 | .name = "Phono Input Channel B", | ||
456 | .private_value = _MAKE_NI_CONTROL(0x02, 0x05), | ||
457 | }, | ||
458 | { | ||
459 | .name = "Phono Input Channel C", | ||
460 | .private_value = _MAKE_NI_CONTROL(0x02, 0x07), | ||
461 | }, | ||
462 | { | ||
463 | .name = "Phono Input Channel D", | ||
464 | .private_value = _MAKE_NI_CONTROL(0x02, 0x09), | ||
465 | }, | ||
466 | }; | ||
467 | |||
468 | static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | ||
469 | const struct snd_kcontrol_new *kc, | ||
470 | unsigned int count) | ||
471 | { | ||
472 | int i, err = 0; | ||
473 | struct snd_kcontrol_new template = { | ||
474 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
475 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, | ||
476 | .get = snd_nativeinstruments_control_get, | ||
477 | .put = snd_nativeinstruments_control_put, | ||
478 | .info = snd_ctl_boolean_mono_info, | ||
479 | }; | ||
480 | |||
481 | for (i = 0; i < count; i++) { | ||
482 | struct snd_kcontrol *c; | ||
483 | |||
484 | template.name = kc[i].name; | ||
485 | template.private_value = kc[i].private_value; | ||
486 | |||
487 | c = snd_ctl_new1(&template, mixer); | ||
488 | err = snd_ctl_add(mixer->chip->card, c); | ||
489 | |||
490 | if (err < 0) | ||
491 | break; | ||
492 | } | ||
493 | |||
494 | return err; | ||
495 | } | ||
496 | |||
497 | /* M-Audio FastTrack Ultra quirks */ | ||
498 | |||
499 | /* private_free callback */ | ||
500 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | ||
501 | { | ||
502 | kfree(kctl->private_data); | ||
503 | kctl->private_data = NULL; | ||
504 | } | ||
505 | |||
506 | static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer, | ||
507 | int in, int out, const char *name) | ||
508 | { | ||
509 | struct usb_mixer_elem_info *cval; | ||
510 | struct snd_kcontrol *kctl; | ||
511 | |||
512 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | ||
513 | if (!cval) | ||
514 | return -ENOMEM; | ||
515 | |||
516 | cval->id = 5; | ||
517 | cval->mixer = mixer; | ||
518 | cval->val_type = USB_MIXER_S16; | ||
519 | cval->channels = 1; | ||
520 | cval->control = out + 1; | ||
521 | cval->cmask = 1 << in; | ||
522 | |||
523 | kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); | ||
524 | if (!kctl) { | ||
525 | kfree(cval); | ||
526 | return -ENOMEM; | ||
527 | } | ||
528 | |||
529 | snprintf(kctl->id.name, sizeof(kctl->id.name), name); | ||
530 | kctl->private_free = usb_mixer_elem_free; | ||
531 | return snd_usb_mixer_add_control(mixer, kctl); | ||
532 | } | ||
533 | |||
534 | static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) | ||
535 | { | ||
536 | char name[64]; | ||
537 | int in, out, err; | ||
538 | |||
539 | for (out = 0; out < 8; out++) { | ||
540 | for (in = 0; in < 8; in++) { | ||
541 | snprintf(name, sizeof(name), | ||
542 | "AIn%d - Out%d Capture Volume", in + 1, out + 1); | ||
543 | err = snd_maudio_ftu_create_ctl(mixer, in, out, name); | ||
544 | if (err < 0) | ||
545 | return err; | ||
546 | } | ||
547 | |||
548 | for (in = 8; in < 16; in++) { | ||
549 | snprintf(name, sizeof(name), | ||
550 | "DIn%d - Out%d Playback Volume", in - 7, out + 1); | ||
551 | err = snd_maudio_ftu_create_ctl(mixer, in, out, name); | ||
552 | if (err < 0) | ||
553 | return err; | ||
554 | } | ||
555 | } | ||
556 | |||
557 | return 0; | ||
558 | } | ||
559 | |||
338 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | 560 | void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, |
339 | unsigned char samplerate_id) | 561 | unsigned char samplerate_id) |
340 | { | 562 | { |
@@ -356,30 +578,50 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, | |||
356 | 578 | ||
357 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) | 579 | int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) |
358 | { | 580 | { |
359 | int err; | 581 | int err = 0; |
360 | struct snd_info_entry *entry; | 582 | struct snd_info_entry *entry; |
361 | 583 | ||
362 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) | 584 | if ((err = snd_usb_soundblaster_remote_init(mixer)) < 0) |
363 | return err; | 585 | return err; |
364 | 586 | ||
365 | if (mixer->chip->usb_id == USB_ID(0x041e, 0x3020) || | 587 | switch (mixer->chip->usb_id) { |
366 | mixer->chip->usb_id == USB_ID(0x041e, 0x3040) || | 588 | case USB_ID(0x041e, 0x3020): |
367 | mixer->chip->usb_id == USB_ID(0x041e, 0x3048)) { | 589 | case USB_ID(0x041e, 0x3040): |
368 | if ((err = snd_audigy2nx_controls_create(mixer)) < 0) | 590 | case USB_ID(0x041e, 0x3042): |
369 | return err; | 591 | case USB_ID(0x041e, 0x30df): |
592 | case USB_ID(0x041e, 0x3048): | ||
593 | err = snd_audigy2nx_controls_create(mixer); | ||
594 | if (err < 0) | ||
595 | break; | ||
370 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) | 596 | if (!snd_card_proc_new(mixer->chip->card, "audigy2nx", &entry)) |
371 | snd_info_set_text_ops(entry, mixer, | 597 | snd_info_set_text_ops(entry, mixer, |
372 | snd_audigy2nx_proc_read); | 598 | snd_audigy2nx_proc_read); |
373 | } | 599 | break; |
374 | 600 | ||
375 | if (mixer->chip->usb_id == USB_ID(0x0b05, 0x1739) || | 601 | case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ |
376 | mixer->chip->usb_id == USB_ID(0x0b05, 0x1743)) { | 602 | case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ |
603 | err = snd_maudio_ftu_create_mixer(mixer); | ||
604 | break; | ||
605 | |||
606 | case USB_ID(0x0b05, 0x1739): | ||
607 | case USB_ID(0x0b05, 0x1743): | ||
377 | err = snd_xonar_u1_controls_create(mixer); | 608 | err = snd_xonar_u1_controls_create(mixer); |
378 | if (err < 0) | 609 | break; |
379 | return err; | 610 | |
611 | case USB_ID(0x17cc, 0x1011): /* Traktor Audio 6 */ | ||
612 | err = snd_nativeinstruments_create_mixer(mixer, | ||
613 | snd_nativeinstruments_ta6_mixers, | ||
614 | ARRAY_SIZE(snd_nativeinstruments_ta6_mixers)); | ||
615 | break; | ||
616 | |||
617 | case USB_ID(0x17cc, 0x1021): /* Traktor Audio 10 */ | ||
618 | err = snd_nativeinstruments_create_mixer(mixer, | ||
619 | snd_nativeinstruments_ta10_mixers, | ||
620 | ARRAY_SIZE(snd_nativeinstruments_ta10_mixers)); | ||
621 | break; | ||
380 | } | 622 | } |
381 | 623 | ||
382 | return 0; | 624 | return err; |
383 | } | 625 | } |
384 | 626 | ||
385 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, | 627 | void snd_usb_mixer_rc_memory_change(struct usb_mixer_interface *mixer, |