[alsa-devel] Patch series for Fast Track Ultra mixer quirks
Here's the set of patches to make Fast Track Ultra mixer quirks possible. It's just a split version of the patch we've discussed on the ALSA ML before.
These patches can as well be pulled from
git@github.com:zonque/linux-2.6.git usb-audio
Daniel Mack (5): ALSA: usb-audio: move assignment of chip->ctrl_intf ALSA: usb-audio: rework add_control_to_empty() ALSA: usb-audio: export snd_usb_feature_unit_ctl ALSA: usb-audio: add new quirk type QUIRK_AUDIO_STANDARD_MIXER ALSA: usb-audio: more control quirks for M-Audio FastTrack devices
sound/usb/card.c | 17 ++++++----- sound/usb/mixer.c | 32 ++++++++------------ sound/usb/mixer.h | 14 ++++++++- sound/usb/mixer_quirks.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/quirks-table.h | 4 +- sound/usb/quirks.c | 18 +++++++++++- sound/usb/usbaudio.h | 1 + 7 files changed, 125 insertions(+), 31 deletions(-)
This is needed for upcoming changes to the quirks mechanism.
Signed-off-by: Daniel Mack zonque@gmail.com --- sound/usb/card.c | 16 ++++++++-------- 1 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index a90662a..84a5ce7 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -492,14 +492,6 @@ static void *snd_usb_audio_probe(struct usb_device *dev, } }
- chip->txfr_quirk = 0; - err = 1; /* continue */ - if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { - /* need some special handlings */ - if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) - goto __error; - } - /* * For devices with more than one control interface, we assume the * first contains the audio controls. We might need a more specific @@ -508,6 +500,14 @@ static void *snd_usb_audio_probe(struct usb_device *dev, if (!chip->ctrl_intf) chip->ctrl_intf = alts;
+ chip->txfr_quirk = 0; + err = 1; /* continue */ + if (quirk && quirk->ifnum != QUIRK_NO_INTERFACE) { + /* need some special handlings */ + if ((err = snd_usb_create_quirk(chip, intf, &usb_audio_driver, quirk)) < 0) + goto __error; + } + if (err > 0) { /* create normal USB audio interfaces */ if (snd_usb_create_streams(chip, ifnum) < 0 ||
This patch renames add_control_to_empty() to snd_usb_mixer_add_control() and exports it, so the quirks functions can make use of it.
Also, as "struct mixer_build" is private to mixer.c, rewrite the function to take an argument of type "struct usb_mixer_interface" instead.
Signed-off-by: Daniel Mack zonque@gmail.com --- sound/usb/mixer.c | 19 ++++++++++--------- sound/usb/mixer.h | 3 +++ 2 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index eab06ed..ba19bfd 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -535,20 +535,21 @@ static int check_matrix_bitmap(unsigned char *bmap, int ich, int och, int num_ou * if failed, give up and free the control instance. */
-static int add_control_to_empty(struct mixer_build *state, struct snd_kcontrol *kctl) +int snd_usb_mixer_add_control(struct usb_mixer_interface *mixer, + struct snd_kcontrol *kctl) { struct usb_mixer_elem_info *cval = kctl->private_data; int err;
- while (snd_ctl_find_id(state->chip->card, &kctl->id)) + while (snd_ctl_find_id(mixer->chip->card, &kctl->id)) kctl->id.index++; - if ((err = snd_ctl_add(state->chip->card, kctl)) < 0) { + if ((err = snd_ctl_add(mixer->chip->card, kctl)) < 0) { snd_printd(KERN_ERR "cannot add control (err = %d)\n", err); return err; } cval->elem_id = &kctl->id; - cval->next_id_elem = state->mixer->id_elems[cval->id]; - state->mixer->id_elems[cval->id] = cval; + cval->next_id_elem = mixer->id_elems[cval->id]; + mixer->id_elems[cval->id] = cval; return 0; }
@@ -1176,7 +1177,7 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
snd_printdd(KERN_INFO "[%d] FU [%s] ch = %d, val = %d/%d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max, cval->res); - add_control_to_empty(state, kctl); + snd_usb_mixer_add_control(state->mixer, kctl); }
@@ -1340,7 +1341,7 @@ static void build_mixer_unit_ctl(struct mixer_build *state,
snd_printdd(KERN_INFO "[%d] MU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - add_control_to_empty(state, kctl); + snd_usb_mixer_add_control(state->mixer, kctl); }
@@ -1641,7 +1642,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid, void *raw
snd_printdd(KERN_INFO "[%d] PU [%s] ch = %d, val = %d/%d\n", cval->id, kctl->id.name, cval->channels, cval->min, cval->max); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err; } return 0; @@ -1858,7 +1859,7 @@ static int parse_audio_selector_unit(struct mixer_build *state, int unitid, void
snd_printdd(KERN_INFO "[%d] SU [%s] items = %d\n", cval->id, kctl->id.name, desc->bNrInPins); - if ((err = add_control_to_empty(state, kctl)) < 0) + if ((err = snd_usb_mixer_add_control(state->mixer, kctl)) < 0) return err;
return 0; diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index b4a2c81..459551a 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -55,4 +55,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval, void snd_usb_mixer_inactivate(struct usb_mixer_interface *mixer); 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); + #endif /* __USBMIXER_H */
In order to allow quirks functions to hook up to the standard feature unit op tables, this patch exports a pointer to the struct that is used internally.
That way, all the code handling the control can be kept private, and external code can reference the symbol to re-use it.
Signed-off-by: Daniel Mack zonque@gmail.com --- sound/usb/card.c | 1 + sound/usb/mixer.c | 13 +++---------- sound/usb/mixer.h | 11 ++++++++++- sound/usb/quirks.c | 1 + 4 files changed, 15 insertions(+), 11 deletions(-)
diff --git a/sound/usb/card.c b/sound/usb/card.c index 84a5ce7..220c616 100644 --- a/sound/usb/card.c +++ b/sound/usb/card.c @@ -48,6 +48,7 @@ #include <linux/usb/audio.h> #include <linux/usb/audio-v2.h>
+#include <sound/control.h> #include <sound/core.h> #include <sound/info.h> #include <sound/pcm.h> diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index ba19bfd..c22fa76 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -86,16 +86,6 @@ struct mixer_build { const struct usbmix_selector_map *selector_map; };
-enum { - USB_MIXER_BOOLEAN, - USB_MIXER_INV_BOOLEAN, - USB_MIXER_S8, - USB_MIXER_U8, - USB_MIXER_S16, - USB_MIXER_U16, -}; - - /*E-mu 0202/0404/0204 eXtension Unit(XU) control*/ enum { USB_XU_CLOCK_RATE = 0xe301, @@ -985,6 +975,9 @@ static struct snd_kcontrol_new usb_feature_unit_ctl_ro = { .put = NULL, };
+/* This symbol is exported in order to allow the mixer quirks to + * hook up to the standard feature unit control mechanism */ +struct snd_kcontrol_new *snd_usb_feature_unit_ctl = &usb_feature_unit_ctl;
/* * build a feature control diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h index 459551a..ae1a14d 100644 --- a/sound/usb/mixer.h +++ b/sound/usb/mixer.h @@ -24,7 +24,16 @@ struct usb_mixer_interface { u8 xonar_u1_status; };
-#define MAX_CHANNELS 10 /* max logical channels */ +#define MAX_CHANNELS 16 /* max logical channels */ + +enum { + USB_MIXER_BOOLEAN, + USB_MIXER_INV_BOOLEAN, + USB_MIXER_S8, + USB_MIXER_U8, + USB_MIXER_S16, + USB_MIXER_U16, +};
struct usb_mixer_elem_info { struct usb_mixer_interface *mixer; diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index bd13d72..2546dc8 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -19,6 +19,7 @@ #include <linux/usb.h> #include <linux/usb/audio.h>
+#include <sound/control.h> #include <sound/core.h> #include <sound/info.h> #include <sound/pcm.h>
This quirk type will let the driver assume that there is a standard mixer on a given interface, or that a specific mixer quirks will handle the device.
Signed-off-by: Daniel Mack zonque@gmail.com --- sound/usb/quirks.c | 17 ++++++++++++++++- sound/usb/usbaudio.h | 1 + 2 files changed, 17 insertions(+), 1 deletions(-)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index 2546dc8..2e969cb 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -264,6 +264,20 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip, }
/* + * Create a standard mixer for the specified interface. + */ +static int create_standard_mixer_quirk(struct snd_usb_audio *chip, + struct usb_interface *iface, + struct usb_driver *driver, + const struct snd_usb_audio_quirk *quirk) +{ + if (quirk->ifnum < 0) + return 0; + + return snd_usb_create_mixer(chip, quirk->ifnum, 0); +} + +/* * audio-interface quirks * * returns zero if no standard audio/MIDI parsing is needed. @@ -295,7 +309,8 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip, [QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk, [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, [QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk, - [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk + [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk, + [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk, };
if (quirk->type < QUIRK_TYPE_COUNT) { diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h index 32f2a97..1e79986 100644 --- a/sound/usb/usbaudio.h +++ b/sound/usb/usbaudio.h @@ -84,6 +84,7 @@ enum quirk_type { QUIRK_AUDIO_FIXED_ENDPOINT, QUIRK_AUDIO_EDIROL_UAXX, QUIRK_AUDIO_ALIGN_TRANSFER, + QUIRK_AUDIO_STANDARD_MIXER,
QUIRK_TYPE_COUNT };
Make use of the freshly introduced methods to re-use standard mixer handling and add some controls that are hidden but implemented in a standard conform way on M-Audio's FastTrack devices.
Signed-off-by: Daniel Mack zonque@gmail.com Original-code-by: Felix Homann linuxaudio@showlabor.de --- sound/usb/mixer_quirks.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/quirks-table.h | 4 +- 2 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c index 9146cff..3d0f487 100644 --- a/sound/usb/mixer_quirks.c +++ b/sound/usb/mixer_quirks.c @@ -40,6 +40,8 @@ #include "mixer_quirks.h" #include "helper.h"
+extern struct snd_kcontrol_new *snd_usb_feature_unit_ctl; + /* * Sound Blaster remote control configuration * @@ -492,6 +494,69 @@ static int snd_nativeinstruments_create_mixer(struct usb_mixer_interface *mixer, return err; }
+/* 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) +{ + char name[64]; + int in, out, err; + + for (out = 0; out < 8; out++) { + for (in = 0; in < 8; 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); + if (err < 0) + return err; + } + + for (in = 8; in < 16; 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); + if (err < 0) + return err; + } + } + + return 0; +} + void snd_emuusb_set_samplerate(struct snd_usb_audio *chip, unsigned char samplerate_id) { @@ -533,6 +598,11 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer) snd_audigy2nx_proc_read); break;
+ 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); + break; + case USB_ID(0x0b05, 0x1739): case USB_ID(0x0b05, 0x1743): err = snd_xonar_u1_controls_create(mixer); diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h index 78792a8..0b2ae8e 100644 --- a/sound/usb/quirks-table.h +++ b/sound/usb/quirks-table.h @@ -1988,7 +1988,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE + .type = QUIRK_AUDIO_STANDARD_MIXER, }, { .ifnum = 1, @@ -2055,7 +2055,7 @@ YAMAHA_DEVICE(0x7010, "UB99"), .data = & (const struct snd_usb_audio_quirk[]) { { .ifnum = 0, - .type = QUIRK_IGNORE_INTERFACE + .type = QUIRK_AUDIO_STANDARD_MIXER, }, { .ifnum = 1,
At Wed, 25 May 2011 09:08:58 +0200, Daniel Mack wrote:
Here's the set of patches to make Fast Track Ultra mixer quirks possible. It's just a split version of the patch we've discussed on the ALSA ML before.
Thanks.
I'd have exported a function creating FU mixer element instead of the control element link, but your patches are simple enough, so I applied as is.
Takashi
These patches can as well be pulled from
git@github.com:zonque/linux-2.6.git usb-audio
Daniel Mack (5): ALSA: usb-audio: move assignment of chip->ctrl_intf ALSA: usb-audio: rework add_control_to_empty() ALSA: usb-audio: export snd_usb_feature_unit_ctl ALSA: usb-audio: add new quirk type QUIRK_AUDIO_STANDARD_MIXER ALSA: usb-audio: more control quirks for M-Audio FastTrack devices
sound/usb/card.c | 17 ++++++----- sound/usb/mixer.c | 32 ++++++++------------ sound/usb/mixer.h | 14 ++++++++- sound/usb/mixer_quirks.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++ sound/usb/quirks-table.h | 4 +- sound/usb/quirks.c | 18 +++++++++++- sound/usb/usbaudio.h | 1 + 7 files changed, 125 insertions(+), 31 deletions(-)
On Wed, May 25, 2011 at 9:41 AM, Takashi Iwai tiwai@suse.de wrote:
At Wed, 25 May 2011 09:08:58 +0200, Daniel Mack wrote:
Here's the set of patches to make Fast Track Ultra mixer quirks possible. It's just a split version of the patch we've discussed on the ALSA ML before.
Thanks.
I'd have exported a function creating FU mixer element instead of the control element link, but your patches are simple enough, so I applied as is.
I can have a look at this later and send a fixup.
Thanks, Daniel
I'd have exported a function creating FU mixer element instead of the control element link, but your patches are simple enough, so I applied as is.
I can have a look at this later and send a fixup.
Thanks to everyone involved for efforts in developing and merging this support.
So when Takashi says he's applied it what git branch/repo is that if it's published?
So I thought it might be worthwhile sumarising the current status of the Fast track ultra support in alsa from a user perspective:
Done working 100%: Recording at all supported sample rates (44.1, 48, 88.2 and 96)kHz Mixer support for channel routing within the device (thanks to Daniel and Felix) Midi in and out.
Still needing work for full functionality (device is usable as is these things would make support as good as vendor (other os) drivers):
Playback works but has an odd artifact that's quite noticable when playing back pure sine functions (seems to drop a sample once every some power of 2 it's not the end of the world and is not noticable in normal use. This was discussed on this list in september however it remains unresolved. I should test my other usb soundcards and verify it's only the FTU that's affected tho.
The remaining mixer controls and switches (dsp/reverb sends and setting and internal/external clock controls) now we have a framework for the mixer support adding the remaining controls should be straightforward the big challenge imho was how to integrate into the quirk code.
Grant.
At Thu, 26 May 2011 11:08:15 +1000, Grant Diffey wrote:
I'd have exported a function creating FU mixer element instead of the control element link, but your patches are simple enough, so I applied as is.
I can have a look at this later and send a fixup.
Thanks to everyone involved for efforts in developing and merging this support.
So when Takashi says he's applied it what git branch/repo is that if it's published?
It's applied to sound git tree below (in fix/misc branch), and will be included in 2.6.40 kernel.
git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6.git
Takashi
Am 26.05.2011 03:08, schrieb Grant Diffey:
The remaining mixer controls and switches (dsp/reverb sends and setting and internal/external clock controls) now we have a framework for the mixer support adding the remaining controls should be straightforward the big challenge imho was how to integrate into the quirk code.
I already have most controls working for the DSP section in my private tree. The only thing missing is the switch to control which reverb style is used. I will send a patch soon.
Internal/external clock setting is a different beast. I've got no idea how to implement it. I don't even have a 2nd device to use as an external clock so I can't test anything. Chances are this will be relatively easy once Daniel gets his hands on a FTU.
--Felix
participants (4)
-
Daniel Mack
-
Felix Homann
-
Grant Diffey
-
Takashi Iwai