public inbox for linux-sound@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects
@ 2026-02-20 16:03 Geoffrey D. Bennett
  2026-02-20 16:03 ` [PATCH 1/4] ALSA: usb-audio: Improve Focusrite sample rate filtering Geoffrey D. Bennett
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-20 16:03 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

Hi all,

This series fixes two problems caused by probe-time testing of
altsettings and sample rates on Focusrite devices. When a sample rate
of 192kHz is selected during the probe's trial and error, the internal
mixer and Air and Safe modes are disabled. I.e. no audio passes
through the mixer, and Air and Safe modes cannot be selected until an
application opens the PCM and sets a lower rate. This results in user
annoyance and bug reports of unexpected silence and mode changes.

I tested 20 Focusrite devices (Scarlett 2nd, 3rd, 4th Gen, Clarett+,
and Vocaster) and found that the valid sample rates can be determined
from USB descriptors alone, without the QUIRK_FLAG_VALIDATE_RATES
trial-and-error testing of each rate and altsetting. I also added a
quirk to skip the redundant interface setup and enabled the quirk to
skip the clock selector write-back (reading the current value then
writing it back unchanged triggers a ~300ms delay per altsetting).

The result of all this: the probe time drops from ~4 seconds to ~4ms,
there is no interruption to audio, and the mode settings do not
inadvertently get reset. The contents of /proc/asound/card*/stream0 is
identical before and after on all tested devices.

Background
----------

Focusrite interfaces with digital I/O use multiple altsettings for
different channel counts at different sample rates (more channels at
48kHz, fewer at 192kHz). The clock source reports all rates for every
altsetting, so rates need filtering.

Two mechanisms currently do this:

1. focusrite_valid_sample_rate() reads a non-standard Format Type
   descriptor (bLength=10, vs standard UAC2 bLength=6) with a max_rate
   in bytes 6-9.

2. validate_sample_rate_table_v2v3() (QUIRK_FLAG_VALIDATE_RATES) sets
   each rate on the device and queries UAC2_AS_VAL_ALT_SETTINGS to
   check validity. Prunes rates that fail.

Mechanism #1 currently uses fallthrough logic (commit cc8e91054c0a):
an altsetting with max_rate=192000 accepts all rates down to 44100.
This is correct for Clarett+ but wrong for Scarlett 3rd/4th Gen, where
only the matching rate pair should be accepted. Mechanism #2 gets the
right answer but has the USB side effects above.

Commit 05f254a6369a had strict 1:1 mapping, correct for Scarlett but
wrong for Clarett+. Neither approach alone works for all devices.

The UAC2_AS_VAL_ALT_SETTINGS readable bit in the AS header bmControls
predicts which behaviour the device needs:

- val_alt readable: strict — each altsetting only accepts its own rate
  pair
- val_alt not readable: fallthrough — all rates up to max_rate

Device test matrix:

  Device                   Playback          Capture           val_alt
  -------------------------------------------------------------------
  Scarlett 6i6 2nd Gen     1 alt, bLen=6     1 alt, bLen=6     no
  Scarlett 18i8 2nd Gen    1 alt, bLen=6     3 alts, bLen=10   no
  Scarlett 18i20 2nd Gen   3 alts, bLen=10   3 alts, bLen=10   no
  Scarlett Solo 3rd Gen    1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 2i2 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 4i4 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 8i6 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 18i8 3rd Gen    3 alts, bLen=6    3 alts, bLen=10   yes
  Scarlett 18i20 3rd Gen   3 alts, bLen=10   3 alts, bLen=10   yes
  Scarlett Solo 4th Gen    1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 2i2 4th Gen     1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 4i4 4th Gen     1 alt, bLen=6     1 alt, bLen=6     yes
  Scarlett 16i16 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
  Scarlett 18i16 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
  Scarlett 18i20 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
  Clarett+ 2Pre            1 alt, bLen=6     3 alts, bLen=10   mixed*
  Clarett+ 4Pre            3 alts, bLen=6    3 alts, bLen=10   no
  Clarett+ 8Pre            3 alts, bLen=10   3 alts, bLen=10   no
  Vocaster One             1 alt, bLen=6     1 alt, bLen=6     yes
  Vocaster Two             1 alt, bLen=6     1 alt, bLen=6     yes

  * Clarett+ 2Pre: playback val_alt=no (single alt),
    capture val_alt=yes

  bLen=10: non-standard Focusrite Format Type descriptor with max_rate
  in bytes 6-9 (LE u32). Standard UAC2 is bLen=6. Single-altsetting
  devices need no rate filtering. Vocaster only supports 48kHz.

For val_alt=yes multi-alt devices, the old VALIDATE_RATES probing
agreed with the new strict filtering. For val_alt=no (2nd Gen,
Clarett+), the device accepts all rates up to max_rate on any
altsetting. I confirmed this on the Scarlett 18i20 2nd Gen and
Clarett+ 8Pre with speaker-test running 10 channels at 48kHz on the
up-to-192kHz altsetting.

Patches
-------

1/4: Improve focusrite_valid_sample_rate() to check bmControls for
UAC2_AS_VAL_ALT_SETTINGS:
  - val_alt readable + bLength=10: strict mapping
  - val_alt not readable + bLength=10: fallthrough (unchanged)
  - val_alt readable + bLength!=10 + multi-alt: use the Focusrite
    altsetting convention (alt 1=48k, 2=96k, 3=192k)
  - otherwise: no filtering

The third case handles the Scarlett 18i8 3rd Gen, which has bLength=6
on playback (no max_rate) but 3 altsettings with val_alt=yes,
requiring strict mapping.

2/4: Remove QUIRK_FLAG_VALIDATE_RATES for Focusrite. With patch 1,
descriptor-based filtering gets the right rates without USB probing.

3/4: Add QUIRK_FLAG_SKIP_IFACE_SETUP. Skips the probe-time interface
setup (usb_set_interface, init_pitch, init_sample_rate) in
__snd_usb_parse_audio_interface() which is redundant with
snd_usb_endpoint_prepare() at stream-open time. Enabled this quirk for
Focusrite devices. This is similar to commit ac5e2fb4 ("ALSA:
usb-audio: Drop superfluous interface setup at parsing") but gated as
a quirk. It's a worthwhile optimisation and is the second half of
fixing the problem with the sample rate being changed.

4/4: Enable QUIRK_FLAG_SKIP_CLOCK_SELECTOR for Focusrite devices.
snd_usb_clock_find_source() reads the clock selector value then writes
it back unchanged. On Focusrite devices this triggers an unnecessary
~300ms delay per altsetting.

Tested on all devices listed above: /proc/asound/card*/stream0
identical before and after.

Regards,
Geoffrey

Geoffrey D. Bennett (4):
  ALSA: usb-audio: Improve Focusrite sample rate filtering
  ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices
  ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP
  ALSA: usb-audio: Skip clock selector for Focusrite devices

 sound/usb/format.c   | 70 ++++++++++++++++++++++++++++++++++++++++----
 sound/usb/quirks.c   |  4 ++-
 sound/usb/stream.c   |  3 ++
 sound/usb/usbaudio.h |  6 ++++
 4 files changed, 77 insertions(+), 6 deletions(-)

-- 
2.53.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] ALSA: usb-audio: Improve Focusrite sample rate filtering
  2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
@ 2026-02-20 16:03 ` Geoffrey D. Bennett
  2026-02-20 16:04 ` [PATCH 2/4] ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices Geoffrey D. Bennett
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-20 16:03 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

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>
---
 sound/usb/format.c | 70 ++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 65 insertions(+), 5 deletions(-)

diff --git a/sound/usb/format.c b/sound/usb/format.c
index 64cfe4a9d8cd..1207c507882a 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -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);
 }
 
 /*
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices
  2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
  2026-02-20 16:03 ` [PATCH 1/4] ALSA: usb-audio: Improve Focusrite sample rate filtering Geoffrey D. Bennett
@ 2026-02-20 16:04 ` Geoffrey D. Bennett
  2026-02-20 16:06 ` [PATCH 3/4] ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP Geoffrey D. Bennett
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-20 16:04 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

Remove QUIRK_FLAG_VALIDATE_RATES for Focusrite. With the previous
commit, focusrite_valid_sample_rate() produces correct rate tables
without USB probing.

QUIRK_FLAG_VALIDATE_RATES sends SET_CUR requests for each rate (~25ms
each) and leaves the device at 192kHz. This is a problem because that
rate: 1) disables the internal mixer, so outputs are silent until an
application opens the PCM and sets a lower rate, and 2) the Air and
Safe modes get disabled.

Fixes: 5963e5262180 ("ALSA: usb-audio: Enable rate validation for Scarlett devices")
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/quirks.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 17e49617218b..3e6ade7ded92 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2424,7 +2424,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
 	VENDOR_FLG(0x07fd, /* MOTU */
 		   QUIRK_FLAG_VALIDATE_RATES),
 	VENDOR_FLG(0x1235, /* Focusrite Novation */
-		   QUIRK_FLAG_VALIDATE_RATES),
+		   0),
 	VENDOR_FLG(0x1511, /* AURALiC */
 		   QUIRK_FLAG_DSD_RAW),
 	VENDOR_FLG(0x152a, /* Thesycon devices */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP
  2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
  2026-02-20 16:03 ` [PATCH 1/4] ALSA: usb-audio: Improve Focusrite sample rate filtering Geoffrey D. Bennett
  2026-02-20 16:04 ` [PATCH 2/4] ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices Geoffrey D. Bennett
@ 2026-02-20 16:06 ` Geoffrey D. Bennett
  2026-02-20 16:06 ` [PATCH 4/4] ALSA: usb-audio: Skip clock selector for Focusrite devices Geoffrey D. Bennett
  2026-02-23  8:58 ` [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Takashi Iwai
  4 siblings, 0 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-20 16:06 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

Add a quirk flag to skip the usb_set_interface(),
snd_usb_init_pitch(), and snd_usb_init_sample_rate() calls in
__snd_usb_parse_audio_interface(). These are redundant with
snd_usb_endpoint_prepare() at stream-open time.

Enable the quirk for Focusrite devices, as init_sample_rate(rate_max)
sets 192kHz during probing, which disables the internal mixer and Air
and Safe modes.

Fixes: 16f1f838442d ("Revert "ALSA: usb-audio: Drop superfluous interface setup at parsing"")
Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/quirks.c   | 3 ++-
 sound/usb/stream.c   | 3 +++
 sound/usb/usbaudio.h | 6 ++++++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 3e6ade7ded92..5c977ba3c944 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2424,7 +2424,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
 	VENDOR_FLG(0x07fd, /* MOTU */
 		   QUIRK_FLAG_VALIDATE_RATES),
 	VENDOR_FLG(0x1235, /* Focusrite Novation */
-		   0),
+		   QUIRK_FLAG_SKIP_IFACE_SETUP),
 	VENDOR_FLG(0x1511, /* AURALiC */
 		   QUIRK_FLAG_DSD_RAW),
 	VENDOR_FLG(0x152a, /* Thesycon devices */
@@ -2506,6 +2506,7 @@ static const char *const snd_usb_audio_quirk_flag_names[] = {
 	QUIRK_STRING_ENTRY(MIC_RES_384),
 	QUIRK_STRING_ENTRY(MIXER_PLAYBACK_MIN_MUTE),
 	QUIRK_STRING_ENTRY(MIXER_CAPTURE_MIN_MUTE),
+	QUIRK_STRING_ENTRY(SKIP_IFACE_SETUP),
 	NULL
 };
 
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
index ec7d756d78d1..421e94b233e1 100644
--- a/sound/usb/stream.c
+++ b/sound/usb/stream.c
@@ -1259,6 +1259,9 @@ static int __snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
 			set_iface_first = true;
 
 		/* try to set the interface... */
+		if (chip->quirk_flags & QUIRK_FLAG_SKIP_IFACE_SETUP)
+			continue;
+
 		usb_set_interface(chip->dev, iface_no, 0);
 		if (set_iface_first)
 			usb_set_interface(chip->dev, iface_no, altno);
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 79978cae9799..085530cf62d9 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -224,6 +224,10 @@ extern bool snd_usb_skip_validation;
  *  playback value represents muted state instead of minimum audible volume
  * QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE
  *  Similar to QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE, but for capture streams
+ * QUIRK_FLAG_SKIP_IFACE_SETUP
+ *  Skip the probe-time interface setup (usb_set_interface,
+ *  init_pitch, init_sample_rate); redundant with
+ *  snd_usb_endpoint_prepare() at stream-open time
  */
 
 enum {
@@ -253,6 +257,7 @@ enum {
 	QUIRK_TYPE_MIC_RES_384			= 23,
 	QUIRK_TYPE_MIXER_PLAYBACK_MIN_MUTE	= 24,
 	QUIRK_TYPE_MIXER_CAPTURE_MIN_MUTE	= 25,
+	QUIRK_TYPE_SKIP_IFACE_SETUP		= 26,
 /* Please also edit snd_usb_audio_quirk_flag_names */
 };
 
@@ -284,5 +289,6 @@ enum {
 #define QUIRK_FLAG_MIC_RES_384			QUIRK_FLAG(MIC_RES_384)
 #define QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE	QUIRK_FLAG(MIXER_PLAYBACK_MIN_MUTE)
 #define QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE	QUIRK_FLAG(MIXER_CAPTURE_MIN_MUTE)
+#define QUIRK_FLAG_SKIP_IFACE_SETUP		QUIRK_FLAG(SKIP_IFACE_SETUP)
 
 #endif /* __USBAUDIO_H */
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] ALSA: usb-audio: Skip clock selector for Focusrite devices
  2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
                   ` (2 preceding siblings ...)
  2026-02-20 16:06 ` [PATCH 3/4] ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP Geoffrey D. Bennett
@ 2026-02-20 16:06 ` Geoffrey D. Bennett
  2026-02-23  8:58 ` [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Takashi Iwai
  4 siblings, 0 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-20 16:06 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

Add QUIRK_FLAG_SKIP_CLOCK_SELECTOR for Focusrite devices.

During interface parsing, snd_usb_clock_find_source() reads the clock
selector value then writes it back unchanged. On Focusrite devices
this redundant write results in a ~300ms delay per altsetting, adding
~1.8s to probe time on a typical device with 6 altsettings.

Enabling SKIP_CLOCK_SELECTOR skips the redundant write-back.

Signed-off-by: Geoffrey D. Bennett <g@b4.vu>
---
 sound/usb/quirks.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 5c977ba3c944..ffc08ee869ae 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2424,6 +2424,7 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
 	VENDOR_FLG(0x07fd, /* MOTU */
 		   QUIRK_FLAG_VALIDATE_RATES),
 	VENDOR_FLG(0x1235, /* Focusrite Novation */
+		   QUIRK_FLAG_SKIP_CLOCK_SELECTOR |
 		   QUIRK_FLAG_SKIP_IFACE_SETUP),
 	VENDOR_FLG(0x1511, /* AURALiC */
 		   QUIRK_FLAG_DSD_RAW),
-- 
2.53.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects
  2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
                   ` (3 preceding siblings ...)
  2026-02-20 16:06 ` [PATCH 4/4] ALSA: usb-audio: Skip clock selector for Focusrite devices Geoffrey D. Bennett
@ 2026-02-23  8:58 ` Takashi Iwai
  2026-02-23 23:58   ` Geoffrey D. Bennett
  4 siblings, 1 reply; 7+ messages in thread
From: Takashi Iwai @ 2026-02-23  8:58 UTC (permalink / raw)
  To: Geoffrey D. Bennett
  Cc: Takashi Iwai, Takashi Iwai, linux-sound, Alexander Tsoy,
	Tina Wuest

On Fri, 20 Feb 2026 17:03:11 +0100,
Geoffrey D. Bennett wrote:
> 
> Hi all,
> 
> This series fixes two problems caused by probe-time testing of
> altsettings and sample rates on Focusrite devices. When a sample rate
> of 192kHz is selected during the probe's trial and error, the internal
> mixer and Air and Safe modes are disabled. I.e. no audio passes
> through the mixer, and Air and Safe modes cannot be selected until an
> application opens the PCM and sets a lower rate. This results in user
> annoyance and bug reports of unexpected silence and mode changes.
> 
> I tested 20 Focusrite devices (Scarlett 2nd, 3rd, 4th Gen, Clarett+,
> and Vocaster) and found that the valid sample rates can be determined
> from USB descriptors alone, without the QUIRK_FLAG_VALIDATE_RATES
> trial-and-error testing of each rate and altsetting. I also added a
> quirk to skip the redundant interface setup and enabled the quirk to
> skip the clock selector write-back (reading the current value then
> writing it back unchanged triggers a ~300ms delay per altsetting).
> 
> The result of all this: the probe time drops from ~4 seconds to ~4ms,
> there is no interruption to audio, and the mode settings do not
> inadvertently get reset. The contents of /proc/asound/card*/stream0 is
> identical before and after on all tested devices.
> 
> Background
> ----------
> 
> Focusrite interfaces with digital I/O use multiple altsettings for
> different channel counts at different sample rates (more channels at
> 48kHz, fewer at 192kHz). The clock source reports all rates for every
> altsetting, so rates need filtering.
> 
> Two mechanisms currently do this:
> 
> 1. focusrite_valid_sample_rate() reads a non-standard Format Type
>    descriptor (bLength=10, vs standard UAC2 bLength=6) with a max_rate
>    in bytes 6-9.
> 
> 2. validate_sample_rate_table_v2v3() (QUIRK_FLAG_VALIDATE_RATES) sets
>    each rate on the device and queries UAC2_AS_VAL_ALT_SETTINGS to
>    check validity. Prunes rates that fail.
> 
> Mechanism #1 currently uses fallthrough logic (commit cc8e91054c0a):
> an altsetting with max_rate=192000 accepts all rates down to 44100.
> This is correct for Clarett+ but wrong for Scarlett 3rd/4th Gen, where
> only the matching rate pair should be accepted. Mechanism #2 gets the
> right answer but has the USB side effects above.
> 
> Commit 05f254a6369a had strict 1:1 mapping, correct for Scarlett but
> wrong for Clarett+. Neither approach alone works for all devices.
> 
> The UAC2_AS_VAL_ALT_SETTINGS readable bit in the AS header bmControls
> predicts which behaviour the device needs:
> 
> - val_alt readable: strict ― each altsetting only accepts its own rate
>   pair
> - val_alt not readable: fallthrough ― all rates up to max_rate
> 
> Device test matrix:
> 
>   Device                   Playback          Capture           val_alt
>   -------------------------------------------------------------------
>   Scarlett 6i6 2nd Gen     1 alt, bLen=6     1 alt, bLen=6     no
>   Scarlett 18i8 2nd Gen    1 alt, bLen=6     3 alts, bLen=10   no
>   Scarlett 18i20 2nd Gen   3 alts, bLen=10   3 alts, bLen=10   no
>   Scarlett Solo 3rd Gen    1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 2i2 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 4i4 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 8i6 3rd Gen     1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 18i8 3rd Gen    3 alts, bLen=6    3 alts, bLen=10   yes
>   Scarlett 18i20 3rd Gen   3 alts, bLen=10   3 alts, bLen=10   yes
>   Scarlett Solo 4th Gen    1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 2i2 4th Gen     1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 4i4 4th Gen     1 alt, bLen=6     1 alt, bLen=6     yes
>   Scarlett 16i16 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
>   Scarlett 18i16 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
>   Scarlett 18i20 4th Gen   3 alts, bLen=10   3 alts, bLen=10   yes
>   Clarett+ 2Pre            1 alt, bLen=6     3 alts, bLen=10   mixed*
>   Clarett+ 4Pre            3 alts, bLen=6    3 alts, bLen=10   no
>   Clarett+ 8Pre            3 alts, bLen=10   3 alts, bLen=10   no
>   Vocaster One             1 alt, bLen=6     1 alt, bLen=6     yes
>   Vocaster Two             1 alt, bLen=6     1 alt, bLen=6     yes
> 
>   * Clarett+ 2Pre: playback val_alt=no (single alt),
>     capture val_alt=yes
> 
>   bLen=10: non-standard Focusrite Format Type descriptor with max_rate
>   in bytes 6-9 (LE u32). Standard UAC2 is bLen=6. Single-altsetting
>   devices need no rate filtering. Vocaster only supports 48kHz.
> 
> For val_alt=yes multi-alt devices, the old VALIDATE_RATES probing
> agreed with the new strict filtering. For val_alt=no (2nd Gen,
> Clarett+), the device accepts all rates up to max_rate on any
> altsetting. I confirmed this on the Scarlett 18i20 2nd Gen and
> Clarett+ 8Pre with speaker-test running 10 channels at 48kHz on the
> up-to-192kHz altsetting.
> 
> Patches
> -------
> 
> 1/4: Improve focusrite_valid_sample_rate() to check bmControls for
> UAC2_AS_VAL_ALT_SETTINGS:
>   - val_alt readable + bLength=10: strict mapping
>   - val_alt not readable + bLength=10: fallthrough (unchanged)
>   - val_alt readable + bLength!=10 + multi-alt: use the Focusrite
>     altsetting convention (alt 1=48k, 2=96k, 3=192k)
>   - otherwise: no filtering
> 
> The third case handles the Scarlett 18i8 3rd Gen, which has bLength=6
> on playback (no max_rate) but 3 altsettings with val_alt=yes,
> requiring strict mapping.
> 
> 2/4: Remove QUIRK_FLAG_VALIDATE_RATES for Focusrite. With patch 1,
> descriptor-based filtering gets the right rates without USB probing.
> 
> 3/4: Add QUIRK_FLAG_SKIP_IFACE_SETUP. Skips the probe-time interface
> setup (usb_set_interface, init_pitch, init_sample_rate) in
> __snd_usb_parse_audio_interface() which is redundant with
> snd_usb_endpoint_prepare() at stream-open time. Enabled this quirk for
> Focusrite devices. This is similar to commit ac5e2fb4 ("ALSA:
> usb-audio: Drop superfluous interface setup at parsing") but gated as
> a quirk. It's a worthwhile optimisation and is the second half of
> fixing the problem with the sample rate being changed.
> 
> 4/4: Enable QUIRK_FLAG_SKIP_CLOCK_SELECTOR for Focusrite devices.
> snd_usb_clock_find_source() reads the clock selector value then writes
> it back unchanged. On Focusrite devices this triggers an unnecessary
> ~300ms delay per altsetting.
> 
> Tested on all devices listed above: /proc/asound/card*/stream0
> identical before and after.
> 
> Regards,
> Geoffrey
> 
> Geoffrey D. Bennett (4):
>   ALSA: usb-audio: Improve Focusrite sample rate filtering
>   ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices
>   ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP
>   ALSA: usb-audio: Skip clock selector for Focusrite devices

Although it's a bit risky to take, the result looks still worth for
7.0 inclusion, and the code changes look mostly only for Forcusrite
devices, so I decided to apply those to for-linus branch now.


thanks,

Takashi

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects
  2026-02-23  8:58 ` [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Takashi Iwai
@ 2026-02-23 23:58   ` Geoffrey D. Bennett
  0 siblings, 0 replies; 7+ messages in thread
From: Geoffrey D. Bennett @ 2026-02-23 23:58 UTC (permalink / raw)
  To: Takashi Iwai; +Cc: Takashi Iwai, linux-sound, Alexander Tsoy, Tina Wuest

On Mon, Feb 23, 2026 at 09:58:46AM +0100, Takashi Iwai wrote:
> On Fri, 20 Feb 2026 17:03:11 +0100,
> Geoffrey D. Bennett wrote:
[...]
> > Geoffrey D. Bennett (4):
> >   ALSA: usb-audio: Improve Focusrite sample rate filtering
> >   ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices
> >   ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP
> >   ALSA: usb-audio: Skip clock selector for Focusrite devices
> 
> Although it's a bit risky to take, the result looks still worth for
> 7.0 inclusion, and the code changes look mostly only for Forcusrite
> devices, so I decided to apply those to for-linus branch now.

Thanks Takashi.

I've packaged it up for easy building out-of-tree for anyone who wants
to help test it but isn't familiar with building kernels:
https://github.com/geoffreybennett/linux-fcp/releases/tag/v6.18-f15

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-02-23 23:58 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-20 16:03 [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Geoffrey D. Bennett
2026-02-20 16:03 ` [PATCH 1/4] ALSA: usb-audio: Improve Focusrite sample rate filtering Geoffrey D. Bennett
2026-02-20 16:04 ` [PATCH 2/4] ALSA: usb-audio: Remove VALIDATE_RATES quirk for Focusrite devices Geoffrey D. Bennett
2026-02-20 16:06 ` [PATCH 3/4] ALSA: usb-audio: Add QUIRK_FLAG_SKIP_IFACE_SETUP Geoffrey D. Bennett
2026-02-20 16:06 ` [PATCH 4/4] ALSA: usb-audio: Skip clock selector for Focusrite devices Geoffrey D. Bennett
2026-02-23  8:58 ` [PATCH 0/4] ALSA: usb-audio: Fix Focusrite probe-time side effects Takashi Iwai
2026-02-23 23:58   ` Geoffrey D. Bennett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox