aboutsummaryrefslogtreecommitdiff
path: root/sound/usb
diff options
context:
space:
mode:
authorAdam Goode2018-07-18 16:41:05 -0400
committerTakashi Iwai2018-07-19 08:44:46 +0200
commit58cabe8715f20b7fb33431bb1f2c5bd7a438b11b (patch)
treea9ac16e4b188aa52fa595d53a97e61f142947829 /sound/usb
parent67ece13ffe862f9d17a144c6cd3feef88a57db13 (diff)
ALSA: usb-audio: Allow changing from a bad sample rate
If the audio device is externally clocked and set to a rate that does not match the external clock, the clock will never be valid and we cannot set the rate successfully. To fix this, allow a rate change even if the clock is initially invalid, and validate again after the rate is changed. This fixes problems with MOTU UltraLite AVB hardware over USB. Signed-off-by: Adam Goode <agoode@google.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/usb')
-rw-r--r--sound/usb/clock.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index c79749613fa6..db5e39d67a90 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -513,14 +513,28 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
bool writeable;
u32 bmControls;
+ /* First, try to find a valid clock. This may trigger
+ * automatic clock selection if the current clock is not
+ * valid.
+ */
clock = snd_usb_clock_find_source(chip, fmt->protocol,
fmt->clock, true);
- if (clock < 0)
- return clock;
+ if (clock < 0) {
+ /* We did not find a valid clock, but that might be
+ * because the current sample rate does not match an
+ * external clock source. Try again without validation
+ * and we will do another validation after setting the
+ * rate.
+ */
+ clock = snd_usb_clock_find_source(chip, fmt->protocol,
+ fmt->clock, false);
+ if (clock < 0)
+ return clock;
+ }
prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock);
if (prev_rate == rate)
- return 0;
+ goto validation;
if (fmt->protocol == UAC_VERSION_3) {
struct uac3_clock_source_descriptor *cs_desc;
@@ -577,6 +591,10 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
snd_usb_set_interface_quirk(dev);
}
+validation:
+ /* validate clock after rate change */
+ if (!uac_clock_source_is_valid(chip, fmt->protocol, clock))
+ return -ENXIO;
return 0;
}