]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - sound/usb/quirks.c
Merge tag 'pwm/for-4.10-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/thierry...
[mirror_ubuntu-artful-kernel.git] / sound / usb / quirks.c
index 152292e5ee2b2246ab649a65a920ce4b1f7e1669..b3fd2382fdd9ed62f102e210489eadd17f4e3b8f 100644 (file)
@@ -1165,6 +1165,18 @@ static bool is_marantz_denon_dac(unsigned int id)
        return false;
 }
 
+/* TEAC UD-501/UD-503/NT-503 USB DACs need a vendor cmd to switch
+ * between PCM/DOP and native DSD mode
+ */
+static bool is_teac_50X_dac(unsigned int id)
+{
+       switch (id) {
+       case USB_ID(0x0644, 0x8043): /* TEAC UD-501/UD-503/NT-503 */
+               return true;
+       }
+       return false;
+}
+
 int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
                              struct audioformat *fmt)
 {
@@ -1192,6 +1204,26 @@ int snd_usb_select_mode_quirk(struct snd_usb_substream *subs,
                        break;
                }
                mdelay(20);
+       } else if (is_teac_50X_dac(subs->stream->chip->usb_id)) {
+               /* Vendor mode switch cmd is required. */
+               switch (fmt->altsetting) {
+               case 3: /* DSD mode (DSD_U32) requested */
+                       err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+                                             USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+                                             1, 1, NULL, 0);
+                       if (err < 0)
+                               return err;
+                       break;
+
+               case 2: /* PCM or DOP mode (S32) requested */
+               case 1: /* PCM mode (S16) requested */
+                       err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0,
+                                             USB_DIR_OUT|USB_TYPE_VENDOR|USB_RECIP_INTERFACE,
+                                             0, 1, NULL, 0);
+                       if (err < 0)
+                               return err;
+                       break;
+               }
        }
        return 0;
 }
@@ -1217,6 +1249,12 @@ void snd_usb_endpoint_start_quirk(struct snd_usb_endpoint *ep)
             ep->chip->usb_id == USB_ID(0x0763, 0x2031)) &&
            ep->type == SND_USB_ENDPOINT_TYPE_DATA)
                ep->skip_packets = 16;
+
+       /* Work around devices that report unreasonable feedback data */
+       if ((ep->chip->usb_id == USB_ID(0x0644, 0x8038) ||  /* TEAC UD-H01 */
+            ep->chip->usb_id == USB_ID(0x1852, 0x5034)) && /* T+A Dac8 */
+           ep->syncmaxsize == 4)
+               ep->tenor_fb_quirk = 1;
 }
 
 void snd_usb_set_interface_quirk(struct usb_device *dev)
@@ -1331,5 +1369,11 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
        }
 
+       /* TEAC devices with USB DAC functionality */
+       if (is_teac_50X_dac(chip->usb_id)) {
+               if (fp->altsetting == 3)
+                       return SNDRV_PCM_FMTBIT_DSD_U32_BE;
+       }
+
        return 0;
 }