01-02-2020, 06:10 PM
An addendum.
I got to wondering how Linux determines if a USB DAC is DSD-capable. It's not something obvious in the USB enumeration of the interface.
Apparently it's done based on recognizing the specific device. Here's a snippet from the kernel-source code for sound/usb/quirks.c. (NOTE the intro comment "all hardware that is known to support this format has to be listed here")
My Khadas Tone Board enumerates as USB vendor 20b1 (e.g., 0x20b1) which, by the last switch statement, is identified to the kernel (thence to ALSA) as DSD-capable.
Regards,
Kent
I got to wondering how Linux determines if a USB DAC is DSD-capable. It's not something obvious in the USB enumeration of the interface.
Apparently it's done based on recognizing the specific device. Here's a snippet from the kernel-source code for sound/usb/quirks.c. (NOTE the intro comment "all hardware that is known to support this format has to be listed here")
Code:
/*
* snd_usb_interface_dsd_format_quirks() is called from format.c to
* augment the PCM format bit-field for DSD types. The UAC standards
* don't have a designated bit field to denote DSD-capable interfaces,
* hence all hardware that is known to support this format has to be
* listed here.
*/
u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
struct audioformat *fp,
unsigned int sample_bytes)
{
struct usb_interface *iface;
/* Playback Designs */
if (USB_ID_VENDOR(chip->usb_id) == 0x23ba &&
USB_ID_PRODUCT(chip->usb_id) < 0x0110) {
switch (fp->altsetting) {
case 1:
fp->dsd_dop = true;
return SNDRV_PCM_FMTBIT_DSD_U16_LE;
case 2:
fp->dsd_bitrev = true;
return SNDRV_PCM_FMTBIT_DSD_U8;
case 3:
fp->dsd_bitrev = true;
return SNDRV_PCM_FMTBIT_DSD_U16_LE;
}
}
/* XMOS based USB DACs */
switch (chip->usb_id) {
case USB_ID(0x1511, 0x0037): /* AURALiC VEGA */
case USB_ID(0x2522, 0x0012): /* LH Labs VI DAC Infinity */
case USB_ID(0x2772, 0x0230): /* Pro-Ject Pre Box S2 Digital */
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
case USB_ID(0x16b0, 0x06b2): /* NuPrime DAC-10 */
case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
case USB_ID(0x16d0, 0x0733): /* Furutech ADL Stratos */
case USB_ID(0x16d0, 0x09db): /* NuPrime Audio DAC-9 */
case USB_ID(0x1db5, 0x0003): /* Bryston BDA3 */
case USB_ID(0x22e1, 0xca01): /* HDTA Serenade DSD */
case USB_ID(0x249c, 0x9326): /* M2Tech Young MkIII */
case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
case USB_ID(0x2622, 0x0041): /* Audiolab M-DAC+ */
case USB_ID(0x27f7, 0x3002): /* W4S DAC-2v2SE */
case USB_ID(0x29a2, 0x0086): /* Mutec MC3+ USB */
case USB_ID(0x6b42, 0x0042): /* MSB Technology */
if (fp->altsetting == 3)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
/* Amanero Combo384 USB based DACs with native DSD support */
case USB_ID(0x16d0, 0x071a): /* Amanero - Combo384 */
case USB_ID(0x2ab6, 0x0004): /* T+A DAC8DSD-V2.0, MP1000E-V2.0, MP2000R-V2.0, MP2500R-V2.0, MP3100HV-V2.0 */
case USB_ID(0x2ab6, 0x0005): /* T+A USB HD Audio 1 */
case USB_ID(0x2ab6, 0x0006): /* T+A USB HD Audio 2 */
if (fp->altsetting == 2) {
switch (le16_to_cpu(chip->dev->descriptor.bcdDevice)) {
case 0x199:
return SNDRV_PCM_FMTBIT_DSD_U32_LE;
case 0x19b:
case 0x203:
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
default:
break;
}
}
break;
case USB_ID(0x16d0, 0x0a23):
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
default:
break;
}
/* ITF-USB DSD based DACs */
if (is_itf_usb_dsd_dac(chip->usb_id)) {
iface = usb_ifnum_to_if(chip->dev, fp->iface);
/* Altsetting 2 support native DSD if the num of altsets is
* three (0-2),
* Altsetting 3 support native DSD if the num of altsets is
* four (0-3).
*/
if (fp->altsetting == iface->num_altsetting - 1)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
}
/* Mostly generic method to detect many DSD-capable implementations -
* from XMOS/Thesycon
*/
switch (USB_ID_VENDOR(chip->usb_id)) {
case 0x152a: /* Thesycon devices */
case 0x20b1: /* XMOS based devices */
case 0x22d9: /* Oppo */
case 0x23ba: /* Playback Designs */
case 0x25ce: /* Mytek devices */
case 0x278b: /* Rotel? */
case 0x292b: /* Gustard/Ess based devices */
case 0x2ab6: /* T+A devices */
case 0x3842: /* EVGA */
case 0xc502: /* HiBy devices */
if (fp->dsd_raw)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
default:
break;
}
return 0;
}
My Khadas Tone Board enumerates as USB vendor 20b1 (e.g., 0x20b1) which, by the last switch statement, is identified to the kernel (thence to ALSA) as DSD-capable.
Regards,
Kent