ALSA: usb-audio - Add quirks for M-Audio Fast Track Pro and Quattro

This patch gives M-Audio Fast Track Pro and M-Audio Quattro quirks and
endpoints to boot and setup those devices with special options (digital
inputs and outputs, 24 bits mode, etc...). M-Audio Audiophile quirks are
just adapted to match the new global M-Audio parameters.

Special configurations can be then loaded through a modprobe conf file.
For example, to set the 24 bits mode on the Fast Track Pro add
/etc/modprobe.d/fast_track_pro.conf :

    options snd_usb_audio   vid=0x763 pid=0x2012 device_setup=0x08

Here is a list of the possibilities in this example :
http://files.parisson.com/debian/fast-track-pro.conf

Signed-off-by: Guillaume Pellerin <yomguy@parisson.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Guillaume Pellerin 2011-07-12 18:13:46 +02:00 committed by Takashi Iwai
parent 3101ba035c
commit 0f5733b0c8
2 changed files with 136 additions and 25 deletions

View File

@ -408,6 +408,8 @@ int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
/* doesn't set the sample rate attribute, but supports it */ /* doesn't set the sample rate attribute, but supports it */
fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE; fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
break; break;
case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
case USB_ID(0x047f, 0x0ca1): /* plantronics headset */ case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
an older model 77d:223) */ an older model 77d:223) */

View File

@ -369,6 +369,30 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
return 0; return 0;
} }
static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev)
{
int err;
if (dev->actconfig->desc.bConfigurationValue == 1) {
snd_printk(KERN_INFO "usb-audio: "
"Fast Track Pro switching to config #2\n");
/* This function has to be available by the usb core module.
* if it is not avialable the boot quirk has to be left out
* and the configuration has to be set by udev or hotplug
* rules
*/
err = usb_driver_set_configuration(dev, 2);
if (err < 0) {
snd_printdd("error usb_driver_set_configuration: %d\n",
err);
return -ENODEV;
}
} else
snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
return 0;
}
/* /*
* C-Media CM106/CM106+ have four 16-bit internal registers that are nicely * C-Media CM106/CM106+ have four 16-bit internal registers that are nicely
* documented in the device's data sheet. * documented in the device's data sheet.
@ -471,16 +495,49 @@ static int snd_usb_nativeinstruments_boot_quirk(struct usb_device *dev)
/* /*
* Setup quirks * Setup quirks
*/ */
#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */ #define MAUDIO_SET 0x01 /* parse device_setup */
#define AUDIOPHILE_SET_DTS 0x02 /* if set, enable DTS Digital Output */ #define MAUDIO_SET_COMPATIBLE 0x80 /* use only "win-compatible" interfaces */
#define AUDIOPHILE_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */ #define MAUDIO_SET_DTS 0x02 /* enable DTS Digital Output */
#define AUDIOPHILE_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */ #define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
#define AUDIOPHILE_SET_DI 0x10 /* if set, enable Digital Input */ #define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */
#define AUDIOPHILE_SET_MASK 0x1F /* bit mask for setup value */ #define MAUDIO_SET_DI 0x10 /* enable Digital Input */
#define AUDIOPHILE_SET_24B_48K_DI 0x19 /* value for 24bits+48KHz+Digital Input */ #define MAUDIO_SET_MASK 0x1f /* bit mask for setup value */
#define AUDIOPHILE_SET_24B_48K_NOTDI 0x09 /* value for 24bits+48KHz+No Digital Input */ #define MAUDIO_SET_24B_48K_DI 0x19 /* 24bits+48KHz+Digital Input */
#define AUDIOPHILE_SET_16B_48K_DI 0x11 /* value for 16bits+48KHz+Digital Input */ #define MAUDIO_SET_24B_48K_NOTDI 0x09 /* 24bits+48KHz+No Digital Input */
#define AUDIOPHILE_SET_16B_48K_NOTDI 0x01 /* value for 16bits+48KHz+No Digital Input */ #define MAUDIO_SET_16B_48K_DI 0x11 /* 16bits+48KHz+Digital Input */
#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* 16bits+48KHz+No Digital Input */
static int quattro_skip_setting_quirk(struct snd_usb_audio *chip,
int iface, int altno)
{
/* Reset ALL ifaces to 0 altsetting.
* Call it for every possible altsetting of every interface.
*/
usb_set_interface(chip->dev, iface, 0);
if (chip->setup & MAUDIO_SET) {
if (chip->setup & MAUDIO_SET_COMPATIBLE) {
if (iface != 1 && iface != 2)
return 1; /* skip all interfaces but 1 and 2 */
} else {
unsigned int mask;
if (iface == 1 || iface == 2)
return 1; /* skip interfaces 1 and 2 */
if ((chip->setup & MAUDIO_SET_96K) && altno != 1)
return 1; /* skip this altsetting */
mask = chip->setup & MAUDIO_SET_MASK;
if (mask == MAUDIO_SET_24B_48K_DI && altno != 2)
return 1; /* skip this altsetting */
if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3)
return 1; /* skip this altsetting */
if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 4)
return 1; /* skip this altsetting */
}
}
snd_printdd(KERN_INFO
"using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup);
return 0; /* keep this altsetting */
}
static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip, static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
int iface, int iface,
@ -491,30 +548,65 @@ static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
*/ */
usb_set_interface(chip->dev, iface, 0); usb_set_interface(chip->dev, iface, 0);
if (chip->setup & AUDIOPHILE_SET) { if (chip->setup & MAUDIO_SET) {
if ((chip->setup & AUDIOPHILE_SET_DTS) unsigned int mask;
&& altno != 6) if ((chip->setup & MAUDIO_SET_DTS) && altno != 6)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
if ((chip->setup & AUDIOPHILE_SET_96K) if ((chip->setup & MAUDIO_SET_96K) && altno != 1)
&& altno != 1)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
if ((chip->setup & AUDIOPHILE_SET_MASK) == mask = chip->setup & MAUDIO_SET_MASK;
AUDIOPHILE_SET_24B_48K_DI && altno != 2) if (mask == MAUDIO_SET_24B_48K_DI && altno != 2)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
if ((chip->setup & AUDIOPHILE_SET_MASK) == if (mask == MAUDIO_SET_24B_48K_NOTDI && altno != 3)
AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
if ((chip->setup & AUDIOPHILE_SET_MASK) == if (mask == MAUDIO_SET_16B_48K_DI && altno != 4)
AUDIOPHILE_SET_16B_48K_DI && altno != 4)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
if ((chip->setup & AUDIOPHILE_SET_MASK) == if (mask == MAUDIO_SET_16B_48K_NOTDI && altno != 5)
AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5)
return 1; /* skip this altsetting */ return 1; /* skip this altsetting */
} }
return 0; /* keep this altsetting */ return 0; /* keep this altsetting */
} }
static int fasttrackpro_skip_setting_quirk(struct snd_usb_audio *chip,
int iface, int altno)
{
/* Reset ALL ifaces to 0 altsetting.
* Call it for every possible altsetting of every interface.
*/
usb_set_interface(chip->dev, iface, 0);
/* possible configuration where both inputs and only one output is
*used is not supported by the current setup
*/
if (chip->setup & (MAUDIO_SET | MAUDIO_SET_24B)) {
if (chip->setup & MAUDIO_SET_96K) {
if (altno != 3 && altno != 6)
return 1;
} else if (chip->setup & MAUDIO_SET_DI) {
if (iface == 4)
return 1; /* no analog input */
if (altno != 2 && altno != 5)
return 1; /* enable only altsets 2 and 5 */
} else {
if (iface == 5)
return 1; /* disable digialt input */
if (altno != 2 && altno != 5)
return 1; /* enalbe only altsets 2 and 5 */
}
} else {
/* keep only 16-Bit mode */
if (altno != 1)
return 1;
}
snd_printdd(KERN_INFO
"using altsetting %d for interface %d config %d\n",
altno, iface, chip->setup);
return 0; /* keep this altsetting */
}
int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip, int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
int iface, int iface,
int altno) int altno)
@ -522,6 +614,12 @@ int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
/* audiophile usb: skip altsets incompatible with device_setup */ /* audiophile usb: skip altsets incompatible with device_setup */
if (chip->usb_id == USB_ID(0x0763, 0x2003)) if (chip->usb_id == USB_ID(0x0763, 0x2003))
return audiophile_skip_setting_quirk(chip, iface, altno); return audiophile_skip_setting_quirk(chip, iface, altno);
/* quattro usb: skip altsets incompatible with device_setup */
if (chip->usb_id == USB_ID(0x0763, 0x2001))
return quattro_skip_setting_quirk(chip, iface, altno);
/* fasttrackpro usb: skip altsets incompatible with device_setup */
if (chip->usb_id == USB_ID(0x0763, 0x2012))
return fasttrackpro_skip_setting_quirk(chip, iface, altno);
return 0; return 0;
} }
@ -560,6 +658,8 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */ case USB_ID(0x17cc, 0x1010): /* Traktor Audio 6 */
case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */ case USB_ID(0x17cc, 0x1020): /* Traktor Audio 10 */
return snd_usb_nativeinstruments_boot_quirk(dev); return snd_usb_nativeinstruments_boot_quirk(dev);
case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
return snd_usb_fasttrackpro_boot_quirk(dev);
} }
return 0; return 0;
@ -570,15 +670,24 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
*/ */
int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp) int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
{ {
/* it depends on altsetting wether the device is big-endian or not */
switch (chip->usb_id) { switch (chip->usb_id) {
case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */ case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
if (fp->endpoint & USB_DIR_IN) if (fp->altsetting == 2 || fp->altsetting == 3 ||
fp->altsetting == 5 || fp->altsetting == 6)
return 1; return 1;
break; break;
case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
if (chip->setup == 0x00 || if (chip->setup == 0x00 ||
fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3) fp->altsetting == 1 || fp->altsetting == 2 ||
fp->altsetting == 3)
return 1; return 1;
break;
case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro */
if (fp->altsetting == 2 || fp->altsetting == 3 ||
fp->altsetting == 5 || fp->altsetting == 6)
return 1;
break;
} }
return 0; return 0;
} }