summaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorHector Martin <marcan@marcan.st>2020-08-10 17:24:00 +0900
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2020-08-19 08:15:04 +0200
commit820ec1efe430395f6a699fa920c516bf0a70aa1c (patch)
treeab605013baf06de5edccd4a05811fd01701b6b10 /sound
parent7f496a7224b1a70a07ed7ed0d5b329980730816e (diff)
downloadlinux-stable-820ec1efe430395f6a699fa920c516bf0a70aa1c.tar.gz
linux-stable-820ec1efe430395f6a699fa920c516bf0a70aa1c.tar.bz2
linux-stable-820ec1efe430395f6a699fa920c516bf0a70aa1c.zip
ALSA: usb-audio: work around streaming quirk for MacroSilicon MS2109
commit 1b7ecc241a67ad6b584e071bd791a54e0cd5f097 upstream. Further investigation of the L-R swap problem on the MS2109 reveals that the problem isn't that the channels are swapped, but rather that they are swapped and also out of phase by one sample. In other words, the issue is actually that the very first frame that comes from the hardware is a half-frame containing only the right channel, and after that everything becomes offset. So introduce a new quirk field to drop the very first 2 bytes that come in after the format is configured and a capture stream starts. This puts the channels in phase and in the correct order. Cc: stable@vger.kernel.org Signed-off-by: Hector Martin <marcan@marcan.st> Link: https://lore.kernel.org/r/20200810082400.225858-1-marcan@marcan.st Signed-off-by: Takashi Iwai <tiwai@suse.de> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'sound')
-rw-r--r--sound/usb/card.h1
-rw-r--r--sound/usb/pcm.c6
-rw-r--r--sound/usb/quirks.c3
-rw-r--r--sound/usb/stream.c1
4 files changed, 11 insertions, 0 deletions
diff --git a/sound/usb/card.h b/sound/usb/card.h
index 7f11655bde50..f30fec68e2ca 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -129,6 +129,7 @@ struct snd_usb_substream {
unsigned int tx_length_quirk:1; /* add length specifier to transfers */
unsigned int fmt_type; /* USB audio format type (1-3) */
unsigned int pkt_offset_adj; /* Bytes to drop from beginning of packets (for non-compliant devices) */
+ unsigned int stream_offset_adj; /* Bytes to drop from beginning of stream (for non-compliant devices) */
unsigned int running: 1; /* running status */
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index 8b91be394407..7743e7bc6bf2 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -1387,6 +1387,12 @@ static void retire_capture_urb(struct snd_usb_substream *subs,
// continue;
}
bytes = urb->iso_frame_desc[i].actual_length;
+ if (subs->stream_offset_adj > 0) {
+ unsigned int adj = min(subs->stream_offset_adj, bytes);
+ cp += adj;
+ bytes -= adj;
+ subs->stream_offset_adj -= adj;
+ }
frames = bytes / stride;
if (!subs->txfr_quirk)
bytes = frames * stride;
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e9ec6166acc6..8d9117312e30 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1166,6 +1166,9 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
case USB_ID(0x041e, 0x3f19): /* E-Mu 0204 USB */
set_format_emu_quirk(subs, fmt);
break;
+ case USB_ID(0x534d, 0x2109): /* MacroSilicon MS2109 */
+ subs->stream_offset_adj = 2;
+ break;
}
}
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index 9d020bd0de17..ff5d803cfaf0 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -99,6 +99,7 @@ static void snd_usb_init_substream(struct snd_usb_stream *as,
subs->tx_length_quirk = as->chip->tx_length_quirk;
subs->speed = snd_usb_get_speed(subs->dev);
subs->pkt_offset_adj = 0;
+ subs->stream_offset_adj = 0;
snd_usb_set_pcm_ops(as->pcm, stream);