summaryrefslogtreecommitdiff
path: root/sound/usb/endpoint.c
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2013-04-17 00:01:38 +0800
committerTakashi Iwai <tiwai@suse.de>2013-04-18 10:03:32 +0200
commitd24f5061ee7b9b58a7e97f3c2a72f0a9b115e7e0 (patch)
treef394f2599adac67b13c31dce99e83c3948f6d452 /sound/usb/endpoint.c
parent8a2a74d2b7667b2719858caf9eb2b5a92460195d (diff)
ALSA: snd-usb: add support for DSD DOP stream transport
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> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb/endpoint.c')
-rw-r--r--sound/usb/endpoint.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7e9c55a73540..32d0b41a1ff6 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;