[PATCH 2/3] ALSA: usb-audio: Add QUIRK_FLAG_MIXER_SKIP_GET_CUR_VOL

From: Rong Zhang

Date: Tue May 26 2026 - 13:51:41 EST


Since commit 86aa1ea1f15c ("ALSA: usb-audio: Do not expose sticky
mixers"), the UAC mixer core utilizes volume SET_CUR and GET_CUR to
identify devices with sticky mixers. Unfortunately, even though most
devices with sticky GET_CUR also have corresponding sticky SET_CUR,
which I actually met more since the commit had been merged, there is
also a rare case that some devices may have volume mixers that responds
to SET_CUR properly but with its GET_CUR stubbed. This cause the sticky
check to consider the mixer to be sticky and unnecessarily disable it.

Add QUIRK_FLAG_MIXER_SKIP_GET_CUR_VOL to prevent sending GET_CUR to
mixers by returning -ENXIO early. The error effectively skips the sticky
check as it's only meaningful when the mixer has some sort of self-
awareness. Similar to QUIRK_FLAG_GET_SAMPLE_RATE, this should also help
if some unmet devices can't tolerate volume GET_CUR in other ways.

Signed-off-by: Rong Zhang <i@xxxxxxxx>
---
Documentation/sound/alsa-configuration.rst | 4 ++++
sound/usb/mixer.c | 5 +++++
sound/usb/quirks.c | 1 +
sound/usb/usbaudio.h | 6 ++++++
4 files changed, 16 insertions(+)

diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index 4b30cd63c5a5..bc3bc65c379a 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -2389,6 +2389,10 @@ quirk_flags
from snd_usb_handle_sync_urb. Instead fall through and enqueue a
packet_info containing only size-0 packets, so the OUT ring keeps
moving (emits silence). Needed by Behringer Flow 8 (1397:050c).
+ * bit 30: ``mixer_skip_get_cur_vol``
+ Skip reading current volume for mixers, as some devices return
+ constant values or errors but otherwise works fine, i.e., setting
+ volume takes desired effect.

This module supports multiple devices, autoprobe and hotplugging.

diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index d61bde654219..3b745aebb181 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -420,6 +420,11 @@ static int get_cur_ctl_value(struct usb_mixer_elem_info *cval,
static inline int get_cur_mix_raw(struct usb_mixer_elem_info *cval,
int channel, int *value)
{
+ struct snd_usb_audio *chip = cval->head.mixer->chip;
+
+ if (chip->quirk_flags & QUIRK_FLAG_MIXER_SKIP_GET_CUR_VOL)
+ return -ENXIO;
+
return get_ctl_value(cval, UAC_GET_CUR,
(cval->control << 8) | channel,
value);
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index e2c95be38aca..fbd44baace68 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2605,6 +2605,7 @@ static const char *const snd_usb_audio_quirk_flag_names[] = {
QUIRK_STRING_ENTRY(MIXER_PLAYBACK_LINEAR_VOL),
QUIRK_STRING_ENTRY(MIXER_CAPTURE_LINEAR_VOL),
QUIRK_STRING_ENTRY(IFB_SILENCE_ON_EMPTY),
+ QUIRK_STRING_ENTRY(MIXER_SKIP_GET_CUR_VOL),
NULL
};

diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 9afcad8f143a..f4e048788f0b 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -242,6 +242,10 @@ extern bool snd_usb_skip_validation;
* from snd_usb_handle_sync_urb. Instead fall through and enqueue a
* packet_info containing only size-0 packets, so the OUT ring keeps
* moving (emits silence). Needed by Behringer Flow 8 (1397:050c).
+ * QUIRK_FLAG_MIXER_SKIP_GET_CUR_VOL
+ * Skip reading current volume for mixers, as some devices return constant
+ * values or errors but otherwise works fine, i.e., setting volume takes
+ * desired effect.
*/

enum {
@@ -275,6 +279,7 @@ enum {
QUIRK_TYPE_MIXER_PLAYBACK_LINEAR_VOL = 27,
QUIRK_TYPE_MIXER_CAPTURE_LINEAR_VOL = 28,
QUIRK_TYPE_IFB_SILENCE_ON_EMPTY = 29,
+ QUIRK_TYPE_MIXER_SKIP_GET_CUR_VOL = 30,
/* Please also edit snd_usb_audio_quirk_flag_names */
};

@@ -310,5 +315,6 @@ enum {
#define QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL QUIRK_FLAG(MIXER_PLAYBACK_LINEAR_VOL)
#define QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL QUIRK_FLAG(MIXER_CAPTURE_LINEAR_VOL)
#define QUIRK_FLAG_IFB_SILENCE_ON_EMPTY QUIRK_FLAG(IFB_SILENCE_ON_EMPTY)
+#define QUIRK_FLAG_MIXER_SKIP_GET_CUR_VOL QUIRK_FLAG(MIXER_SKIP_GET_CUR_VOL)

#endif /* __USBAUDIO_H */

--
2.53.0