Skip to content

Instantly share code, notes, and snippets.

@Apsu
Created July 7, 2012 04:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Apsu/3064557 to your computer and use it in GitHub Desktop.
Save Apsu/3064557 to your computer and use it in GitHub Desktop.
M-Audio FastTrack Pro 48/96kHz 24-bit kernel patch
--- original/linux-2.6.38.4/sound/usb/quirks.c 2011-04-21 16:34:46.000000000 -0500
+++ new/linux-2.6.38.4/sound/usb/quirks.c 2011-04-23 20:32:19.486586452 -0500
@@ -427,16 +427,17 @@
/*
* Setup quirks
*/
-#define AUDIOPHILE_SET 0x01 /* if set, parse device_setup */
-#define AUDIOPHILE_SET_DTS 0x02 /* if set, enable DTS Digital Output */
-#define AUDIOPHILE_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
-#define AUDIOPHILE_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */
-#define AUDIOPHILE_SET_DI 0x10 /* if set, enable Digital Input */
-#define AUDIOPHILE_SET_MASK 0x1F /* bit mask for setup value */
-#define AUDIOPHILE_SET_24B_48K_DI 0x19 /* value for 24bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_24B_48K_NOTDI 0x09 /* value for 24bits+48KHz+No Digital Input */
-#define AUDIOPHILE_SET_16B_48K_DI 0x11 /* value for 16bits+48KHz+Digital Input */
-#define AUDIOPHILE_SET_16B_48K_NOTDI 0x01 /* value for 16bits+48KHz+No Digital Input */
+#define MAUDIO_SET 0x01 /* if set, parse chip_setup */
+#define MAUDIO_SET_COMPATIBLE 0x80 /* if set, use only "win-compatible" interfaces */
+#define MAUDIO_SET_DTS 0x02 /* if set, enable DTS Digital Output */
+#define MAUDIO_SET_96K 0x04 /* 48-96KHz rate if set, 8-48KHz otherwise */
+#define MAUDIO_SET_24B 0x08 /* 24bits sample if set, 16bits otherwise */
+#define MAUDIO_SET_DI 0x10 /* if set, enable Digital Input */
+#define MAUDIO_SET_MASK 0x1F /* bit mask for setup value */
+#define MAUDIO_SET_24B_48K_DI 0x19 /* value for 24bits+48KHz+Digital Input */
+#define MAUDIO_SET_24B_48K_NOTDI 0x09 /* value for 24bits+48KHz+No Digital Input */
+#define MAUDIO_SET_16B_48K_DI 0x11 /* value for 16bits+48KHz+Digital Input */
+#define MAUDIO_SET_16B_48K_NOTDI 0x01 /* value for 16bits+48KHz+No Digital Input */
static int audiophile_skip_setting_quirk(struct snd_usb_audio *chip,
int iface,
@@ -447,38 +448,137 @@
*/
usb_set_interface(chip->dev, iface, 0);
- if (chip->setup & AUDIOPHILE_SET) {
- if ((chip->setup & AUDIOPHILE_SET_DTS)
+ if (chip->setup & MAUDIO_SET) {
+ if ((chip->setup & MAUDIO_SET_DTS)
&& altno != 6)
return 1; /* skip this altsetting */
- if ((chip->setup & AUDIOPHILE_SET_96K)
+ if ((chip->setup & MAUDIO_SET_96K)
&& altno != 1)
return 1; /* skip this altsetting */
- if ((chip->setup & AUDIOPHILE_SET_MASK) ==
- AUDIOPHILE_SET_24B_48K_DI && altno != 2)
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_24B_48K_DI && altno != 2)
return 1; /* skip this altsetting */
- if ((chip->setup & AUDIOPHILE_SET_MASK) ==
- AUDIOPHILE_SET_24B_48K_NOTDI && altno != 3)
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_24B_48K_NOTDI && altno != 3)
return 1; /* skip this altsetting */
- if ((chip->setup & AUDIOPHILE_SET_MASK) ==
- AUDIOPHILE_SET_16B_48K_DI && altno != 4)
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_16B_48K_DI && altno != 4)
return 1; /* skip this altsetting */
- if ((chip->setup & AUDIOPHILE_SET_MASK) ==
- AUDIOPHILE_SET_16B_48K_NOTDI && altno != 5)
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_16B_48K_NOTDI && altno != 5)
return 1; /* skip this altsetting */
}
return 0; /* keep this altsetting */
}
+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 {
+ 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 */
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_24B_48K_DI && altno != 2)
+ return 1; /* skip this altsetting */
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_24B_48K_NOTDI && altno != 3)
+ return 1; /* skip this altsetting */
+ if ((chip->setup & MAUDIO_SET_MASK) ==
+ MAUDIO_SET_16B_48K_NOTDI && altno != 4)
+ return 1; /* skip this altsetting */
+ }
+ }
+ snd_printk(KERN_INFO "using altsetting %d for interface %d config %d\n", altno, iface, chip->setup);
+ 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 digital input */
+
+ if((altno != 2) && (altno != 5))
+ return 1; /* enable only altsets 2 and 5 */
+ }
+ } else {
+ /* keep only 16-Bit mode */
+ if(altno !=1)
+ return 1;
+ }
+
+ snd_printk(KERN_INFO "using altsetting %d for interface %d config %d\n", altno, iface, chip->setup);
+ return 0; /* keep this altsetting */
+}
+
+
+static int snd_usb_fasttrackpro_boot_quirk(struct usb_device *dev, struct usb_interface *intf)
+{
+ int err;
+
+ if(dev->actconfig->desc.bConfigurationValue==1) {
+ if(intf->num_altsetting==1) {
+ snd_printk(KERN_INFO "Switching to config #2\n");
+ /* This function has to be available by the usb core module.
+ if it is not available 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_printk("error usb_driver_set_configuration: %d\n", err);
+ return -ENODEV;
+ }
+ }
+ } else {
+ snd_printk(KERN_INFO "Fast Track Pro config OK\n");
+ }
+
+ return 0;
+}
+
int snd_usb_apply_interface_quirk(struct snd_usb_audio *chip,
int iface,
int altno)
{
- /* audiophile usb: skip altsets incompatible with device_setup */
+ /* m-audio usb devices: skip altsets incompatible with chip-setup */
if (chip->usb_id == USB_ID(0x0763, 0x2003))
return audiophile_skip_setting_quirk(chip, iface, altno);
+ if (chip->usb_id == USB_ID(0x0763, 0x2001))
+ return quattro_skip_setting_quirk(chip, iface, altno);
+
+ if (chip->usb_id == USB_ID(0x0763, 0x2012))
+ return fasttrackpro_skip_setting_quirk(chip, iface, altno);
+
return 0;
}
@@ -510,6 +610,10 @@
if (id == USB_ID(0x133e, 0x0815))
return snd_usb_accessmusic_boot_quirk(dev);
+ /* M-Audio Fast Track Pro */
+ if (id == USB_ID(0x0763, 0x2012))
+ return snd_usb_fasttrackpro_boot_quirk(dev, intf);
+
return 0;
}
@@ -519,14 +623,23 @@
int snd_usb_is_big_endian_format(struct snd_usb_audio *chip, struct audioformat *fp)
{
switch (chip->usb_id) {
- case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
- if (fp->endpoint & USB_DIR_IN)
+ case USB_ID(0x0763, 0x2001): /* M-Audio Quattro: captured data only */
+ /* it depends on altsetting wether the device is big-endian or not */
+ if(fp->altsetting==2 || fp->altsetting==3 ||
+ fp->altsetting==5 || fp->altsetting==6)
+ return 1;
+ break;
+ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+ if (chip->setup == 0x00 ||
+ fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
return 1;
- break;
- case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
- if (chip->setup == 0x00 ||
- fp->altsetting==1 || fp->altsetting==2 || fp->altsetting==3)
+ break;
+ case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro */
+ /* it depends on altsetting wether the device is big-endian or not*/
+ if(fp->altsetting==2 || fp->altsetting==3 ||
+ fp->altsetting==5 || fp->altsetting==6)
return 1;
+ break;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment