From: Daniel Mack <zonque@gmail.com>
To: Felix Homann <linuxaudio@showlabor.de>
Cc: Takashi Iwai <tiwai@suse.de>,
alsa-devel@alsa-project.org, Grant Diffey <gdiffey@gmail.com>
Subject: Re: A plea for help on mixer support for Fast Track Ultra (8R)
Date: Fri, 20 May 2011 13:37:43 +0200 [thread overview]
Message-ID: <BANLkTik-_m-Anr2s5=+G7ksyCHdOEGfN2w@mail.gmail.com> (raw)
In-Reply-To: <4DD64D13.9070200@showlabor.de>
[-- Attachment #1: Type: text/plain, Size: 663 bytes --]
On Fri, May 20, 2011 at 1:14 PM, Felix Homann <linuxaudio@showlabor.de> wrote:
> Sorry, here are the first lines:
>
> [ 4104.510080] usb 1-3: new high speed USB device using ehci_hcd and address
> 2
> [ 4104.661745] usb 1-3: config 1 interface 3 altsetting 0 bulk endpoint 0x7
> has invalid maxpacket 8
> [ 4104.661750] usb 1-3: config 1 interface 3 altsetting 0 bulk endpoint 0x87
> has invalid maxpacket 8
> [ 4104.824137] BUG: unable to handle kernel NULL pointer dereference at
> 0000000000000020
> [ 4104.824147] IP: [<ffffffffa04b0119>] snd_usb_mixer_controls+0x49/0x1a0
> [snd_usb_audio]
Ok, chip->ctrl_intf needs to be initialized. Next try ...
Daniel
[-- Attachment #2: ftu-mixer.diff --]
[-- Type: application/octet-stream, Size: 10970 bytes --]
diff --git a/sound/usb/card.c b/sound/usb/card.c
index a90662a..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>
@@ -492,14 +493,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 +501,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 ||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index eab06ed..7c07bc2 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,
@@ -535,20 +525,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;
}
@@ -967,7 +958,7 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return changed;
}
-static struct snd_kcontrol_new usb_feature_unit_ctl = {
+struct snd_kcontrol_new usb_feature_unit_ctl = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "", /* will be filled later manually */
.info = mixer_ctl_feature_info,
@@ -984,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
@@ -1176,7 +1170,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 +1334,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 +1635,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 +1852,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;
@@ -1935,7 +1929,7 @@ static int snd_usb_mixer_dev_free(struct snd_device *device)
*
* walk through all UAC_OUTPUT_TERMINAL descriptors to search for mixers
*/
-static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
+int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
{
struct mixer_build state;
int err;
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index b4a2c81..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;
@@ -55,4 +64,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 */
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 9146cff..24141af 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 chn, 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 = chn + 1;
+ cval->cmask = 1 << chn;
+
+ 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 n, chn, err;
+
+ for (n = 0; n < 8; n++) {
+ for (chn = 0; chn < 8; chn++) {
+ snprintf(name, sizeof(name),
+ "AIn%d - Out%d Capture Volume", chn + 1, n + 1);
+ err = snd_maudio_ftu_create_ctl(mixer, n, chn, name);
+ if (err < 0)
+ return err;
+ }
+
+ for (chn = 0; chn < 8; chn++) {
+ snprintf(name, sizeof(name),
+ "DIn%d - Out%d Playback Volume", chn + 1, n + 1);
+ err = snd_maudio_ftu_create_ctl(mixer, n, chn, 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,
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index bd13d72..a31a5c4 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>
@@ -58,6 +59,7 @@ static int create_composite_quirk(struct snd_usb_audio *chip,
if (quirk->ifnum != probed_ifnum)
usb_driver_claim_interface(driver, iface, (void *)-1L);
}
+
return 0;
}
@@ -263,6 +265,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.
@@ -294,7 +310,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
};
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
next prev parent reply other threads:[~2011-05-20 11:37 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-18 15:19 A plea for help on mixer support for Fast Track Ultra (8R) Felix Homann
2011-05-18 15:29 ` Felix Homann
2011-05-18 17:51 ` Daniel Mack
2011-05-18 18:46 ` Felix Homann
2011-05-18 21:30 ` Daniel Mack
2011-05-19 0:51 ` Grant Diffey
2011-05-19 5:42 ` Takashi Iwai
2011-05-19 6:45 ` Felix Homann
2011-05-19 7:15 ` Clemens Ladisch
2011-05-19 7:24 ` Takashi Iwai
2011-05-19 8:14 ` Felix Homann
2011-05-19 8:52 ` Daniel Mack
2011-05-19 10:56 ` Felix Homann
2011-05-19 11:05 ` Daniel Mack
2011-05-19 12:23 ` Felix Homann
2011-05-19 13:36 ` Felix Homann
2011-05-19 13:42 ` Felix Homann
2011-05-19 14:12 ` Daniel Mack
2011-05-20 10:12 ` Felix Homann
2011-05-20 11:12 ` Daniel Mack
2011-05-20 11:14 ` Felix Homann
2011-05-20 11:37 ` Daniel Mack [this message]
2011-05-20 15:08 ` Grant Diffey
2011-05-20 15:43 ` Grant Diffey
2011-05-20 15:52 ` Felix Homann
2011-05-20 15:54 ` Daniel Mack
2011-05-20 16:25 ` Grant Diffey
2011-05-20 16:38 ` Daniel Mack
2011-05-20 16:44 ` Felix Homann
2011-05-20 16:52 ` Felix Homann
2011-05-24 10:11 ` Felix Homann
2011-05-24 10:47 ` Daniel Mack
2011-05-24 11:54 ` Takashi Iwai
2011-05-24 23:55 ` Grant Diffey
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to='BANLkTik-_m-Anr2s5=+G7ksyCHdOEGfN2w@mail.gmail.com' \
--to=zonque@gmail.com \
--cc=alsa-devel@alsa-project.org \
--cc=gdiffey@gmail.com \
--cc=linuxaudio@showlabor.de \
--cc=tiwai@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).