* [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
@ 2013-04-16 16:01 Daniel Mack
2013-04-16 16:01 ` [PATCH v3 1/5] ALSA: add DSD formats Daniel Mack
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
In contrast to the first two approaches, this one keeps the userspace
unaware of the actual transport on the bus.
More specifically, the DSD_U16_LE format may be implemented to actually
send DOP samples to the device, depending on the quirks entries.
Also, as there is quite some confusion in both data file formats as
well as hardware sample formats about whether to stuff the oldest bit
in the MSB or the LSB of a byte, ALSA defines that now to be in the
MSB, as far as the ALSA userspace layer is concerned. The driver
learned functions to re-encode the bytes according to what the hardware
supports.
I also wrote a very basic test tool which I published here:
https://github.com/zonque/alsa-dsd-player
Thanks,
Daniel
Daniel Mack (5):
ALSA: add DSD formats
ALSA: snd-usb: use ep->stride from urb callbacks
ALSA: snd-usb: add support for DSD DOP stream transport
ALSA: snd-usb: add support for bit-reversed byte formats
ALSA: snd-usb: add quirks handler for DSD streams
include/sound/pcm.h | 2 +
include/uapi/sound/asound.h | 4 +-
sound/core/pcm.c | 2 +
sound/core/pcm_misc.c | 8 +++
sound/usb/card.h | 8 +++
sound/usb/endpoint.c | 9 ++++
sound/usb/format.c | 3 ++
sound/usb/pcm.c | 118 ++++++++++++++++++++++++++++++++++++-------
sound/usb/quirks.c | 28 ++++++++++
sound/usb/quirks.h | 4 ++
10 files changed, 167 insertions(+), 19 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v3 1/5] ALSA: add DSD formats
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
@ 2013-04-16 16:01 ` Daniel Mack
2013-04-16 16:01 ` [PATCH v3 2/5] ALSA: snd-usb: use ep->stride from urb callbacks Daniel Mack
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
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.
The two new types added by this patch describe streams that are capable
of handling DSD samples in DOP format as 8-bit or in 16-bit (or at a x8
or x16 data rate, respectively).
DSD itself specifies samples in *bit*, while DOP and ALSA handle them
as *bytes*. Hence, a factor of 8 or 16 has to be applied for the sample
rare configuration, according to the following table:
configured hardware
176.4KHz 352.8kHz 705.6KHz <---- sample rate
8-bit 2.8MHz 5.6MHz
16-bit 2.8Mhz 5.6MHz 11.2MHz
`-----------------------------'
actual DSD sample rates
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
include/sound/pcm.h | 2 ++
include/uapi/sound/asound.h | 4 +++-
sound/core/pcm.c | 2 ++
sound/core/pcm_misc.c | 8 ++++++++
4 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index aa7b0a8..1b0c648 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_LE _SNDRV_PCM_FMTBIT(DSD_U16_LE)
#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..e3983d5 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, 1-byte samples DSD (x8) */
+#define SNDRV_PCM_FORMAT_DSD_U16_LE ((__force snd_pcm_format_t) 49) /* DSD, 2-byte samples DSD (x16), little endian */
+#define SNDRV_PCM_FORMAT_LAST SNDRV_PCM_FORMAT_DSD_U16_LE
#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..17f45e8 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_LE),
};
const char *snd_pcm_format_name(snd_pcm_format_t format)
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index b875b19..43f24cc 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -140,6 +140,14 @@ static struct pcm_format_data pcm_formats[(INT)SNDRV_PCM_FORMAT_LAST+1] = {
.width = 5, .phys = 5, .le = -1, .signd = -1,
.silence = {},
},
+ [SNDRV_PCM_FORMAT_DSD_U8] = {
+ .width = 8, .phys = 8, .le = 1, .signd = 0,
+ .silence = {},
+ },
+ [SNDRV_PCM_FORMAT_DSD_U16_LE] = {
+ .width = 16, .phys = 16, .le = 1, .signd = 0,
+ .silence = {},
+ },
/* FIXME: the following three formats are not defined properly yet */
[SNDRV_PCM_FORMAT_MPEG] = {
.le = -1, .signd = -1,
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 2/5] ALSA: snd-usb: use ep->stride from urb callbacks
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
2013-04-16 16:01 ` [PATCH v3 1/5] ALSA: add DSD formats Daniel Mack
@ 2013-04-16 16:01 ` Daniel Mack
2013-04-16 16:01 ` [PATCH v3 3/5] ALSA: snd-usb: add support for DSD DOP stream transport Daniel Mack
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
For normal PCM transfer, this change has no effect, as the endpoint's
stride is always frame_bits/8. For DSD DOP streams, however, which is
added later, the hardware stride differs from the software stride, and
the endpoint has the correct information in these cases.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
sound/usb/pcm.c | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 815a37d..6f85202 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1236,8 +1236,8 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
counts = snd_usb_endpoint_next_packet_size(ep);
/* set up descriptor */
- urb->iso_frame_desc[i].offset = frames * stride;
- urb->iso_frame_desc[i].length = counts * stride;
+ urb->iso_frame_desc[i].offset = frames * ep->stride;
+ urb->iso_frame_desc[i].length = counts * ep->stride;
frames += counts;
urb->number_of_packets++;
subs->transfer_done += counts;
@@ -1251,14 +1251,14 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
frames -= subs->transfer_done;
counts -= subs->transfer_done;
urb->iso_frame_desc[i].length =
- counts * stride;
+ counts * ep->stride;
subs->transfer_done = 0;
}
i++;
if (i < ctx->packets) {
/* add a transfer delimiter */
urb->iso_frame_desc[i].offset =
- frames * stride;
+ frames * ep->stride;
urb->iso_frame_desc[i].length = 0;
urb->number_of_packets++;
}
@@ -1269,7 +1269,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
!snd_usb_endpoint_implicit_feedback_sink(subs->data_endpoint)) /* finish at the period boundary */
break;
}
- bytes = frames * stride;
+ bytes = frames * ep->stride;
if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
/* err, the transferred area goes over buffer boundary. */
unsigned int bytes1 =
@@ -1310,8 +1310,8 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
{
unsigned long flags;
struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
- int stride = runtime->frame_bits >> 3;
- int processed = urb->transfer_buffer_length / stride;
+ struct snd_usb_endpoint *ep = subs->data_endpoint;
+ int processed = urb->transfer_buffer_length / ep->stride;
int est_delay;
/* ignore the delay accounting when procssed=0 is given, i.e.
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 3/5] ALSA: snd-usb: add support for DSD DOP stream transport
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
2013-04-16 16:01 ` [PATCH v3 1/5] ALSA: add DSD formats Daniel Mack
2013-04-16 16:01 ` [PATCH v3 2/5] ALSA: snd-usb: use ep->stride from urb callbacks Daniel Mack
@ 2013-04-16 16:01 ` Daniel Mack
2013-04-16 16:01 ` [PATCH v3 4/5] ALSA: snd-usb: add support for bit-reversed byte formats Daniel Mack
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
In order to provide a compatibility way for pushing DSD
samples through ordinary PCM channels, the "DoP open Standard" was
invented. See http://www.dsd-guide.com for the official document.
The host is required to stuff DSD marker bytes (0x05, 0xfa,
alternating) in the MSB of 24 bit wide samples on the bus, in addition
to the 16 bits of actual DSD sample payload.
To support this, the hardware and software stride logic in the driver
has to be tweaked a bit, as we make the userspace believe we're
operating on 16 bit samples, while we in fact push one more byte per
channel down to the hardware.
The DOP runtime information is stored in struct snd_usb_substream, so
we can keep track of our state across multiple calls to
prepare_playback_urb_dsd_dop().
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
sound/usb/card.h | 7 ++++
sound/usb/endpoint.c | 9 ++++++
sound/usb/pcm.c | 87 +++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 8a751b4..2c05cb7 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -28,6 +28,7 @@ struct audioformat {
unsigned int *rate_table; /* rate table */
unsigned char clock; /* associated clock */
struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */
+ bool dsd_dop; /* add DOP headers in case of DSD samples */
};
struct snd_usb_substream;
@@ -138,6 +139,12 @@ struct snd_usb_substream {
int last_frame_number; /* stored frame number */
int last_delay; /* stored delay */
+
+ struct {
+ int marker;
+ int channel;
+ int byte_idx;
+ } dsd_dop;
};
struct snd_usb_stream {
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7e9c55a..32d0b41 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -578,6 +578,15 @@ static int data_ep_set_params(struct snd_usb_endpoint *ep,
int is_playback = usb_pipeout(ep->pipe);
int frame_bits = snd_pcm_format_physical_width(pcm_format) * channels;
+ if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
+ /*
+ * When operating in DSD DOP mode, the size of a sample frame
+ * in hardware differs from the actual physical format width
+ * because we need to make room for the DOP markers.
+ */
+ frame_bits += channels << 3;
+ }
+
ep->datainterval = fmt->datainterval;
ep->stride = frame_bits >> 3;
ep->silence_value = pcm_format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 6f85202..b5eae93 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1120,6 +1120,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
runtime->private_data = subs;
subs->pcm_substream = substream;
/* runtime PM is also done there */
+
+ /* initialize DSD/DOP context */
+ subs->dsd_dop.byte_idx = 0;
+ subs->dsd_dop.channel = 0;
+ subs->dsd_dop.marker = 1;
+
return setup_hw_info(runtime, subs);
}
@@ -1214,6 +1220,56 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
snd_pcm_period_elapsed(subs->pcm_substream);
}
+static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
+ struct urb *urb, unsigned int bytes)
+{
+ struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+ unsigned int stride = runtime->frame_bits >> 3;
+ unsigned int dst_idx = 0;
+ unsigned int src_idx = subs->hwptr_done;
+ unsigned int wrap = runtime->buffer_size * stride;
+ u8 *dst = urb->transfer_buffer;
+ u8 *src = runtime->dma_area;
+ u8 marker[] = { 0x05, 0xfa };
+
+ /*
+ * The DSP DOP format defines a way to transport DSD samples over
+ * normal PCM data endpoints. It requires stuffing of marker bytes
+ * (0x05 and 0xfa, alternating per sample frame), and then expects
+ * 2 additional bytes of actual payload. The whole frame is stored
+ * LSB.
+ *
+ * Hence, for a stereo transport, the buffer layout looks like this,
+ * where L refers to left channel samples and R to right.
+ *
+ * L1 L2 0x05 R1 R2 0x05 L3 L4 0xfa R3 R4 0xfa
+ * L5 L6 0x05 R5 R6 0x05 L7 L8 0xfa R7 R8 0xfa
+ * .....
+ *
+ */
+
+ while (bytes--) {
+ if (++subs->dsd_dop.byte_idx == 3) {
+ /* frame boundary? */
+ dst[dst_idx++] = marker[subs->dsd_dop.marker];
+ src_idx += 2;
+ subs->dsd_dop.byte_idx = 0;
+
+ if (++subs->dsd_dop.channel % runtime->channels == 0) {
+ /* alternate the marker */
+ subs->dsd_dop.marker++;
+ subs->dsd_dop.marker %= ARRAY_SIZE(marker);
+ subs->dsd_dop.channel = 0;
+ }
+ } else {
+ /* stuff the DSD payload */
+ int idx = (src_idx + subs->dsd_dop.byte_idx - 1) % wrap;
+ dst[dst_idx++] = src[idx];
+ subs->hwptr_done++;
+ }
+ }
+}
+
static void prepare_playback_urb(struct snd_usb_substream *subs,
struct urb *urb)
{
@@ -1270,19 +1326,28 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
break;
}
bytes = frames * ep->stride;
- if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
- /* err, the transferred area goes over buffer boundary. */
- unsigned int bytes1 =
- runtime->buffer_size * stride - subs->hwptr_done;
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes1);
- memcpy(urb->transfer_buffer + bytes1,
- runtime->dma_area, bytes - bytes1);
+
+ if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
+ subs->cur_audiofmt->dsd_dop)) {
+ fill_playback_urb_dsd_dop(subs, urb, bytes);
} else {
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes);
+ /* usual PCM */
+ if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+ /* err, the transferred area goes over buffer boundary. */
+ unsigned int bytes1 =
+ runtime->buffer_size * stride - subs->hwptr_done;
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes1);
+ memcpy(urb->transfer_buffer + bytes1,
+ runtime->dma_area, bytes - bytes1);
+ } else {
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes);
+ }
+
+ subs->hwptr_done += bytes;
}
- subs->hwptr_done += bytes;
+
if (subs->hwptr_done >= runtime->buffer_size * stride)
subs->hwptr_done -= runtime->buffer_size * stride;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 4/5] ALSA: snd-usb: add support for bit-reversed byte formats
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
` (2 preceding siblings ...)
2013-04-16 16:01 ` [PATCH v3 3/5] ALSA: snd-usb: add support for DSD DOP stream transport Daniel Mack
@ 2013-04-16 16:01 ` Daniel Mack
2013-04-16 16:01 ` [PATCH v3 5/5] ALSA: snd-usb: add quirks handler for DSD streams Daniel Mack
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
There is quite some confusion around the bit-ordering in DSD samples,
and no general agreement that defines whether hardware is supposed to
expect the oldest sample in the MSB or the LSB of a byte.
ALSA will hence set the rule that on the software API layer, bytes
always carry the oldest bit in the most significant bit of a byte, and
the driver has to translate that at runtime in order to match the
hardware layout.
This patch adds support for this by adding a boolean flag to the
audio format struct.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
sound/usb/card.h | 1 +
sound/usb/pcm.c | 19 ++++++++++++++++++-
2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 2c05cb7..fcae411 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -29,6 +29,7 @@ struct audioformat {
unsigned char clock; /* associated clock */
struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */
bool dsd_dop; /* add DOP headers in case of DSD samples */
+ bool dsd_bitrev; /* reverse the bits of each DSD sample */
};
struct snd_usb_substream;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b5eae93..c31980c 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -16,6 +16,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/bitrev.h>
#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
@@ -1264,7 +1265,12 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs,
} else {
/* stuff the DSD payload */
int idx = (src_idx + subs->dsd_dop.byte_idx - 1) % wrap;
- dst[dst_idx++] = src[idx];
+
+ if (subs->cur_audiofmt->dsd_bitrev)
+ dst[dst_idx++] = bitrev8(src[idx]);
+ else
+ dst[dst_idx++] = src[idx];
+
subs->hwptr_done++;
}
}
@@ -1330,6 +1336,17 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE &&
subs->cur_audiofmt->dsd_dop)) {
fill_playback_urb_dsd_dop(subs, urb, bytes);
+ } else if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U8 &&
+ subs->cur_audiofmt->dsd_bitrev)) {
+ /* bit-reverse the bytes */
+ u8 *buf = urb->transfer_buffer;
+ for (i = 0; i < bytes; i++) {
+ int idx = (subs->hwptr_done + i)
+ % (runtime->buffer_size * stride);
+ buf[i] = bitrev8(runtime->dma_area[idx]);
+ }
+
+ subs->hwptr_done += bytes;
} else {
/* usual PCM */
if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v3 5/5] ALSA: snd-usb: add quirks handler for DSD streams
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
` (3 preceding siblings ...)
2013-04-16 16:01 ` [PATCH v3 4/5] ALSA: snd-usb: add support for bit-reversed byte formats Daniel Mack
@ 2013-04-16 16:01 ` Daniel Mack
2013-04-16 16:13 ` [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Takashi Iwai
2013-04-17 10:59 ` Takashi Iwai
6 siblings, 0 replies; 13+ messages in thread
From: Daniel Mack @ 2013-04-16 16:01 UTC (permalink / raw)
To: alsa-devel; +Cc: tiwai, clemens, Daniel Mack, demian, ray, andreas
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.
That quirks handler can augment the already parsed formats bit-field,
by any of the new SNDRV_PCM_FMTBIT_DSD_{U8_U16} and setting the dsd_dop
flag in the audio format, if the driver should take care for the DOP
byte stuffing.
The only devices that are known to work with this are the ones with
a 'Playback Designs' vendor id.
Signed-off-by: Daniel Mack <zonque@gmail.com>
---
sound/usb/format.c | 3 +++
sound/usb/quirks.c | 28 ++++++++++++++++++++++++++++
sound/usb/quirks.h | 4 ++++
3 files changed, 35 insertions(+)
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 20c7751..020ede0 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -136,6 +136,9 @@ 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);
}
+
+ pcm_formats |= snd_usb_interface_dsd_format_quirks(chip, fp, sample_bytes);
+
return pcm_formats;
}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 2927981..4c6366c 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -915,3 +915,31 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
mdelay(20);
}
+/*
+ * 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)
+{
+ /* Playback Designs */
+ if (le16_to_cpu(chip->dev->descriptor.idVendor) == 0x23ba) {
+ 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;
+ }
+ }
+
+ return 0;
+}
diff --git a/sound/usb/quirks.h b/sound/usb/quirks.h
index 7c3681f..665e972 100644
--- a/sound/usb/quirks.h
+++ b/sound/usb/quirks.h
@@ -31,4 +31,8 @@ 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);
+u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
+ struct audioformat *fp,
+ unsigned int sample_bytes);
+
#endif /* __USBAUDIO_QUIRKS_H */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
` (4 preceding siblings ...)
2013-04-16 16:01 ` [PATCH v3 5/5] ALSA: snd-usb: add quirks handler for DSD streams Daniel Mack
@ 2013-04-16 16:13 ` Takashi Iwai
2013-04-17 10:59 ` Takashi Iwai
6 siblings, 0 replies; 13+ messages in thread
From: Takashi Iwai @ 2013-04-16 16:13 UTC (permalink / raw)
To: Daniel Mack; +Cc: ray, andreas, alsa-devel, clemens, demian
At Wed, 17 Apr 2013 00:01:35 +0800,
Daniel Mack wrote:
>
> In contrast to the first two approaches, this one keeps the userspace
> unaware of the actual transport on the bus.
>
> More specifically, the DSD_U16_LE format may be implemented to actually
> send DOP samples to the device, depending on the quirks entries.
>
> Also, as there is quite some confusion in both data file formats as
> well as hardware sample formats about whether to stuff the oldest bit
> in the MSB or the LSB of a byte, ALSA defines that now to be in the
> MSB, as far as the ALSA userspace layer is concerned. The driver
> learned functions to re-encode the bytes according to what the hardware
> supports.
>
> I also wrote a very basic test tool which I published here:
>
> https://github.com/zonque/alsa-dsd-player
Maybe it'd be good to merge it into alsa-lib/test directory or
alsa-utils (or alsa-tools).
Takashi
>
>
> Thanks,
> Daniel
>
> Daniel Mack (5):
> ALSA: add DSD formats
> ALSA: snd-usb: use ep->stride from urb callbacks
> ALSA: snd-usb: add support for DSD DOP stream transport
> ALSA: snd-usb: add support for bit-reversed byte formats
> ALSA: snd-usb: add quirks handler for DSD streams
>
> include/sound/pcm.h | 2 +
> include/uapi/sound/asound.h | 4 +-
> sound/core/pcm.c | 2 +
> sound/core/pcm_misc.c | 8 +++
> sound/usb/card.h | 8 +++
> sound/usb/endpoint.c | 9 ++++
> sound/usb/format.c | 3 ++
> sound/usb/pcm.c | 118 ++++++++++++++++++++++++++++++++++++-------
> sound/usb/quirks.c | 28 ++++++++++
> sound/usb/quirks.h | 4 ++
> 10 files changed, 167 insertions(+), 19 deletions(-)
>
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
` (5 preceding siblings ...)
2013-04-16 16:13 ` [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Takashi Iwai
@ 2013-04-17 10:59 ` Takashi Iwai
2013-04-17 11:03 ` Daniel Mack
6 siblings, 1 reply; 13+ messages in thread
From: Takashi Iwai @ 2013-04-17 10:59 UTC (permalink / raw)
To: Daniel Mack; +Cc: ray, andreas, alsa-devel, clemens, demian
At Wed, 17 Apr 2013 00:01:35 +0800,
Daniel Mack wrote:
>
> In contrast to the first two approaches, this one keeps the userspace
> unaware of the actual transport on the bus.
>
> More specifically, the DSD_U16_LE format may be implemented to actually
> send DOP samples to the device, depending on the quirks entries.
>
> Also, as there is quite some confusion in both data file formats as
> well as hardware sample formats about whether to stuff the oldest bit
> in the MSB or the LSB of a byte, ALSA defines that now to be in the
> MSB, as far as the ALSA userspace layer is concerned. The driver
> learned functions to re-encode the bytes according to what the hardware
> supports.
>
> I also wrote a very basic test tool which I published here:
>
> https://github.com/zonque/alsa-dsd-player
>
>
> Thanks,
> Daniel
>
> Daniel Mack (5):
> ALSA: add DSD formats
> ALSA: snd-usb: use ep->stride from urb callbacks
> ALSA: snd-usb: add support for DSD DOP stream transport
> ALSA: snd-usb: add support for bit-reversed byte formats
> ALSA: snd-usb: add quirks handler for DSD streams
All patches look OK to me through a quick glance, so I'm going to
apply them later, unless anyone has objection.
thanks,
Takashi
>
> include/sound/pcm.h | 2 +
> include/uapi/sound/asound.h | 4 +-
> sound/core/pcm.c | 2 +
> sound/core/pcm_misc.c | 8 +++
> sound/usb/card.h | 8 +++
> sound/usb/endpoint.c | 9 ++++
> sound/usb/format.c | 3 ++
> sound/usb/pcm.c | 118 ++++++++++++++++++++++++++++++++++++-------
> sound/usb/quirks.c | 28 ++++++++++
> sound/usb/quirks.h | 4 ++
> 10 files changed, 167 insertions(+), 19 deletions(-)
>
> --
> 1.7.10.4
>
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-17 10:59 ` Takashi Iwai
@ 2013-04-17 11:03 ` Daniel Mack
2013-04-17 17:01 ` Jussi Laako
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Mack @ 2013-04-17 11:03 UTC (permalink / raw)
To: Takashi Iwai; +Cc: alsa-devel, clemens, Jussi Laako, demian, ray, andreas
On 17.04.2013 12:59, Takashi Iwai wrote:
> At Wed, 17 Apr 2013 00:01:35 +0800,
> Daniel Mack wrote:
>>
>> In contrast to the first two approaches, this one keeps the userspace
>> unaware of the actual transport on the bus.
>>
>> More specifically, the DSD_U16_LE format may be implemented to actually
>> send DOP samples to the device, depending on the quirks entries.
>>
>> Also, as there is quite some confusion in both data file formats as
>> well as hardware sample formats about whether to stuff the oldest bit
>> in the MSB or the LSB of a byte, ALSA defines that now to be in the
>> MSB, as far as the ALSA userspace layer is concerned. The driver
>> learned functions to re-encode the bytes according to what the hardware
>> supports.
>>
>> I also wrote a very basic test tool which I published here:
>>
>> https://github.com/zonque/alsa-dsd-player
>>
>>
>> Thanks,
>> Daniel
>>
>> Daniel Mack (5):
>> ALSA: add DSD formats
>> ALSA: snd-usb: use ep->stride from urb callbacks
>> ALSA: snd-usb: add support for DSD DOP stream transport
>> ALSA: snd-usb: add support for bit-reversed byte formats
>> ALSA: snd-usb: add quirks handler for DSD streams
>
> All patches look OK to me through a quick glance, so I'm going to
> apply them later, unless anyone has objection.
I'd like to wait for another day or so for Jussi to state his oppinion.
He seems to be the only one on this list who has ever dealt with DSD on
Linux, so we should listen to him ;)
Thanks,
Daniel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-17 11:03 ` Daniel Mack
@ 2013-04-17 17:01 ` Jussi Laako
2013-04-17 17:04 ` Daniel Mack
0 siblings, 1 reply; 13+ messages in thread
From: Jussi Laako @ 2013-04-17 17:01 UTC (permalink / raw)
To: Daniel Mack; +Cc: alsa-devel, Takashi Iwai, clemens, demian, ray, andreas
On 04/17/2013 02:03 PM, Daniel Mack wrote:
> I'd like to wait for another day or so for Jussi to state his oppinion.
Looks good to me. Hopefully the necessary details about bit ordering
find their way to the ALSA API docs.
I was left thinking about how this:
> + if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
> + /*
> + * When operating in DSD DOP mode, the size of a sample frame
> + * in hardware differs from the actual physical format width
> + * because we need to make room for the DOP markers.
> + */
> + frame_bits += channels << 3;
> + }
relates to case where the endpoint uses 32-bit int sample format and
thus needs a zero pad byte for DoP...
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-17 17:01 ` Jussi Laako
@ 2013-04-17 17:04 ` Daniel Mack
2013-04-17 17:13 ` Jussi Laako
0 siblings, 1 reply; 13+ messages in thread
From: Daniel Mack @ 2013-04-17 17:04 UTC (permalink / raw)
To: Jussi Laako; +Cc: alsa-devel, Takashi Iwai, clemens, demian, ray, andreas
On 17.04.2013 19:01, Jussi Laako wrote:
> On 04/17/2013 02:03 PM, Daniel Mack wrote:
>> I'd like to wait for another day or so for Jussi to state his oppinion.
>
> Looks good to me. Hopefully the necessary details about bit ordering
> find their way to the ALSA API docs.
You volunteer for sending a patch? :)
>
> I was left thinking about how this:
>
>> + if (pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && fmt->dsd_dop) {
>> + /*
>> + * When operating in DSD DOP mode, the size of a sample frame
>> + * in hardware differs from the actual physical format width
>> + * because we need to make room for the DOP markers.
>> + */
>> + frame_bits += channels << 3;
>> + }
>
> relates to case where the endpoint uses 32-bit int sample format and
> thus needs a zero pad byte for DoP...
Ok, that's a case I haven't though of yet, but we can easily extend that
logic once such a device is used by anyone. For now, this entire logic
is only relevant for one series of devices, and for that, we know the
parameters exactly.
The important thing is that we don't have to break the userspace API,
but I think we're safe here, right?
Thanks,
Daniel
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-17 17:04 ` Daniel Mack
@ 2013-04-17 17:13 ` Jussi Laako
2013-04-18 8:05 ` Takashi Iwai
0 siblings, 1 reply; 13+ messages in thread
From: Jussi Laako @ 2013-04-17 17:13 UTC (permalink / raw)
To: Daniel Mack; +Cc: alsa-devel, Takashi Iwai, clemens, demian, ray, andreas
On 04/17/2013 08:04 PM, Daniel Mack wrote:
> You volunteer for sending a patch? :)
I have to admit I have no idea from where and how ALSA API docs are
generated.
> Ok, that's a case I haven't though of yet, but we can easily extend that
> logic once such a device is used by anyone. For now, this entire logic
> is only relevant for one series of devices, and for that, we know the
> parameters exactly.
Over 50% of devices I've seen use 32-bit sample formats for DoP,
including the one I regularly use with Linux. That's why I asked...
Currently most popular OEM blocks are XMOS and M2Tech hiFace which both
use 32-bit sample format.
> The important thing is that we don't have to break the userspace API,
> but I think we're safe here, right?
Yes, it looks good to me.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v3 0/5] ALSA: snd-usb: add support for DSD
2013-04-17 17:13 ` Jussi Laako
@ 2013-04-18 8:05 ` Takashi Iwai
0 siblings, 0 replies; 13+ messages in thread
From: Takashi Iwai @ 2013-04-18 8:05 UTC (permalink / raw)
To: Jussi Laako; +Cc: alsa-devel, clemens, Daniel Mack, demian, ray, andreas
At Wed, 17 Apr 2013 20:13:45 +0300,
Jussi Laako wrote:
>
> On 04/17/2013 08:04 PM, Daniel Mack wrote:
> > You volunteer for sending a patch? :)
>
> I have to admit I have no idea from where and how ALSA API docs are
> generated.
>
> > Ok, that's a case I haven't though of yet, but we can easily extend that
> > logic once such a device is used by anyone. For now, this entire logic
> > is only relevant for one series of devices, and for that, we know the
> > parameters exactly.
>
> Over 50% of devices I've seen use 32-bit sample formats for DoP,
> including the one I regularly use with Linux. That's why I asked...
>
> Currently most popular OEM blocks are XMOS and M2Tech hiFace which both
> use 32-bit sample format.
>
> > The important thing is that we don't have to break the userspace API,
> > but I think we're safe here, right?
>
> Yes, it looks good to me.
OK, then I merge the patches as is.
Let's continue refining the code on git for-next branch.
thanks,
Takashi
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2013-04-18 8:06 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-04-16 16:01 [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Daniel Mack
2013-04-16 16:01 ` [PATCH v3 1/5] ALSA: add DSD formats Daniel Mack
2013-04-16 16:01 ` [PATCH v3 2/5] ALSA: snd-usb: use ep->stride from urb callbacks Daniel Mack
2013-04-16 16:01 ` [PATCH v3 3/5] ALSA: snd-usb: add support for DSD DOP stream transport Daniel Mack
2013-04-16 16:01 ` [PATCH v3 4/5] ALSA: snd-usb: add support for bit-reversed byte formats Daniel Mack
2013-04-16 16:01 ` [PATCH v3 5/5] ALSA: snd-usb: add quirks handler for DSD streams Daniel Mack
2013-04-16 16:13 ` [PATCH v3 0/5] ALSA: snd-usb: add support for DSD Takashi Iwai
2013-04-17 10:59 ` Takashi Iwai
2013-04-17 11:03 ` Daniel Mack
2013-04-17 17:01 ` Jussi Laako
2013-04-17 17:04 ` Daniel Mack
2013-04-17 17:13 ` Jussi Laako
2013-04-18 8:05 ` Takashi Iwai
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.