]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ALSA: usb-audio: Improve Focusrite sample rate filtering
authorGeoffrey D. Bennett <g@b4.vu>
Fri, 20 Feb 2026 16:03:45 +0000 (02:33 +1030)
committerTakashi Iwai <tiwai@suse.de>
Mon, 23 Feb 2026 08:57:09 +0000 (09:57 +0100)
Replace the bLength == 10 max_rate check in
focusrite_valid_sample_rate() with filtering that also examines the
bmControls VAL_ALT_SETTINGS bit.

When VAL_ALT_SETTINGS is readable, the device uses strict
per-altsetting rate filtering (only the highest rate pair for that
altsetting is valid). When it is not readable, all rates up to
max_rate are valid.

For devices without the bLength == 10 Format Type descriptor extension
but with VAL_ALT_SETTINGS readable and multiple altsettings (only seen
in Scarlett 18i8 3rd Gen playback), fall back to the Focusrite
convention: alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.

This produces correct rate tables for all tested Focusrite devices
(all Scarlett 2nd, 3rd, and 4th Gen, Clarett+, and Vocaster) using
only USB descriptors, allowing QUIRK_FLAG_VALIDATE_RATES to be removed
for Focusrite in the next commit.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/7e18c1f393a6ecb6fc75dd867a2c4dbe135e3e22.1771594828.git.g@b4.vu
sound/usb/format.c

index 64cfe4a9d8cdf267bf5bd2226ddcb0f2707777df..1207c507882add52322973d7922cd699049eaeaa 100644 (file)
@@ -305,17 +305,48 @@ static bool s1810c_valid_sample_rate(struct audioformat *fp,
 }
 
 /*
- * Many Focusrite devices supports a limited set of sampling rates per
- * altsetting. Maximum rate is exposed in the last 4 bytes of Format Type
- * descriptor which has a non-standard bLength = 10.
+ * Focusrite devices use rate pairs: 44100/48000, 88200/96000, and
+ * 176400/192000. Return true if rate is in the pair for max_rate.
+ */
+static bool focusrite_rate_pair(unsigned int rate,
+                               unsigned int max_rate)
+{
+       switch (max_rate) {
+       case 48000:  return rate == 44100 || rate == 48000;
+       case 96000:  return rate == 88200 || rate == 96000;
+       case 192000: return rate == 176400 || rate == 192000;
+       default:     return true;
+       }
+}
+
+/*
+ * Focusrite devices report all supported rates in a single clock
+ * source but only a subset is valid per altsetting.
+ *
+ * Detection uses two descriptor features:
+ *
+ * 1. Format Type descriptor bLength == 10: non-standard extension
+ *    with max sample rate in bytes 6..9.
+ *
+ * 2. bmControls VAL_ALT_SETTINGS readable bit: when set, the device
+ *    only supports the highest rate pair for that altsetting, and when
+ *    clear, all rates up to max_rate are valid.
+ *
+ * For devices without the bLength == 10 extension but with
+ * VAL_ALT_SETTINGS readable and multiple altsettings (only seen in
+ * Scarlett 18i8 3rd Gen playback), fall back to the Focusrite
+ * convention: alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
  */
 static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
                                        struct audioformat *fp,
                                        unsigned int rate)
 {
+       struct usb_interface *iface;
        struct usb_host_interface *alts;
+       struct uac2_as_header_descriptor *as;
        unsigned char *fmt;
        unsigned int max_rate;
+       bool val_alt;
 
        alts = snd_usb_get_host_interface(chip, fp->iface, fp->altsetting);
        if (!alts)
@@ -326,9 +357,21 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
        if (!fmt)
                return true;
 
+       as = snd_usb_find_csint_desc(alts->extra, alts->extralen,
+                                    NULL, UAC_AS_GENERAL);
+       if (!as)
+               return true;
+
+       val_alt = uac_v2v3_control_is_readable(as->bmControls,
+                                              UAC2_AS_VAL_ALT_SETTINGS);
+
        if (fmt[0] == 10) { /* bLength */
                max_rate = combine_quad(&fmt[6]);
 
+               if (val_alt)
+                       return focusrite_rate_pair(rate, max_rate);
+
+               /* No val_alt: rates fall through from higher */
                switch (max_rate) {
                case 192000:
                        if (rate == 176400 || rate == 192000)
@@ -344,12 +387,29 @@ static bool focusrite_valid_sample_rate(struct snd_usb_audio *chip,
                        usb_audio_info(chip,
                                "%u:%d : unexpected max rate: %u\n",
                                fp->iface, fp->altsetting, max_rate);
-
                        return true;
                }
        }
 
-       return true;
+       if (!val_alt)
+               return true;
+
+       /* Multi-altsetting device with val_alt but no max_rate
+        * in the format descriptor. Use Focusrite convention:
+        * alt 1 = 48kHz, alt 2 = 96kHz, alt 3 = 192kHz.
+        */
+       iface = usb_ifnum_to_if(chip->dev, fp->iface);
+       if (!iface || iface->num_altsetting <= 2)
+               return true;
+
+       switch (fp->altsetting) {
+       case 1:         max_rate = 48000; break;
+       case 2:         max_rate = 96000; break;
+       case 3:         max_rate = 192000; break;
+       default:        return true;
+       }
+
+       return focusrite_rate_pair(rate, max_rate);
 }
 
 /*