Merge tag 'mac80211-next-for-davem-2015-01-19' of git://git.kernel.org/pub/scm/linux...
[pandora-kernel.git] / sound / usb / quirks.c
index 60dfe0d..a739841 100644 (file)
 static int create_composite_quirk(struct snd_usb_audio *chip,
                                  struct usb_interface *iface,
                                  struct usb_driver *driver,
-                                 const struct snd_usb_audio_quirk *quirk)
+                                 const struct snd_usb_audio_quirk *quirk_comp)
 {
        int probed_ifnum = get_iface_desc(iface->altsetting)->bInterfaceNumber;
+       const struct snd_usb_audio_quirk *quirk;
        int err;
 
-       for (quirk = quirk->data; quirk->ifnum >= 0; ++quirk) {
+       for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) {
                iface = usb_ifnum_to_if(chip->dev, quirk->ifnum);
                if (!iface)
                        continue;
@@ -58,9 +59,17 @@ static int create_composite_quirk(struct snd_usb_audio *chip,
                err = snd_usb_create_quirk(chip, iface, driver, quirk);
                if (err < 0)
                        return err;
-               if (quirk->ifnum != probed_ifnum)
+       }
+
+       for (quirk = quirk_comp->data; quirk->ifnum >= 0; ++quirk) {
+               iface = usb_ifnum_to_if(chip->dev, quirk->ifnum);
+               if (!iface)
+                       continue;
+               if (quirk->ifnum != probed_ifnum &&
+                   !usb_interface_claimed(iface))
                        usb_driver_claim_interface(driver, iface, (void *)-1L);
        }
+
        return 0;
 }
 
@@ -1102,6 +1111,44 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
        }
 }
 
+
+/* Marantz/Denon USB DACs need a vendor cmd to switch
+ * between PCM and native DSD mode
+ */
+int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
+                             struct audioformat *fmt)
+{
+       struct usb_device *dev = subs->dev;
+       int err;
+
+       switch (subs->stream->chip->usb_id) {
+       case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
+       case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
+
+               /* First switch to alt set 0, otherwise the mode switch cmd
+                * will not be accepted by the DAC
+                */
+               err = usb_set_interface(dev, fmt->iface, 0);
+               if (err < 0)
+                       return err;
+
+               mdelay(20); /* Delay needed after setting the interface */
+
+               switch (fmt->altsetting) {
+               case 2: /* DSD mode requested */
+               case 1: /* PCM mode requested */
+                       err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+                                             USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+                                             fmt->altsetting - 1, 1, NULL, 0);
+                       if (err < 0)
+                               return err;
+                       break;
+               }
+               mdelay(20);
+       }
+       return 0;
+}
+
 void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
 {
        /*
@@ -1160,6 +1207,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
                        break;
                }
        }
+
+       /* Zoom R16/24 needs a tiny delay here, otherwise requests like
+        * get/set frequency return as failed despite actually succeeding.
+        */
+       if ((le16_to_cpu(dev->descriptor.idVendor) == 0x1686) &&
+           (le16_to_cpu(dev->descriptor.idProduct) == 0x00dd) &&
+           (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+               mdelay(1);
 }
 
 /*
@@ -1190,8 +1245,9 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
 
        /* XMOS based USB DACs */
        switch (chip->usb_id) {
-       /* iFi Audio micro/nano iDSD */
-       case USB_ID(0x20b1, 0x3008):
+       case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
+       case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
+       case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
                if (fp->altsetting == 2)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
@@ -1204,5 +1260,16 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                break;
        }
 
+       /* Denon/Marantz devices with USB DAC functionality */
+       switch (chip->usb_id) {
+       case USB_ID(0x154e, 0x3005): /* Marantz HD-DAC1 */
+       case USB_ID(0x154e, 0x3006): /* Marantz SA-14S1 */
+               if (fp->altsetting == 2)
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+               break;
+       default:
+               break;
+       }
+
        return 0;
 }