ALSA: usb-audio: Allow changing from a bad sample rate
authorAdam Goode <agoode@google.com>
Wed, 18 Jul 2018 20:41:05 +0000 (16:41 -0400)
committerTakashi Iwai <tiwai@suse.de>
Thu, 19 Jul 2018 06:44:46 +0000 (08:44 +0200)
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>
sound/usb/clock.c

index c797496..db5e39d 100644 (file)
@@ -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;
 }