aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/mixer_quirks.c210
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
43extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; 43extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
44 44
45/* private_free callback */
46static 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 */
59static 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*/
500static void usb_mixer_elem_free(struct snd_kcontrol *kctl) 579static 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
506static 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
534static 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
560static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer, 617static 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
606static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) 637static 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}