diff options
author | Daniel Mack <zonque@gmail.com> | 2013-04-16 12:01:39 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-04-18 04:03:47 -0400 |
commit | 44dcbbb1cd615634c09d1bf31c124332795903a8 (patch) | |
tree | ef2b5642e14bcbb8fe082e1e60c83975556ac1aa /sound/usb | |
parent | d24f5061ee7b9b58a7e97f3c2a72f0a9b115e7e0 (diff) |
ALSA: snd-usb: add support for bit-reversed byte formats
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>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r-- | sound/usb/card.h | 1 | ||||
-rw-r--r-- | sound/usb/pcm.c | 19 |
2 files changed, 19 insertions, 1 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h index ac55477ce6dd..bf2889a2cae5 100644 --- a/sound/usb/card.h +++ b/sound/usb/card.h | |||
@@ -29,6 +29,7 @@ struct audioformat { | |||
29 | unsigned char clock; /* associated clock */ | 29 | unsigned char clock; /* associated clock */ |
30 | struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */ | 30 | struct snd_pcm_chmap_elem *chmap; /* (optional) channel map */ |
31 | bool dsd_dop; /* add DOP headers in case of DSD samples */ | 31 | bool dsd_dop; /* add DOP headers in case of DSD samples */ |
32 | bool dsd_bitrev; /* reverse the bits of each DSD sample */ | ||
32 | }; | 33 | }; |
33 | 34 | ||
34 | struct snd_usb_substream; | 35 | struct snd_usb_substream; |
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c index 4cd917cf058e..9723f3ceb155 100644 --- a/sound/usb/pcm.c +++ b/sound/usb/pcm.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/bitrev.h> | ||
19 | #include <linux/ratelimit.h> | 20 | #include <linux/ratelimit.h> |
20 | #include <linux/usb.h> | 21 | #include <linux/usb.h> |
21 | #include <linux/usb/audio.h> | 22 | #include <linux/usb/audio.h> |
@@ -1264,7 +1265,12 @@ static inline void fill_playback_urb_dsd_dop(struct snd_usb_substream *subs, | |||
1264 | } else { | 1265 | } else { |
1265 | /* stuff the DSD payload */ | 1266 | /* stuff the DSD payload */ |
1266 | int idx = (src_idx + subs->dsd_dop.byte_idx - 1) % wrap; | 1267 | int idx = (src_idx + subs->dsd_dop.byte_idx - 1) % wrap; |
1267 | dst[dst_idx++] = src[idx]; | 1268 | |
1269 | if (subs->cur_audiofmt->dsd_bitrev) | ||
1270 | dst[dst_idx++] = bitrev8(src[idx]); | ||
1271 | else | ||
1272 | dst[dst_idx++] = src[idx]; | ||
1273 | |||
1268 | subs->hwptr_done++; | 1274 | subs->hwptr_done++; |
1269 | } | 1275 | } |
1270 | } | 1276 | } |
@@ -1330,6 +1336,17 @@ static void prepare_playback_urb(struct snd_usb_substream *subs, | |||
1330 | if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && | 1336 | if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U16_LE && |
1331 | subs->cur_audiofmt->dsd_dop)) { | 1337 | subs->cur_audiofmt->dsd_dop)) { |
1332 | fill_playback_urb_dsd_dop(subs, urb, bytes); | 1338 | fill_playback_urb_dsd_dop(subs, urb, bytes); |
1339 | } else if (unlikely(subs->pcm_format == SNDRV_PCM_FORMAT_DSD_U8 && | ||
1340 | subs->cur_audiofmt->dsd_bitrev)) { | ||
1341 | /* bit-reverse the bytes */ | ||
1342 | u8 *buf = urb->transfer_buffer; | ||
1343 | for (i = 0; i < bytes; i++) { | ||
1344 | int idx = (subs->hwptr_done + i) | ||
1345 | % (runtime->buffer_size * stride); | ||
1346 | buf[i] = bitrev8(runtime->dma_area[idx]); | ||
1347 | } | ||
1348 | |||
1349 | subs->hwptr_done += bytes; | ||
1333 | } else { | 1350 | } else { |
1334 | /* usual PCM */ | 1351 | /* usual PCM */ |
1335 | if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { | 1352 | if (subs->hwptr_done + bytes > runtime->buffer_size * stride) { |