diff options
Diffstat (limited to 'sound/usb/mixer_quirks.c')
-rw-r--r-- | sound/usb/mixer_quirks.c | 210 |
1 files changed, 125 insertions, 85 deletions
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e2072edc7772..1c3da65f1af1 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c | |||
@@ -42,6 +42,85 @@ | |||
42 | 42 | ||
43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; | 43 | extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; |
44 | 44 | ||
45 | /* private_free callback */ | ||
46 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | ||
47 | { | ||
48 | kfree(kctl->private_data); | ||
49 | kctl->private_data = NULL; | ||
50 | } | ||
51 | |||
52 | /* This function allows for the creation of standard UAC controls. | ||
53 | * See the quirks for M-Audio FTUs or Ebox-44. | ||
54 | * If you don't want to set a TLV callback pass NULL. | ||
55 | * | ||
56 | * Since there doesn't seem to be a devices that needs a multichannel | ||
57 | * version, we keep it mono for simplicity. | ||
58 | */ | ||
59 | static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, | ||
60 | unsigned int unitid, | ||
61 | unsigned int control, | ||
62 | unsigned int cmask, | ||
63 | int val_type, | ||
64 | const char *name, | ||
65 | snd_kcontrol_tlv_rw_t *tlv_callback) | ||
66 | { | ||
67 | int err; | ||
68 | struct usb_mixer_elem_info *cval; | ||
69 | struct snd_kcontrol *kctl; | ||
70 | |||
71 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | ||
72 | if (!cval) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | cval->id = unitid; | ||
76 | cval->mixer = mixer; | ||
77 | cval->val_type = val_type; | ||
78 | cval->channels = 1; | ||
79 | cval->control = control; | ||
80 | cval->cmask = cmask; | ||
81 | |||
82 | /* FIXME: Do we need this? | ||
83 | * The following values are for compatibility with | ||
84 | * Ebox-44 mixer. | ||
85 | * But the corresponding ebox-44 function says: | ||
86 | * "Volume controls will override these values" | ||
87 | * | ||
88 | * These values don't have any effect at all for | ||
89 | * M-Audio FTUs. | ||
90 | * So I think, we can safely omit the range settings here. | ||
91 | */ | ||
92 | cval->min = 0; | ||
93 | cval->max = 1; | ||
94 | cval->res = 0; | ||
95 | cval->dBmin = 0; | ||
96 | cval->dBmax = 0; | ||
97 | |||
98 | /* Create control */ | ||
99 | kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); | ||
100 | if (!kctl) { | ||
101 | kfree(cval); | ||
102 | return -ENOMEM; | ||
103 | } | ||
104 | |||
105 | /* Set name */ | ||
106 | snprintf(kctl->id.name, sizeof(kctl->id.name), name); | ||
107 | kctl->private_free = usb_mixer_elem_free; | ||
108 | |||
109 | /* set TLV */ | ||
110 | if (tlv_callback) { | ||
111 | kctl->tlv.c = tlv_callback; | ||
112 | kctl->vd[0].access |= | ||
113 | SNDRV_CTL_ELEM_ACCESS_TLV_READ | | ||
114 | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; | ||
115 | } | ||
116 | /* Add control to mixer */ | ||
117 | err = snd_usb_mixer_add_control(mixer, kctl); | ||
118 | if (err < 0) | ||
119 | return err; | ||
120 | |||
121 | return 0; | ||
122 | } | ||
123 | |||
45 | /* | 124 | /* |
46 | * Sound Blaster remote control configuration | 125 | * Sound Blaster remote control configuration |
47 | * | 126 | * |
@@ -496,59 +575,37 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, | |||
496 | 575 | ||
497 | /* M-Audio FastTrack Ultra quirks */ | 576 | /* M-Audio FastTrack Ultra quirks */ |
498 | 577 | ||
499 | /* private_free callback */ | 578 | /* Create a volume control for FTU devices*/ |
500 | static void usb_mixer_elem_free(struct snd_kcontrol *kctl) | 579 | static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) |
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 | { | 580 | { |
536 | char name[64]; | 581 | char name[64]; |
582 | unsigned int control, cmask; | ||
537 | int in, out, err; | 583 | int in, out, err; |
538 | 584 | ||
585 | const unsigned int id = 5; | ||
586 | const int val_type = USB_MIXER_S16; | ||
587 | |||
539 | for (out = 0; out < 8; out++) { | 588 | for (out = 0; out < 8; out++) { |
589 | control = out + 1; | ||
540 | for (in = 0; in < 8; in++) { | 590 | for (in = 0; in < 8; in++) { |
591 | cmask = 1 << in; | ||
541 | snprintf(name, sizeof(name), | 592 | snprintf(name, sizeof(name), |
542 | "AIn%d - Out%d Capture Volume", in + 1, out + 1); | 593 | "AIn%d - Out%d Capture Volume", |
543 | err = snd_maudio_ftu_create_ctl(mixer, in, out, name); | 594 | in + 1, out + 1); |
595 | err = snd_create_std_mono_ctl(mixer, id, control, | ||
596 | cmask, val_type, name, | ||
597 | NULL); | ||
544 | if (err < 0) | 598 | if (err < 0) |
545 | return err; | 599 | return err; |
546 | } | 600 | } |
547 | |||
548 | for (in = 8; in < 16; in++) { | 601 | for (in = 8; in < 16; in++) { |
602 | cmask = 1 << in; | ||
549 | snprintf(name, sizeof(name), | 603 | snprintf(name, sizeof(name), |
550 | "DIn%d - Out%d Playback Volume", in - 7, out + 1); | 604 | "DIn%d - Out%d Playback Volume", |
551 | err = snd_maudio_ftu_create_ctl(mixer, in, out, name); | 605 | in - 7, out + 1); |
606 | err = snd_create_std_mono_ctl(mixer, id, control, | ||
607 | cmask, val_type, name, | ||
608 | NULL); | ||
552 | if (err < 0) | 609 | if (err < 0) |
553 | return err; | 610 | return err; |
554 | } | 611 | } |
@@ -557,44 +614,18 @@ static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) | |||
557 | return 0; | 614 | return 0; |
558 | } | 615 | } |
559 | 616 | ||
560 | static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer, | 617 | static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) |
561 | int unitid, int control, int cmask, | ||
562 | int val_type, const char *name) | ||
563 | { | 618 | { |
564 | struct usb_mixer_elem_info *cval; | 619 | int err; |
565 | struct snd_kcontrol *kctl; | ||
566 | |||
567 | cval = kzalloc(sizeof(*cval), GFP_KERNEL); | ||
568 | if (!cval) | ||
569 | return -ENOMEM; | ||
570 | |||
571 | cval->id = unitid; | ||
572 | cval->mixer = mixer; | ||
573 | |||
574 | cval->val_type = val_type; | ||
575 | cval->channels = 1; | ||
576 | cval->control = control; | ||
577 | cval->cmask = cmask; | ||
578 | |||
579 | /* Volume controls will override these values */ | ||
580 | cval->min = 0; | ||
581 | cval->max = 1; | ||
582 | cval->res = 0; | ||
583 | |||
584 | cval->dBmin = 0; | ||
585 | cval->dBmax = 0; | ||
586 | 620 | ||
587 | kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); | 621 | err = snd_maudio_ftu_create_volume_ctls(mixer); |
588 | if (!kctl) { | 622 | if (err < 0) |
589 | kfree(cval); | 623 | return err; |
590 | return -ENOMEM; | ||
591 | } | ||
592 | 624 | ||
593 | snprintf(kctl->id.name, sizeof(kctl->id.name), name); | 625 | return 0; |
594 | kctl->private_free = usb_mixer_elem_free; | ||
595 | return snd_usb_mixer_add_control(mixer, kctl); | ||
596 | } | 626 | } |
597 | 627 | ||
628 | |||
598 | /* | 629 | /* |
599 | * Create mixer for Electrix Ebox-44 | 630 | * Create mixer for Electrix Ebox-44 |
600 | * | 631 | * |
@@ -605,17 +636,26 @@ static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer, | |||
605 | 636 | ||
606 | static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) | 637 | static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) |
607 | { | 638 | { |
608 | snd_ebox44_create_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch"); | 639 | snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, |
609 | snd_ebox44_create_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume"); | 640 | "Headphone Playback Switch", NULL); |
610 | snd_ebox44_create_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume"); | 641 | snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, |
611 | 642 | "Headphone A Mix Playback Volume", NULL); | |
612 | snd_ebox44_create_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch"); | 643 | snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, |
613 | snd_ebox44_create_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume"); | 644 | "Headphone B Mix Playback Volume", NULL); |
614 | snd_ebox44_create_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume"); | 645 | |
615 | 646 | snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, | |
616 | snd_ebox44_create_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch"); | 647 | "Output Playback Switch", NULL); |
617 | snd_ebox44_create_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume"); | 648 | snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, |
618 | snd_ebox44_create_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume"); | 649 | "Output A Playback Volume", NULL); |
650 | snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, | ||
651 | "Output B Playback Volume", NULL); | ||
652 | |||
653 | snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, | ||
654 | "Input Capture Switch", NULL); | ||
655 | snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, | ||
656 | "Input A Capture Volume", NULL); | ||
657 | snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, | ||
658 | "Input B Capture Volume", NULL); | ||
619 | 659 | ||
620 | return 0; | 660 | return 0; |
621 | } | 661 | } |