[alsa-devel] [PATCH 0/7] Alsa: snd-usb: Improve M-Audio Fast Track Ultra mixer - v2
This is the second try on a series of patches that improves the mixer for Fast Track Ultra (8R) devices by
* adding TLV to existing controls * adding new controls for the effect section.
It unifies the control creation for FTU and Ebox-44 devices.
Mark, could you please look at mixer_quirks.c. Do we really need the range settings in snd_create_std_mono_ctl()? BTW, you might like to add some TLV callback to the Ebox-44 controls as well.
I hope I sorted Takashis issues out this time.
Regards,
Felix
Felix Homann (7): Unify M-Audio Fast Track Ultra and Ebox-44 mixer quirks. Rename and export mixer_vol_tlv Add TLV to M-Audio Fast Track Ultra controls Rename Fast Track Ultra mixer quirk functions Update comment for M-Audio FTU quirk M-Audio Fast Track Ultra: Add effect program switch M-Audio Fast Track Ultra: Add effect controls
sound/usb/mixer.c | 22 ++- sound/usb/mixer.h | 3 + sound/usb/mixer_quirks.c | 472 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 429 insertions(+), 68 deletions(-)
Merge snd_maudio_ftu_create_ctl() and snd_ebox44_create_ctl() into snd_create_std_mono_ctl(). As opposed to the ftu and ebox-44 specific functions, a TLV callback can be specified for controls created by snd_create_std_mono_ctl().
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index e2072ed..22a1f7b 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -42,6 +42,85 @@
extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl;
+/* private_free callback */ +static void usb_mixer_elem_free(struct snd_kcontrol *kctl) +{ + kfree(kctl->private_data); + kctl->private_data = NULL; +} + +/* This function allows for the creation of standard UAC controls. + * See the quirks for M-Audio FTUs or Ebox-44. + * If you don't want to set a TLV callback pass NULL. + * + * Since there doesn't seem to be a devices that needs a multichannel + * version, we keep it mono for simplicity. + */ +static int snd_create_std_mono_ctl(struct usb_mixer_interface *mixer, + unsigned int unitid, + unsigned int control, + unsigned int cmask, + int val_type, + const char *name, + snd_kcontrol_tlv_rw_t *tlv_callback) +{ + int err; + struct usb_mixer_elem_info *cval; + struct snd_kcontrol *kctl; + + cval = kzalloc(sizeof(*cval), GFP_KERNEL); + if (!cval) + return -ENOMEM; + + cval->id = unitid; + cval->mixer = mixer; + cval->val_type = val_type; + cval->channels = 1; + cval->control = control; + cval->cmask = cmask; + + /* FIXME: Do we need this? + * The following values are for compatibility with + * Ebox-44 mixer. + * But the corresponding ebox-44 function says: + * "Volume controls will override these values" + * + * These values don't have any effect at all for + * M-Audio FTUs. + * So I think, we can safely omit the range settings here. + */ + cval->min = 0; + cval->max = 1; + cval->res = 0; + cval->dBmin = 0; + cval->dBmax = 0; + + /* Create control */ + kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); + if (!kctl) { + kfree(cval); + return -ENOMEM; + } + + /* Set name */ + snprintf(kctl->id.name, sizeof(kctl->id.name), name); + kctl->private_free = usb_mixer_elem_free; + + /* set TLV */ + if (!tlv_callback) { + kctl->tlv.c = tlv_callback; + kctl->vd[0].access |= + SNDRV_CTL_ELEM_ACCESS_TLV_READ | + SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; + } + /* Add control to mixer */ + err = snd_usb_mixer_add_control(mixer, kctl); + if (err < 0) + return err; + + return 0; +} + /* * Sound Blaster remote control configuration * @@ -496,59 +575,37 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
/* M-Audio FastTrack Ultra quirks */
-/* private_free callback */ -static void usb_mixer_elem_free(struct snd_kcontrol *kctl) -{ - kfree(kctl->private_data); - kctl->private_data = NULL; -} - -static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer, - int in, int out, const char *name) -{ - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (!cval) - return -ENOMEM; - - cval->id = 5; - cval->mixer = mixer; - cval->val_type = USB_MIXER_S16; - cval->channels = 1; - cval->control = out + 1; - cval->cmask = 1 << in; - - kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); - if (!kctl) { - kfree(cval); - return -ENOMEM; - } - - snprintf(kctl->id.name, sizeof(kctl->id.name), name); - kctl->private_free = usb_mixer_elem_free; - return snd_usb_mixer_add_control(mixer, kctl); -} - -static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) +/* Create a volume control for FTU devices*/ +static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) { char name[64]; + unsigned int control, cmask; int in, out, err;
+ const unsigned int id = 5; + const int val_type = USB_MIXER_S16; + for (out = 0; out < 8; out++) { + control = out + 1; for (in = 0; in < 8; in++) { + cmask = 1 << in; snprintf(name, sizeof(name), - "AIn%d - Out%d Capture Volume", in + 1, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); + "AIn%d - Out%d Capture Volume", + in + 1, out + 1); + err = snd_create_std_mono_ctl(mixer, id, control, + cmask, val_type, name, + NULL); if (err < 0) return err; } - for (in = 8; in < 16; in++) { + cmask = 1 << in; snprintf(name, sizeof(name), - "DIn%d - Out%d Playback Volume", in - 7, out + 1); - err = snd_maudio_ftu_create_ctl(mixer, in, out, name); + "DIn%d - Out%d Playback Volume", + in - 7, out + 1); + err = snd_create_std_mono_ctl(mixer, id, control, + cmask, val_type, name, + NULL); if (err < 0) return err; } @@ -557,44 +614,18 @@ static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
-static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer, - int unitid, int control, int cmask, - int val_type, const char *name) +static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) { - struct usb_mixer_elem_info *cval; - struct snd_kcontrol *kctl; - - cval = kzalloc(sizeof(*cval), GFP_KERNEL); - if (!cval) - return -ENOMEM; - - cval->id = unitid; - cval->mixer = mixer; - - cval->val_type = val_type; - cval->channels = 1; - cval->control = control; - cval->cmask = cmask; - - /* Volume controls will override these values */ - cval->min = 0; - cval->max = 1; - cval->res = 0; - - cval->dBmin = 0; - cval->dBmax = 0; + int err;
- kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval); - if (!kctl) { - kfree(cval); - return -ENOMEM; - } + err = snd_maudio_ftu_create_volume_ctls(mixer); + if (err < 0) + return err;
- snprintf(kctl->id.name, sizeof(kctl->id.name), name); - kctl->private_free = usb_mixer_elem_free; - return snd_usb_mixer_add_control(mixer, kctl); + return 0; }
+ /* * Create mixer for Electrix Ebox-44 * @@ -605,17 +636,26 @@ static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer,
static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) { - snd_ebox44_create_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch"); - snd_ebox44_create_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume"); - snd_ebox44_create_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume"); - - snd_ebox44_create_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch"); - snd_ebox44_create_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume"); - snd_ebox44_create_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume"); - - snd_ebox44_create_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch"); - snd_ebox44_create_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume"); - snd_ebox44_create_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume"); + snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, + "Headphone Playback Switch", NULL); + snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, + "Headphone A Mix Playback Volume", NULL); + snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, + "Headphone B Mix Playback Volume", NULL); + + snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, + "Output Playback Switch", NULL); + snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, + "Output A Playback Volume", NULL); + snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, + "Output B Playback Volume", NULL); + + snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, + "Input Capture Switch", NULL); + snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, + "Input A Capture Volume", NULL); + snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, + "Input B Capture Volume", NULL);
return 0; }
At Mon, 23 Apr 2012 16:37:31 +0200, Felix Homann wrote:
- /* set TLV */
- if (!tlv_callback) {
I guess you want without !, no?
kctl->tlv.c = tlv_callback;
kctl->vd[0].access |=
SNDRV_CTL_ELEM_ACCESS_TLV_READ |
SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK;
- }
- /* Add control to mixer */
- err = snd_usb_mixer_add_control(mixer, kctl);
- if (err < 0)
return err;
- return 0;
+}
/*
- Sound Blaster remote control configuration
@@ -496,59 +575,37 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
/* M-Audio FastTrack Ultra quirks */
-/* private_free callback */ -static void usb_mixer_elem_free(struct snd_kcontrol *kctl) -{
- kfree(kctl->private_data);
- kctl->private_data = NULL;
-}
-static int snd_maudio_ftu_create_ctl(struct usb_mixer_interface *mixer,
int in, int out, const char *name)
-{
- struct usb_mixer_elem_info *cval;
- struct snd_kcontrol *kctl;
- cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (!cval)
return -ENOMEM;
- cval->id = 5;
- cval->mixer = mixer;
- cval->val_type = USB_MIXER_S16;
- cval->channels = 1;
- cval->control = out + 1;
- cval->cmask = 1 << in;
- kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
- if (!kctl) {
kfree(cval);
return -ENOMEM;
- }
- snprintf(kctl->id.name, sizeof(kctl->id.name), name);
- kctl->private_free = usb_mixer_elem_free;
- return snd_usb_mixer_add_control(mixer, kctl);
-}
-static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) +/* Create a volume control for FTU devices*/ +static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) { char name[64];
unsigned int control, cmask; int in, out, err;
const unsigned int id = 5;
const int val_type = USB_MIXER_S16;
for (out = 0; out < 8; out++) {
control = out + 1;
for (in = 0; in < 8; in++) {
cmask = 1 << in; snprintf(name, sizeof(name),
"AIn%d - Out%d Capture Volume", in + 1, out + 1);
err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
"AIn%d - Out%d Capture Volume",
in + 1, out + 1);
err = snd_create_std_mono_ctl(mixer, id, control,
cmask, val_type, name,
}NULL); if (err < 0) return err;
- for (in = 8; in < 16; in++) {
cmask = 1 << in; snprintf(name, sizeof(name),
"DIn%d - Out%d Playback Volume", in - 7, out + 1);
err = snd_maudio_ftu_create_ctl(mixer, in, out, name);
"DIn%d - Out%d Playback Volume",
in - 7, out + 1);
err = snd_create_std_mono_ctl(mixer, id, control,
cmask, val_type, name,
}NULL); if (err < 0) return err;
@@ -557,44 +614,18 @@ static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) return 0; }
-static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer,
int unitid, int control, int cmask,
int val_type, const char *name)
+static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) {
- struct usb_mixer_elem_info *cval;
- struct snd_kcontrol *kctl;
- cval = kzalloc(sizeof(*cval), GFP_KERNEL);
- if (!cval)
return -ENOMEM;
- cval->id = unitid;
- cval->mixer = mixer;
- cval->val_type = val_type;
- cval->channels = 1;
- cval->control = control;
- cval->cmask = cmask;
- /* Volume controls will override these values */
- cval->min = 0;
- cval->max = 1;
- cval->res = 0;
- cval->dBmin = 0;
- cval->dBmax = 0;
- int err;
- kctl = snd_ctl_new1(snd_usb_feature_unit_ctl, cval);
- if (!kctl) {
kfree(cval);
return -ENOMEM;
- }
- err = snd_maudio_ftu_create_volume_ctls(mixer);
- if (err < 0)
return err;
- snprintf(kctl->id.name, sizeof(kctl->id.name), name);
- kctl->private_free = usb_mixer_elem_free;
- return snd_usb_mixer_add_control(mixer, kctl);
- return 0;
}
/*
- Create mixer for Electrix Ebox-44
@@ -605,17 +636,26 @@ static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer,
static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) {
- snd_ebox44_create_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume");
- snd_ebox44_create_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume");
- snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Headphone Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
"Headphone A Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
"Headphone B Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Output Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
"Output A Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
"Output B Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Input Capture Switch", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
"Input A Capture Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
"Input B Capture Volume", NULL);
It would be safer to check the error of each call, but then it'd be better to make a table and loop over it. You can create a new patch for that.
thanks,
Takashi
Hi,
2012/4/23 Takashi Iwai tiwai@suse.de:
At Mon, 23 Apr 2012 16:37:31 +0200, Felix Homann wrote:
- /* set TLV */
- if (!tlv_callback) {
I guess you want without !, no?
you're absolutely right.
- snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
- "Input B Capture Volume", NULL);
It would be safer to check the error of each call, but then it'd be better to make a table and loop over it. You can create a new patch for that.
Please, tell Mark Hills. It's his patch you applied a couple of days ago. I just renamed the functions and added the 'NULL' at the end of the calls.
Regards,
Felix
At Mon, 23 Apr 2012 18:00:03 +0200, Felix Homann wrote:
Hi,
2012/4/23 Takashi Iwai tiwai@suse.de:
At Mon, 23 Apr 2012 16:37:31 +0200, Felix Homann wrote:
- /* set TLV */
- if (!tlv_callback) {
I guess you want without !, no?
you're absolutely right.
- snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
- "Input B Capture Volume", NULL);
It would be safer to check the error of each call, but then it'd be better to make a table and loop over it. You can create a new patch for that.
Please, tell Mark Hills. It's his patch you applied a couple of days ago. I just renamed the functions and added the 'NULL' at the end of the calls.
Well, if you are already working on it, you are the best position to add such simple fixes ;) Otherwise we'll get merge conflicts. As mentioned, just create a new patch to add the error checks.
thanks,
Takashi
On Mon, 23 Apr 2012, Takashi Iwai wrote:
At Mon, 23 Apr 2012 16:37:31 +0200, Felix Homann wrote:
[...]
/*
- Create mixer for Electrix Ebox-44
@@ -605,17 +636,26 @@ static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer,
static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) {
- snd_ebox44_create_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume");
- snd_ebox44_create_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume");
- snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Headphone Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
"Headphone A Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
"Headphone B Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Output Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
"Output A Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
"Output B Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Input Capture Switch", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
"Input A Capture Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
"Input B Capture Volume", NULL);
It would be safer to check the error of each call, but then it'd be better to make a table and loop over it. You can create a new patch for that.
I can do this, if somebody can tell me how best to handle the error. If snd_ebox44_create_ctl fails andI return an error code, I become responsible for un-winding the previous creations?
Thanks
At Mon, 23 Apr 2012 19:43:09 +0100 (BST), Mark Hills wrote:
On Mon, 23 Apr 2012, Takashi Iwai wrote:
At Mon, 23 Apr 2012 16:37:31 +0200, Felix Homann wrote:
[...]
/*
- Create mixer for Electrix Ebox-44
@@ -605,17 +636,26 @@ static int snd_ebox44_create_ctl(struct usb_mixer_interface *mixer,
static int snd_ebox44_create_mixer(struct usb_mixer_interface *mixer) {
- snd_ebox44_create_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Headphone Playback Switch");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16, "Headphone A Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16, "Headphone B Mix Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Output Playback Switch");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16, "Output A Playback Volume");
- snd_ebox44_create_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16, "Output B Playback Volume");
- snd_ebox44_create_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN, "Input Capture Switch");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16, "Input A Capture Volume");
- snd_ebox44_create_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16, "Input B Capture Volume");
- snd_create_std_mono_ctl(mixer, 4, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Headphone Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x1, USB_MIXER_S16,
"Headphone A Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 4, 2, 0x2, USB_MIXER_S16,
"Headphone B Mix Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Output Playback Switch", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x1, USB_MIXER_S16,
"Output A Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 7, 2, 0x2, USB_MIXER_S16,
"Output B Playback Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 1, 0x0, USB_MIXER_INV_BOOLEAN,
"Input Capture Switch", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x1, USB_MIXER_S16,
"Input A Capture Volume", NULL);
- snd_create_std_mono_ctl(mixer, 10, 2, 0x2, USB_MIXER_S16,
"Input B Capture Volume", NULL);
It would be safer to check the error of each call, but then it'd be better to make a table and loop over it. You can create a new patch for that.
I can do this, if somebody can tell me how best to handle the error. If snd_ebox44_create_ctl fails andI return an error code, I become responsible for un-winding the previous creations?
This doesn't matter. The leftover control elements are released automatically by the card instance destructor.
Anyway, I fixed this manually now together with Felix's patches.
thanks,
Takashi
Rename mixer_vol_tlv to snd_usb_mixer_vol_tlv and export it to make it reuseable in mixer_quirks.c.
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index c374c72..bb56f53 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -486,7 +486,7 @@ static int set_cur_mix_value(struct usb_mixer_elem_info *cval, int channel, /* * TLV callback for mixer volume controls */ -static int mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, +int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, unsigned int size, unsigned int __user *_tlv) { struct usb_mixer_elem_info *cval = kcontrol->private_data; @@ -1158,7 +1158,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc, if (control == UAC_FU_VOLUME) { check_mapped_dB(map, cval); if (cval->dBmin < cval->dBmax || !cval->initialized) { - kctl->tlv.c = mixer_vol_tlv; + kctl->tlv.c = snd_usb_mixer_vol_tlv; kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK; diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 81b2d8a..a7f3d45 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -68,4 +68,7 @@ int snd_usb_mixer_activate(struct usb_mixer_interface *mixer); int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, struct snd_kcontrol *kctl);
+int snd_usb_mixer_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag, + unsigned int size, unsigned int __user *_tlv); + #endif /* __USBMIXER_H */
This adds db gain information to M-Audio Fast Track Ultra (8R) devices.
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 22a1f7b..afb5cdb 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -594,7 +594,7 @@ static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) in + 1, out + 1); err = snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, name, - NULL); + &snd_usb_mixer_vol_tlv); if (err < 0) return err; } @@ -605,7 +605,7 @@ static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) in - 7, out + 1); err = snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, name, - NULL); + &snd_usb_mixer_vol_tlv); if (err < 0) return err; }
This is in preparation for more FTU controls to come. Should help keeping names a bit shorter.
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index afb5cdb..6e4f51c 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -576,7 +576,7 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, /* M-Audio FastTrack Ultra quirks */
/* Create a volume control for FTU devices*/ -static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) +static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) { char name[64]; unsigned int control, cmask; @@ -614,11 +614,11 @@ static int snd_maudio_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) return 0; }
-static int snd_maudio_ftu_create_mixer(struct usb_mixer_interface *mixer) +static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) { int err;
- err = snd_maudio_ftu_create_volume_ctls(mixer); + err = snd_ftu_create_volume_ctls(mixer); if (err < 0) return err;
@@ -703,7 +703,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ - err = snd_maudio_ftu_create_mixer(mixer); + err = snd_ftu_create_mixer(mixer); break;
case USB_ID(0x0b05, 0x1739):
Just cosmetics...
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 6e4f51c..3adef3e 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -575,7 +575,7 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer,
/* M-Audio FastTrack Ultra quirks */
-/* Create a volume control for FTU devices*/ +/* Create volume controls for FTU devices*/ static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) { char name[64];
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 3adef3e..f751137 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -574,6 +574,187 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, }
/* M-Audio FastTrack Ultra quirks */ +/* FTU Effect switch */ +struct snd_ftu_eff_switch_priv_val { + struct usb_mixer_interface *mixer; + int cached_value; + int is_cached; +}; + +static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + static char *texts[8] = {"Room 1", + "Room 2", + "Room 3", + "Hall 1", + "Hall 2", + "Plate", + "Delay", + "Echo" + }; + + uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; + uinfo->count = 1; + uinfo->value.enumerated.items = 8; + if (uinfo->value.enumerated.item > 7) + uinfo->value.enumerated.item = 7; + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); + + return 0; +} + +static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_usb_audio *chip; + struct usb_mixer_interface *mixer; + struct snd_ftu_eff_switch_priv_val *pval; + int err; + unsigned char value[2]; + + pval = (struct snd_ftu_eff_switch_priv_val *) + kctl->private_value; + + if (pval->is_cached) { + ucontrol->value.enumerated.item[0] = pval->cached_value; + return 0; + } + + mixer = (struct usb_mixer_interface *) pval->mixer; + if (snd_BUG_ON(!mixer)) + return -EINVAL; + + chip = (struct snd_usb_audio *) mixer->chip; + if (snd_BUG_ON(!chip)) + return -EINVAL; + + const int id = 6; + const int validx = 1; + const int val_type = USB_MIXER_S16; + + value[0] = 0x00; + value[1] = 0x00; + + const int val_len = 2; + + err = snd_usb_ctl_msg(chip->dev, + usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), + value, val_len); + if (err < 0) + return -1; + + ucontrol->value.enumerated.item[0] = value[0]; + pval->cached_value = value[0]; + pval->is_cached = 1; + + return 0; +} + +static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_usb_audio *chip; + struct snd_ftu_eff_switch_priv_val *pval; + + struct usb_mixer_interface *mixer; + int changed, cur_val, err, new_val; + unsigned char value[2]; + + changed = 0; + const int id = 6; + const int validx = 1; + const int val_type = USB_MIXER_S16; + const int val_len = 2; + + pval = (struct snd_ftu_eff_switch_priv_val *) + kctl->private_value; + cur_val = pval->cached_value; + new_val = ucontrol->value.enumerated.item[0]; + + mixer = (struct usb_mixer_interface *) pval->mixer; + if (snd_BUG_ON(!mixer)) + return -EINVAL; + + chip = (struct snd_usb_audio *) mixer->chip; + if (snd_BUG_ON(!chip)) + return -EINVAL; + + if (!pval->is_cached) { + /* Read current value */ + err = snd_usb_ctl_msg(chip->dev, + usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN, + validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), + value, val_len); + if (err < 0) + return -1; + + cur_val = value[0]; + pval->cached_value = cur_val; + pval->is_cached = 1; + } + /* update value if needed */ + if (cur_val != new_val) { + value[0] = new_val; + value[1] = 0; + err = snd_usb_ctl_msg(chip->dev, + usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR, + USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT, + validx << 8, snd_usb_ctrl_intf(chip) | (id << 8), + value, val_len); + if (err < 0) + return -1; + + pval->cached_value = new_val; + pval->is_cached = 1; + changed = 1; + } + + return changed; +} + +static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer) +{ + static struct snd_kcontrol_new template = { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Effect Program Switch", + .index = 0, + .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, + .info = snd_ftu_eff_switch_info, + .get = snd_ftu_eff_switch_get, + .put = snd_ftu_eff_switch_put + }; + + int err; + struct snd_kcontrol *kctl; + struct snd_ftu_eff_switch_priv_val *pval; + + pval = kzalloc(sizeof(*pval), GFP_KERNEL); + if (!pval) + return -ENOMEM; + + pval->cached_value = 0; + pval->is_cached = 0; + pval->mixer = mixer; + + template.private_value = (unsigned long) pval; + kctl = snd_ctl_new1(&template, mixer->chip); + if (!kctl) { + kfree(pval); + return -ENOMEM; + } + + err = snd_ctl_add(mixer->chip->card, kctl); + if (err < 0) + return err; + + return 0; +} +
/* Create volume controls for FTU devices*/ static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) @@ -622,6 +803,10 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) if (err < 0) return err;
+ err = snd_ftu_create_effect_switch(mixer); + if (err < 0) + return err; + return 0; }
At Mon, 23 Apr 2012 16:37:36 +0200, Felix Homann wrote:
Signed-off-by: Felix Homann linuxaudio@showlabor.de
Put some more texts here. Otherwise one can't know what you've done. For example, you can explain more about what effect is added and how. Or any current restriction or whatever.
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 3adef3e..f751137 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -574,6 +574,187 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, }
/* M-Audio FastTrack Ultra quirks */ +/* FTU Effect switch */ +struct snd_ftu_eff_switch_priv_val {
- struct usb_mixer_interface *mixer;
- int cached_value;
- int is_cached;
+};
+static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
+{
- static char *texts[8] = {"Room 1",
"Room 2",
"Room 3",
"Hall 1",
"Hall 2",
"Plate",
"Delay",
"Echo"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item > 7)
uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name,
texts[uinfo->value.enumerated.item]);
- return 0;
+}
+static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
+{
- struct snd_usb_audio *chip;
- struct usb_mixer_interface *mixer;
- struct snd_ftu_eff_switch_priv_val *pval;
- int err;
- unsigned char value[2];
- pval = (struct snd_ftu_eff_switch_priv_val *)
kctl->private_value;
- if (pval->is_cached) {
ucontrol->value.enumerated.item[0] = pval->cached_value;
return 0;
- }
- mixer = (struct usb_mixer_interface *) pval->mixer;
- if (snd_BUG_ON(!mixer))
return -EINVAL;
- chip = (struct snd_usb_audio *) mixer->chip;
- if (snd_BUG_ON(!chip))
return -EINVAL;
- const int id = 6;
- const int validx = 1;
- const int val_type = USB_MIXER_S16;
- value[0] = 0x00;
- value[1] = 0x00;
- const int val_len = 2;
- err = snd_usb_ctl_msg(chip->dev,
usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len);
- if (err < 0)
return -1;
Return err as is.
- ucontrol->value.enumerated.item[0] = value[0];
- pval->cached_value = value[0];
- pval->is_cached = 1;
- return 0;
+}
+static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
+{
- struct snd_usb_audio *chip;
- struct snd_ftu_eff_switch_priv_val *pval;
- struct usb_mixer_interface *mixer;
- int changed, cur_val, err, new_val;
- unsigned char value[2];
- changed = 0;
- const int id = 6;
- const int validx = 1;
- const int val_type = USB_MIXER_S16;
- const int val_len = 2;
- pval = (struct snd_ftu_eff_switch_priv_val *)
kctl->private_value;
- cur_val = pval->cached_value;
- new_val = ucontrol->value.enumerated.item[0];
- mixer = (struct usb_mixer_interface *) pval->mixer;
- if (snd_BUG_ON(!mixer))
return -EINVAL;
- chip = (struct snd_usb_audio *) mixer->chip;
- if (snd_BUG_ON(!chip))
return -EINVAL;
- if (!pval->is_cached) {
/* Read current value */
err = snd_usb_ctl_msg(chip->dev,
usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len);
if (err < 0)
return -1;
Ditto.
cur_val = value[0];
pval->cached_value = cur_val;
pval->is_cached = 1;
- }
- /* update value if needed */
- if (cur_val != new_val) {
value[0] = new_val;
value[1] = 0;
err = snd_usb_ctl_msg(chip->dev,
usb_sndctrlpipe(chip->dev, 0), UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
validx << 8, snd_usb_ctrl_intf(chip) | (id << 8),
value, val_len);
if (err < 0)
return -1;
Ditto.
pval->cached_value = new_val;
pval->is_cached = 1;
changed = 1;
- }
- return changed;
+}
+static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer) +{
- static struct snd_kcontrol_new template = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Effect Program Switch",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = snd_ftu_eff_switch_info,
.get = snd_ftu_eff_switch_get,
.put = snd_ftu_eff_switch_put
- };
Avoid the unnecessary blank line.
- int err;
- struct snd_kcontrol *kctl;
- struct snd_ftu_eff_switch_priv_val *pval;
- pval = kzalloc(sizeof(*pval), GFP_KERNEL);
- if (!pval)
return -ENOMEM;
- pval->cached_value = 0;
- pval->is_cached = 0;
- pval->mixer = mixer;
- template.private_value = (unsigned long) pval;
- kctl = snd_ctl_new1(&template, mixer->chip);
- if (!kctl) {
kfree(pval);
return -ENOMEM;
- }
- err = snd_ctl_add(mixer->chip->card, kctl);
- if (err < 0)
return err;
- return 0;
+}
/* Create volume controls for FTU devices*/ static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) @@ -622,6 +803,10 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) if (err < 0) return err;
- err = snd_ftu_create_effect_switch(mixer);
- if (err < 0)
return err;
- return 0;
}
-- 1.7.5.4
This adds the remaining controls for effects on the FTU devices. Some of these controls need volume quirks. They are added to mixer.c.
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index bb56f53..195b6d2 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -770,6 +770,24 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { switch (cval->mixer->chip->usb_id) { + case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */ + case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */ + if ((strcmp(kctl->id.name, "Effect Duration") == 0)) { + snd_printk(KERN_INFO + "usb-audio: set quirk for FTU Effect Duration\n"); + cval->min = 0x0000; + cval->max = 0x7f00; + cval->res = 0x0100; + break; + } + if (strcmp(kctl->id.name, "Effect Volume") == 0 || + strcmp(kctl->id.name, "Effect Feedback Volume") == 0) { + snd_printk(KERN_INFO + "usb-audio: set quirks for FTU Effect Feedback/Volume\n"); + cval->min = 0x00; + cval->max = 0x7f; + break; + } case USB_ID(0x0471, 0x0101): case USB_ID(0x0471, 0x0104): case USB_ID(0x0471, 0x0105): diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f751137..4d8cc45 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -584,14 +584,14 @@ struct snd_ftu_eff_switch_priv_val { static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) { - static char *texts[8] = {"Room 1", - "Room 2", - "Room 3", - "Hall 1", - "Hall 2", - "Plate", - "Delay", - "Echo" + static const char *texts[8] = {"Room 1", + "Room 2", + "Room 3", + "Hall 1", + "Hall 2", + "Plate", + "Delay", + "Echo" };
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -614,6 +614,13 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, int err; unsigned char value[2];
+ const int id = 6; + const int validx = 1; + const int val_len = 2; + + value[0] = 0x00; + value[1] = 0x00; + pval = (struct snd_ftu_eff_switch_priv_val *) kctl->private_value;
@@ -630,14 +637,6 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, if (snd_BUG_ON(!chip)) return -EINVAL;
- const int id = 6; - const int validx = 1; - const int val_type = USB_MIXER_S16; - - value[0] = 0x00; - value[1] = 0x00; - - const int val_len = 2;
err = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), UAC_GET_CUR, @@ -664,12 +663,13 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl, int changed, cur_val, err, new_val; unsigned char value[2];
- changed = 0; + const int id = 6; const int validx = 1; - const int val_type = USB_MIXER_S16; const int val_len = 2;
+ changed = 0; + pval = (struct snd_ftu_eff_switch_priv_val *) kctl->private_value; cur_val = pval->cached_value; @@ -795,6 +795,102 @@ static int snd_ftu_create_volume_ctls(struct usb_mixer_interface *mixer) return 0; }
+/* This control needs a volume quirk, see mixer.c */ +static int snd_ftu_create_effect_volume_ctl(struct usb_mixer_interface *mixer) +{ + static const char name[] = "Effect Volume"; + const unsigned int id = 6; + const int val_type = USB_MIXER_U8; + const unsigned int control = 2; + const unsigned int cmask = 0; + + return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, + name, snd_usb_mixer_vol_tlv); +} + +/* This control needs a volume quirk, see mixer.c */ +static int snd_ftu_create_effect_duration_ctl(struct usb_mixer_interface *mixer) +{ + static const char name[] = "Effect Duration"; + const unsigned int id = 6; + const int val_type = USB_MIXER_S16; + const unsigned int control = 3; + const unsigned int cmask = 0; + + return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, + name, snd_usb_mixer_vol_tlv); +} + +/* This control needs a volume quirk, see mixer.c */ +static int snd_ftu_create_effect_feedback_ctl(struct usb_mixer_interface *mixer) +{ + static const char name[] = "Effect Feedback Volume"; + const unsigned int id = 6; + const int val_type = USB_MIXER_U8; + const unsigned int control = 4; + const unsigned int cmask = 0; + + return snd_create_std_mono_ctl(mixer, id, control, cmask, val_type, + name, NULL); +} + +static int snd_ftu_create_effect_return_ctls(struct usb_mixer_interface *mixer) +{ + unsigned int cmask; + int err, ch; + char name[48]; + + const unsigned int id = 7; + const int val_type = USB_MIXER_S16; + const unsigned int control = 7; + + for (ch = 0; ch < 4; ++ch) { + cmask = 1 << ch; + snprintf(name, sizeof(name), + "Effect Return %d Volume", ch + 1); + err = snd_create_std_mono_ctl(mixer, id, control, + cmask, val_type, name, + snd_usb_mixer_vol_tlv); + if (err < 0) + return err; + } + + return 0; +} + +static int snd_ftu_create_effect_send_ctls(struct usb_mixer_interface *mixer) +{ + unsigned int cmask; + int err, ch; + char name[48]; + + const unsigned int id = 5; + const int val_type = USB_MIXER_S16; + const unsigned int control = 9; + + for (ch = 0; ch < 8; ++ch) { + cmask = 1 << ch; + snprintf(name, sizeof(name), + "Effect Send AIn%d Volume", ch + 1); + err = snd_create_std_mono_ctl(mixer, id, control, cmask, + val_type, name, + snd_usb_mixer_vol_tlv); + if (err < 0) + return err; + } + for (ch = 8; ch < 16; ++ch) { + cmask = 1 << ch; + snprintf(name, sizeof(name), + "Effect Send DIn%d Volume", ch - 7); + err = snd_create_std_mono_ctl(mixer, id, control, cmask, + val_type, name, + snd_usb_mixer_vol_tlv); + if (err < 0) + return err; + } + return 0; +} + static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) { int err; @@ -806,6 +902,25 @@ static int snd_ftu_create_mixer(struct usb_mixer_interface *mixer) err = snd_ftu_create_effect_switch(mixer); if (err < 0) return err; + err = snd_ftu_create_effect_volume_ctl(mixer); + if (err < 0) + return err; + + err = snd_ftu_create_effect_duration_ctl(mixer); + if (err < 0) + return err; + + err = snd_ftu_create_effect_feedback_ctl(mixer); + if (err < 0) + return err; + + err = snd_ftu_create_effect_return_ctls(mixer); + if (err < 0) + return err; + + err = snd_ftu_create_effect_send_ctls(mixer); + if (err < 0) + return err;
return 0; }
At Mon, 23 Apr 2012 16:37:37 +0200, Felix Homann wrote:
This adds the remaining controls for effects on the FTU devices. Some of these controls need volume quirks. They are added to mixer.c.
Signed-off-by: Felix Homann linuxaudio@showlabor.de
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index bb56f53..195b6d2 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -770,6 +770,24 @@ static void volume_control_quirks(struct usb_mixer_elem_info *cval, struct snd_kcontrol *kctl) { switch (cval->mixer->chip->usb_id) {
- case USB_ID(0x0763, 0x2081): /* M-Audio Fast Track Ultra 8R */
- case USB_ID(0x0763, 0x2080): /* M-Audio Fast Track Ultra */
if ((strcmp(kctl->id.name, "Effect Duration") == 0)) {
snd_printk(KERN_INFO
"usb-audio: set quirk for FTU Effect Duration\n");
cval->min = 0x0000;
cval->max = 0x7f00;
cval->res = 0x0100;
break;
}
if (strcmp(kctl->id.name, "Effect Volume") == 0 ||
strcmp(kctl->id.name, "Effect Feedback Volume") == 0) {
snd_printk(KERN_INFO
"usb-audio: set quirks for FTU Effect Feedback/Volume\n");
cval->min = 0x00;
cval->max = 0x7f;
break;
case USB_ID(0x0471, 0x0101): case USB_ID(0x0471, 0x0104): case USB_ID(0x0471, 0x0105):}
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index f751137..4d8cc45 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -584,14 +584,14 @@ struct snd_ftu_eff_switch_priv_val { static int snd_ftu_eff_switch_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) {
- static char *texts[8] = {"Room 1",
"Room 2",
"Room 3",
"Hall 1",
"Hall 2",
"Plate",
"Delay",
"Echo"
- static const char *texts[8] = {"Room 1",
Write it in the first place in that way.
"Room 2",
"Room 3",
"Hall 1",
"Hall 2",
"Plate",
"Delay",
"Echo"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
@@ -614,6 +614,13 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, int err; unsigned char value[2];
- const int id = 6;
- const int validx = 1;
- const int val_len = 2;
- value[0] = 0x00;
- value[1] = 0x00;
- pval = (struct snd_ftu_eff_switch_priv_val *) kctl->private_value;
@@ -630,14 +637,6 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, if (snd_BUG_ON(!chip)) return -EINVAL;
- const int id = 6;
- const int validx = 1;
- const int val_type = USB_MIXER_S16;
Ditto. Not good to fix something in a later patch if you already know it should be fixed.
thanks,
Takashi
Hi again,
2012/4/23 Takashi Iwai tiwai@suse.de:
- static char *texts[8] = {"Room 1",
- "Room 2",
- "Room 3",
- "Hall 1",
- "Hall 2",
- "Plate",
- "Delay",
- "Echo"
- static const char *texts[8] = {"Room 1",
Write it in the first place in that way.
Sure, would be better.
- "Room 2",
- "Room 3",
- "Hall 1",
- "Hall 2",
- "Plate",
- "Delay",
- "Echo"
};
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; @@ -614,6 +614,13 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, int err; unsigned char value[2];
- const int id = 6;
- const int validx = 1;
- const int val_len = 2;
- value[0] = 0x00;
- value[1] = 0x00;
pval = (struct snd_ftu_eff_switch_priv_val *) kctl->private_value;
@@ -630,14 +637,6 @@ static int snd_ftu_eff_switch_get(struct snd_kcontrol *kctl, if (snd_BUG_ON(!chip)) return -EINVAL;
- const int id = 6;
- const int validx = 1;
- const int val_type = USB_MIXER_S16;
Ditto. Not good to fix something in a later patch if you already know it should be fixed.
If I had known I would have done...
Regards,
Felix
participants (3)
-
Felix Homann
-
Mark Hills
-
Takashi Iwai