[alsa-devel] [RFC] usb-audio: Use a table of mixer controls
Allow mixer controls to be provided clearly in a table, to avoid quantity of error checking at each use.
This is definitely clearer than the current code. But going forward, how should this work with the tables defined in mixer_maps.c?
I've made this generic and tried to follow existing conventions for similar tables (eg. use a terminator, not array size), comments welcome. --- sound/usb/mixer_quirks.c | 104 +++++++++++++++++++++------------------------- 1 files changed, 48 insertions(+), 56 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b69..b80b7e7 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,13 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+struct std_mono_table { + unsigned int unitid, control, cmask; + int val_type; + const char *name; + snd_kcontrol_tlv_rw_t *tlv_callback; +}; + /* private_free callback */ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) { @@ -114,6 +121,24 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, }
/* + * Create a set of standard UAC controls from a table + */ +static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, + struct std_mono_table *t) +{ + int err; + + while (t->name != NULL) { + err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, + t->cmask, t->val_type, t->name, t->tlv_callback); + if (err < 0) + return err; + } + + return 0; +} + +/* * Sound Blaster remote control configuration * * format of remote control data: @@ -916,61 +941,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
- -/* - * Create mixer for Electrix Ebox-44 - * - * The mixer units from this device are corrupt, and even where they - * are valid they presents mono controls as L and R channels of - * stereo. So we create a good mixer in code. - */ - -static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) -{ - int err; - - err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Headphone Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, - "Headphone A Mix Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, - "Headphone B Mix Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Output Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, - "Output A Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, - "Output B Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Input Capture Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, - "Input A Capture Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, - "Input B Capture Volume", NULL); - if (err < 0) - return err; - - return 0; -} - void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -990,6 +960,27 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } }
+/* + * The mixer units for Ebox-44 are corrupt, and even where they + * are valid they presents mono controls as L and R channels of + * stereo. So we create provide a good mixer here. + */ +struct std_mono_table ebox44_table[] = { + { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL }, + { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL }, + { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL }, + + { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL }, + { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL }, + { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL }, + + { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL }, + { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL }, + { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL }, + + { } +}; + int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1035,7 +1026,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break;
case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ - err = snd_ebox44_create_mixer(mixer); + /* detection is disabled in mixer_maps.c */ + err = snd_create_std_mono_table(mixer, ebox44_table); break; }
At Fri, 11 May 2012 18:28:48 +0100, Mark Hills wrote:
Allow mixer controls to be provided clearly in a table, to avoid quantity of error checking at each use.
This is definitely clearer than the current code. But going forward, how should this work with the tables defined in mixer_maps.c?
Yeah, this looks definitely better.
I've made this generic and tried to follow existing conventions for similar tables (eg. use a terminator, not array size), comments welcome.
sound/usb/mixer_quirks.c | 104 +++++++++++++++++++++------------------------- 1 files changed, 48 insertions(+), 56 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b69..b80b7e7 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,13 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+struct std_mono_table {
- unsigned int unitid, control, cmask;
- int val_type;
- const char *name;
- snd_kcontrol_tlv_rw_t *tlv_callback;
+};
/* private_free callback */ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) { @@ -114,6 +121,24 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, }
/*
- Create a set of standard UAC controls from a table
- */
+static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
struct std_mono_table *t)
+{
- int err;
- while (t->name != NULL) {
err = snd_create_std_mono_ctl(mixer, t->unitid, t->control,
t->cmask, t->val_type, t->name, t->tlv_callback);
if (err < 0)
return err;
t++ is missing?
- }
- return 0;
+}
+/*
- Sound Blaster remote control configuration
- format of remote control data:
@@ -916,61 +941,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
-/*
- Create mixer for Electrix Ebox-44
- The mixer units from this device are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create a good mixer in code.
- */
-static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) -{
- int err;
- err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Headphone Playback Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
"Headphone A Mix Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
"Headphone B Mix Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Output Playback Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
"Output A Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
"Output B Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Input Capture Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
"Input A Capture Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
"Input B Capture Volume", NULL);
- if (err < 0)
return err;
- return 0;
-}
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -990,6 +960,27 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } }
+/*
- The mixer units for Ebox-44 are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create provide a good mixer here.
- */
+struct std_mono_table ebox44_table[] = {
- { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL },
- { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL },
- { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL },
- { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL },
- { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL },
- { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL },
- { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL },
- { }
C99 style struct initialization is preferred. Then NULL settings can be omittted.
Other than that, it looks fine to me.
thanks,
Takashi
+};
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1035,7 +1026,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break;
case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */
err = snd_ebox44_create_mixer(mixer);
/* detection is disabled in mixer_maps.c */
break; }err = snd_create_std_mono_table(mixer, ebox44_table);
-- 1.7.4.4
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
On Fri, 11 May 2012, Takashi Iwai wrote:
[...]
/*
- Create a set of standard UAC controls from a table
- */
+static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
struct std_mono_table *t)
+{
- int err;
- while (t->name != NULL) {
err = snd_create_std_mono_ctl(mixer, t->unitid, t->control,
t->cmask, t->val_type, t->name, t->tlv_callback);
if (err < 0)
return err;
t++ is missing?
Hmm, yes. A clear indication that the code I must have not tested the correct code (originally I used ARRAY_SIZE)
I'll make sure to confirm this before I submit a proper patch.
[...]
+/*
- The mixer units for Ebox-44 are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create provide a good mixer here.
- */
+struct std_mono_table ebox44_table[] = {
- { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL },
- { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL },
- { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL },
- { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL },
- { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL },
- { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL },
- { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL },
- { }
C99 style struct initialization is preferred. Then NULL settings can be omittted.
Do you mean like this?
ebox44_table[] = { { .unitid = 4, .control = 1 .cmask = 0x0 /* etc. */ }
Because then it becomes a lot less concise and a lot less readable? Of course, if there are more optional params in the future, then maybe.
IIRC, I could omit the NULL anyway, because static memory is initialised to contain zeroes (hence the "{ }" works). Am I correct? It's late, I might be mistaken.
Other than that, it looks fine to me.
Thanks for comments.
At Sat, 12 May 2012 00:21:14 +0100 (BST), Mark Hills wrote:
On Fri, 11 May 2012, Takashi Iwai wrote:
+/*
- The mixer units for Ebox-44 are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create provide a good mixer here.
- */
+struct std_mono_table ebox44_table[] = {
- { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL },
- { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL },
- { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL },
- { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL },
- { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL },
- { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL },
- { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL },
- { }
C99 style struct initialization is preferred. Then NULL settings can be omittted.
Do you mean like this?
ebox44_table[] = { { .unitid = 4, .control = 1 .cmask = 0x0 /* etc. */ }
Because then it becomes a lot less concise and a lot less readable?
I can't count fields more than two, so to me, C99 style is more readable :)
Of course, if there are more optional params in the future, then maybe.
Yep.
IIRC, I could omit the NULL anyway, because static memory is initialised to contain zeroes (hence the "{ }" works). Am I correct? It's late, I might be mistaken.
Yes. But it's not recommended much, when you think of adding a new field.
Takashi
On Sat, 12 May 2012, Takashi Iwai wrote:
At Sat, 12 May 2012 00:21:14 +0100 (BST), Mark Hills wrote:
On Fri, 11 May 2012, Takashi Iwai wrote:
+/*
- The mixer units for Ebox-44 are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create provide a good mixer here.
- */
+struct std_mono_table ebox44_table[] = {
- { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL },
- { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL },
- { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL },
- { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL },
- { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL },
- { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL },
- { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL },
- { }
C99 style struct initialization is preferred. Then NULL settings can be omittted.
Do you mean like this?
ebox44_table[] = { { .unitid = 4, .control = 1 .cmask = 0x0 /* etc. */ }
Because then it becomes a lot less concise and a lot less readable?
I can't count fields more than two, so to me, C99 style is more readable :)
I know you can count more than two, because I see you do it with function calls all the time :-)
Nevertheless, I'll follow-up with revised (and tested) patches, ready for inclusion.
Of course, if there are more optional params in the future, then maybe.
Yep.
I see now in doing this that likely to happen is that the table becomes a full 'quirks' table with a mix of mono and stereo entries etc..
[...]
Takashi
Allow mixer controls to be provided clearly in a table, to avoid quantity of error checking at each use.
Signed-off-by: Mark Hills mark@pogo.org.uk --- sound/usb/mixer_quirks.c | 105 +++++++++++++++++++++------------------------ 1 files changed, 49 insertions(+), 56 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b69..ce7d96f 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,13 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+struct std_mono_table { + unsigned int unitid, control, cmask; + int val_type; + const char *name; + snd_kcontrol_tlv_rw_t *tlv_callback; +}; + /* private_free callback */ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) { @@ -114,6 +121,25 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, }
/* + * Create a set of standard UAC controls from a table + */ +static int snd_create_std_mono_table(struct usb_mixer_interface *mixer, + struct std_mono_table *t) +{ + int err; + + while (t->name != NULL) { + err = snd_create_std_mono_ctl(mixer, t->unitid, t->control, + t->cmask, t->val_type, t->name, t->tlv_callback); + if (err < 0) + return err; + t++; + } + + return 0; +} + +/* * Sound Blaster remote control configuration * * format of remote control data: @@ -916,61 +942,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
- -/* - * Create mixer for Electrix Ebox-44 - * - * The mixer units from this device are corrupt, and even where they - * are valid they presents mono controls as L and R channels of - * stereo. So we create a good mixer in code. - */ - -static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) -{ - int err; - - err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Headphone Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, - "Headphone A Mix Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, - "Headphone B Mix Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Output Playback Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, - "Output A Playback Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, - "Output B Playback Volume", NULL); - if (err < 0) - return err; - - err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, - "Input Capture Switch", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, - "Input A Capture Volume", NULL); - if (err < 0) - return err; - err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, - "Input B Capture Volume", NULL); - if (err < 0) - return err; - - return 0; -} - void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -990,6 +961,27 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } }
+/* + * The mixer units for Ebox-44 are corrupt, and even where they + * are valid they presents mono controls as L and R channels of + * stereo. So we provide a good mixer here. + */ +struct std_mono_table ebox44_table[] = { + { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL }, + { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL }, + { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL }, + + { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL }, + { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL }, + { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL }, + + { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL }, + { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL }, + { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL }, + + { } +}; + int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1035,7 +1027,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break;
case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */ - err = snd_ebox44_create_mixer(mixer); + /* detection is disabled in mixer_maps.c */ + err = snd_create_std_mono_table(mixer, ebox44_table); break; }
Signed-off-by: Mark Hills mark@pogo.org.uk --- sound/usb/mixer_quirks.c | 74 +++++++++++++++++++++++++++++++++++++++------ 1 files changed, 64 insertions(+), 10 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index ce7d96f..690000d 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -967,19 +967,73 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, * stereo. So we provide a good mixer here. */ struct std_mono_table ebox44_table[] = { - { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL }, - { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL }, - { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL }, + { + .unitid = 4, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Headphone Playback Switch" + }, + { + .unitid = 4, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Headphone A Mix Playback Volume" + }, + { + .unitid = 4, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Headphone B Mix Playback Volume" + },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL }, - { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL }, - { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL }, + { + .unitid = 7, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Output Playback Switch" + }, + { + .unitid = 7, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Output A Playback Volume" + }, + { + .unitid = 7, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Output B Playback Volume" + },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL }, - { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL }, - { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL }, + { + .unitid = 10, + .control = 1, + .cmask = 0x0, + .val_type = USB_MIXER_INV_BOOLEAN, + .name = "Input Capture Switch" + }, + { + .unitid = 10, + .control = 2, + .cmask = 0x1, + .val_type = USB_MIXER_S16, + .name = "Input A Capture Volume" + }, + { + .unitid = 10, + .control = 2, + .cmask = 0x2, + .val_type = USB_MIXER_S16, + .name = "Input B Capture Volume" + },
- { } + {} };
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
At Sat, 9 Jun 2012 13:16:38 +0100, Mark Hills wrote:
Allow mixer controls to be provided clearly in a table, to avoid quantity of error checking at each use.
Signed-off-by: Mark Hills mark@pogo.org.uk
Applied both patches now. Thanks.
Takashi
sound/usb/mixer_quirks.c | 105 +++++++++++++++++++++------------------------ 1 files changed, 49 insertions(+), 56 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 41f4b69..ce7d96f 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,13 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+struct std_mono_table {
- unsigned int unitid, control, cmask;
- int val_type;
- const char *name;
- snd_kcontrol_tlv_rw_t *tlv_callback;
+};
/* private_free callback */ static void usb_mixer_elem_free(struct snd_kcontrol *kctl) { @@ -114,6 +121,25 @@ static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, }
/*
- Create a set of standard UAC controls from a table
- */
+static int snd_create_std_mono_table(struct usb_mixer_interface *mixer,
struct std_mono_table *t)
+{
- int err;
- while (t->name != NULL) {
err = snd_create_std_mono_ctl(mixer, t->unitid, t->control,
t->cmask, t->val_type, t->name, t->tlv_callback);
if (err < 0)
return err;
t++;
- }
- return 0;
+}
+/*
- Sound Blaster remote control configuration
- format of remote control data:
@@ -916,61 +942,6 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
-/*
- Create mixer for Electrix Ebox-44
- The mixer units from this device are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we create a good mixer in code.
- */
-static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) -{
- int err;
- err = snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Headphone Playback Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
"Headphone A Mix Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
"Headphone B Mix Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Output Playback Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
"Output A Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
"Output B Playback Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Input Capture Switch", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
"Input A Capture Volume", NULL);
- if (err < 0)
return err;
- err = snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
"Input B Capture Volume", NULL);
- if (err < 0)
return err;
- return 0;
-}
void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -990,6 +961,27 @@ void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, } }
+/*
- The mixer units for Ebox-44 are corrupt, and even where they
- are valid they presents mono controls as L and R channels of
- stereo. So we provide a good mixer here.
- */
+struct std_mono_table ebox44_table[] = {
- { 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch", NULL },
- { 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume", NULL },
- { 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume", NULL },
- { 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch", NULL },
- { 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume", NULL },
- { 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume", NULL },
- { 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch", NULL },
- { 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume", NULL },
- { 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume", NULL },
- { }
+};
int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) { int err = 0; @@ -1035,7 +1027,8 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) break;
case USB_ID(0x200c, 0x1018): /* Electrix Ebox-44 */
err = snd_ebox44_create_mixer(mixer);
/* detection is disabled in mixer_maps.c */
break; }err = snd_create_std_mono_table(mixer, ebox44_table);
-- 1.7.4.4
Alsa-devel mailing list Alsa-devel@alsa-project.org http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
participants (2)
-
Mark Hills
-
Takashi Iwai