Commit 58cabe87 authored by Adam Goode's avatar Adam Goode Committed by Takashi Iwai

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: default avatarAdam Goode <agoode@google.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 67ece13f
...@@ -513,14 +513,28 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, ...@@ -513,14 +513,28 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
bool writeable; bool writeable;
u32 bmControls; 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, clock = snd_usb_clock_find_source(chip, fmt->protocol,
fmt->clock, true); fmt->clock, true);
if (clock < 0) if (clock < 0) {
return clock; /* 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); prev_rate = get_sample_rate_v2v3(chip, iface, fmt->altsetting, clock);
if (prev_rate == rate) if (prev_rate == rate)
return 0; goto validation;
if (fmt->protocol == UAC_VERSION_3) { if (fmt->protocol == UAC_VERSION_3) {
struct uac3_clock_source_descriptor *cs_desc; struct uac3_clock_source_descriptor *cs_desc;
...@@ -577,6 +591,10 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface, ...@@ -577,6 +591,10 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,
snd_usb_set_interface_quirk(dev); 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; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment