[alsa-devel] [PATCH 1/2] ALSA: add DSD formats
This patch adds two formats for Direct Stream Digital (DSD), a pulse-density encoding format which is described here: https://en.wikipedia.org/wiki/Direct_Stream_Digital
DSD operates on 2.8, 5.6 or 11.2MHz sample rates and as a 1-bit stream. In order to provide a compatibility way for pushing samples of DSD type through ordinary PCM channels, the "DoP open Standard" was created. See http://www.dsd-guide.com for a copy of the documentation.
The two new types describe streams that are capable of handling DSD samples in 8-bit or in 16-bit (or at a single or double data rate, respectively). For applications, the following mapping table is used to configure the DSD mode by selecting a combination of PCM sample rates and word lengths:
352.8kHz 705.6KHz 1411.2KHz
8-bit 2.8MHz 5.6MHz 11.2MHz 16-bit 5.6MHz 11.2MHz
Signed-off-by: Daniel Mack zonque@gmail.com --- include/sound/pcm.h | 2 ++ include/uapi/sound/asound.h | 4 +++- sound/core/pcm.c | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h index aa7b0a8..2dffd55 100644 --- a/include/sound/pcm.h +++ b/include/sound/pcm.h @@ -181,6 +181,8 @@ struct snd_pcm_ops { #define SNDRV_PCM_FMTBIT_G723_24_1B _SNDRV_PCM_FMTBIT(G723_24_1B) #define SNDRV_PCM_FMTBIT_G723_40 _SNDRV_PCM_FMTBIT(G723_40) #define SNDRV_PCM_FMTBIT_G723_40_1B _SNDRV_PCM_FMTBIT(G723_40_1B) +#define SNDRV_PCM_FMTBIT_DSD_U8 _SNDRV_PCM_FMTBIT(DSD_U8) +#define SNDRV_PCM_FMTBIT_DSD_U16 _SNDRV_PCM_FMTBIT(DSD_U16)
#ifdef SNDRV_LITTLE_ENDIAN #define SNDRV_PCM_FMTBIT_S16 SNDRV_PCM_FMTBIT_S16_LE diff --git a/include/uapi/sound/asound.h b/include/uapi/sound/asound.h index 1774a5c..f9b0d3f 100644 --- a/include/uapi/sound/asound.h +++ b/include/uapi/sound/asound.h @@ -214,7 +214,9 @@ typedef int __bitwise snd_pcm_format_t; #define SNDRV_PCM_FORMAT_G723_24_1B ((__force snd_pcm_format_t) 45) /* 1 sample in 1 byte */ #define SNDRV_PCM_FORMAT_G723_40 ((__force snd_pcm_format_t) 46) /* 8 Samples in 5 bytes */ #define SNDRV_PCM_FORMAT_G723_40_1B ((__force snd_pcm_format_t) 47) /* 1 sample in 1 byte */ -#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_G723_40_1B +#define SNDRV_PCM_FORMAT_DSD_U8 ((__force snd_pcm_format_t) 48) /* DSD in 1 byte */ +#define SNDRV_PCM_FORMAT_DSD_U16 ((__force snd_pcm_format_t) 49) /* DSD in 2 bytes */ +#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_16U
#ifdef SNDRV_LITTLE_ENDIAN #define SNDRV_PCM_FORMAT_S16 SNDRV_PCM_FORMAT_S16_LE diff --git a/sound/core/pcm.c b/sound/core/pcm.c index 578327e..433efdb 100644 --- a/sound/core/pcm.c +++ b/sound/core/pcm.c @@ -209,6 +209,8 @@ static char *snd_pcm_format_names[] = { FORMAT(G723_24_1B), FORMAT(G723_40), FORMAT(G723_40_1B), + FORMAT(DSD_U8), + FORMAT(DSD_U16), };
const char *snd_pcm_format_name(snd_pcm_format_t format)
Unfortunately, none of the UAC standards provides a way to identify DSD (Direct Stream Digital) formats. Hence, this patch adds a quirks handler to identify USB interfaces that are capable of handling DSD.
If that quirks handler returns /true/, the PCM formats will be augmented by SNDRV_PCM_FMTBIT_DSD_{U8_U16}, depending on the parsed sample_bytes.
Signed-off-by: Daniel Mack zonque@gmail.com --- sound/usb/format.c | 19 +++++++++++++++++++ sound/usb/quirks.c | 8 ++++++++ sound/usb/quirks.h | 3 +++ 3 files changed, 30 insertions(+)
diff --git a/sound/usb/format.c b/sound/usb/format.c index a695caf..e4c8610 100644 --- a/sound/usb/format.c +++ b/sound/usb/format.c @@ -136,6 +136,25 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip, snd_printk(KERN_INFO "%d:%u:%d : unsupported format bits %#x\n", chip->dev->devnum, fp->iface, fp->altsetting, format); } + + /* + * DSD has no designated specifiers in the USB audio spec, so we have + * to rely on a quirks list. + */ + if (snd_usb_interface_is_dsd(chip->dev, fp->iface, fp->altsetting)) { + switch (sample_bytes) { + case 1: + pcm_formats |= SNDRV_PCM_FMTBIT_DSD_U8; + break; + case 2: + pcm_formats |= SNDRV_PCM_FMTBIT_DSD_U16; + break; + default: + snd_printk(KERN_INFO "%d:%u:%d : unsupported DSD sample bitwidth %d\n", + chip->dev->devnum, fp->iface, fp->altsetting, sample_width); + } + } + return pcm_formats; }
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c index a2ac004..9d7e95c 100644 --- a/sound/usb/quirks.c +++ b/sound/usb/quirks.c @@ -905,3 +905,11 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, mdelay(20); }
+bool snd_usb_interface_is_dsd(struct usb_device *dev, + int interface, int alt_no) +{ + if ((le16_to_cpu(dev->descriptor.idVendor) == 0x23ba) && alt_no > 1) + return true; + + return false; +} diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h index 0ca9e91..a777ef0 100644 --- a/sound/usb/quirks.h +++ b/sound/usb/quirks.h @@ -30,4 +30,7 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe, __u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size);
+bool snd_usb_interface_is_dsd(struct usb_device *dev, + int interface, int alt_no); + #endif /* __USBAUDIO_QUIRKS_H */
participants (1)
-
Daniel Mack