* [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR
@ 2026-08-22 18:52 Rong Zhang
2026-08-22 18:52 ` [PATCH 1/4] ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE Rong Zhang
` (4 more replies)
0 siblings, 5 replies; 6+ messages in thread
From: Rong Zhang @ 2026-08-22 18:52 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Cc: Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer, Rong Zhang
Currently, a mixer is disabled when its GET_CUR is sticky, causing
userspace to fall back to soft mixers, unless
QUIRK_FLAG_MIXER_GET_CUR_BROKEN is set. This leads to issues on some
wireless headphones with broken GET_CUR but effective SET_CUR, which use
poorly-performed lossy codecs and are prone to audible distortion at low
volume. They have to set the quirk flag to reeanble the mixer.
Considering that users can always opt into soft mixers if they need it,
i.e., when SET_CUR is stubbed, demote the severity of sticky GET_CUR by
marking GET_CUR as broken and only provide mixer values from the cache.
The mixer itself is still registered.
The default behavior of sticky check now becomes what
QUIRK_FLAG_MIXER_GET_CUR_BROKEN originally does, so the quirk flag is no
longer needed.
On some devices, whether their GET_CUR being sticky depends on whether
hotpluggable components are present. When the hotpluggable components
are missing on probe, their GET_CUR behavior is classified as broken.
Therefore, reverse QUIRK_FLAG_MIXER_GET_CUR_BROKEN as
QUIRK_FLAG_MIXER_GET_CUR_OK, so that it can be set to prevent the
heuristics from gating GET_CUR.
Note that even if the quirk flag is set, init_cur_mix_raw() should still
initialize the mixer value to cval->min, otherwise restoring the bogus
saved value on the first channel could lead to unbalanced channels.
The first user of QUIRK_FLAG_MIXER_GET_CUR_OK is Logitech PRO X
Wireless, whose Playback mixer's GET_CUR somehow becomes broken when the
microphone is detached, so set QUIRK_FLAG_MIXER_GET_CUR_OK to prevent
the mixer behavior from depending on whether the microphone is attached.
The device also needs QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE as the minimum
mixer value doesn't work properly.
Reported-by: Alexander Niemeyer <adventureFAN@gmx.de>
Closes: https://msgid.link/6262cbbd-d1f2-4c9d-a1c7-9c5d12636f4b@gmx.de
Closes: https://msgid.link/7984832b-86f6-4934-bfc0-1ed70218973a@gmx.de
Signed-off-by: Rong Zhang <i@rong.moe>
---
Rong Zhang (4):
ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE
ALSA: usb-audio: Demote the severity of sticky GET_CUR
ALSA: usb-audio: Reverse MIXER_GET_CUR_BROKEN as MIXER_GET_CUR_OK
ALSA: usb-audio: Add quirk flags for Logitech PRO X Wireless
Documentation/sound/alsa-configuration.rst | 25 ++++-----
sound/usb/mixer.c | 82 ++++++++++--------------------
sound/usb/quirks.c | 19 +++----
sound/usb/usbaudio.h | 24 ++++-----
4 files changed, 56 insertions(+), 94 deletions(-)
---
base-commit: 26260251022fbc2f248a3d747a9b2b961b18d2d8
change-id: bfb273cc-uac-demote-sticky-check-f92d4aaca7e6
Thanks,
Rong
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH 1/4] ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
@ 2026-08-22 18:52 ` Rong Zhang
2026-08-22 18:52 ` [PATCH 2/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Rong Zhang @ 2026-08-22 18:52 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Cc: Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer, Rong Zhang
QUIRK_FLAG_ALWAYS_SET_RATE was introduced into usb-audio before without
appropriate documentation, so add it.
There is an odd colon in its comments, so remove it too.
As this is often forgotten, also add a reminder to the end of the
enumeration.
Fixes: 786f91da8535 ("ALSA: usb-audio: add QUIRK_FLAG_ALWAYS_SET_RATE for Mackie DLZ Creator XS")
Signed-off-by: Rong Zhang <i@rong.moe>
---
Documentation/sound/alsa-configuration.rst | 5 +++++
sound/usb/usbaudio.h | 4 ++--
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index b2171472e6cb..71733e807a7c 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -2406,6 +2406,11 @@ quirk_flags
works around it by enforcing the fixed max URBs (12) instead of
the dynamic calculation from the buffer size, and passing the
`URB_ISO_ASAP` URB flag.
+ * bit 32: ``always_set_rate``
+ Issue SET_CUR for the sample rate even when the clock already reports
+ the requested rate. A device advertising a single rate is otherwise
+ never sent the request at all, and some require it before streaming
+ will start.
This module supports multiple devices, autoprobe and hotplugging.
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index c49709d7ad25..abc2d7e579de 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -260,7 +260,7 @@ extern bool snd_usb_skip_validation;
* to insufficient buffer depth combined with xHCI scheduling variability.
* The larger buffer (MAX_URBS = 12, ~64ms) absorbs system scheduling
* jitter during boot, while URB_ISO_ASAP ensures consistent xHCI scheduling.
- * QUIRK_FLAG_ALWAYS_SET_RATE:
+ * QUIRK_FLAG_ALWAYS_SET_RATE
* Issue SET_CUR for the sample rate even when the clock already reports the
* requested rate. A device advertising a single rate is otherwise never sent
* the request at all, and some require it before streaming will start.
@@ -300,7 +300,7 @@ enum {
QUIRK_TYPE_MIXER_GET_CUR_BROKEN = 30,
QUIRK_TYPE_PLAYBACK_URB_FIXUP = 31,
QUIRK_TYPE_ALWAYS_SET_RATE = 32,
-/* Please also edit snd_usb_audio_quirk_flag_names */
+/* Please also edit snd_usb_audio_quirk_flag_names and alsa-configuration.rst */
};
#define QUIRK_FLAG(x) BIT_U64(QUIRK_TYPE_ ## x)
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 2/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
2026-08-22 18:52 ` [PATCH 1/4] ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE Rong Zhang
@ 2026-08-22 18:52 ` Rong Zhang
2026-08-22 18:52 ` [PATCH 3/4] ALSA: usb-audio: Reverse MIXER_GET_CUR_BROKEN as MIXER_GET_CUR_OK Rong Zhang
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Rong Zhang @ 2026-08-22 18:52 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Cc: Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer, Rong Zhang
Currently, a mixer is disabled when its GET_CUR is sticky, causing
userspace to fall back to soft mixers, unless
QUIRK_FLAG_MIXER_GET_CUR_BROKEN is set. This leads to issues on some
wireless headphones with broken GET_CUR but effective SET_CUR, which use
poorly-performed lossy codecs and are prone to audible distortion at low
volume. They have to set the quirk flag to reeanble the mixer.
Considering that users can always opt into soft mixers if they need it,
i.e., when SET_CUR is stubbed, demote the severity of sticky GET_CUR by
marking GET_CUR as broken and only provide mixer values from the cache.
The mixer itself is still registered.
Signed-off-by: Rong Zhang <i@rong.moe>
---
sound/usb/mixer.c | 76 +++++++++++++++----------------------------------------
1 file changed, 21 insertions(+), 55 deletions(-)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 5de182181ede..3aa9a9c12557 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1237,21 +1237,27 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
}
/*
- * Additional checks for sticky mixers
+ * Additional checks for sticky GET_CUR
*
- * Some devices' volume control mixers are sticky, which accept SET_CUR but
- * do absolutely nothing.
+ * Some devices' volume control mixers have sticky GET_CUR, which implies either
+ * stubbed SET_CUR or broken GET_CUR. For the former case, the mixer accepts
+ * SET_CUR but do absolutely nothing, so falling back to soft mixer is the only
+ * way to control the volume. For the latter case, the mixer has effective
+ * SET_CUR despite GET_CUR being constant, and the mixer is usable as long as we
+ * always provide mixer value from the ceche.
*
* Check the return values of GET_CUR with different SET_CUR values. Consider
- * the mixer as sticky if GET_CUR always returns a constant value.
+ * GET_CUR as sticky if GET_CUR always returns a constant value.
*
- * Some devices have effective SET_CUR despite GET_CUR being constant. Do not
- * consider the mixer as sticky if a quirk flag indicates that.
+ * Unfortunately, we can't distinguish between stubbed SET_CUR and broken
+ * GET_CUR with simple read-back tests. Disabling the mixer regardless and
+ * forcing userspace to use soft mixer instead can lead to audible distortion at
+ * low volume on some wireless headphones, probably due to their poorly-
+ * performed lossy codec.
*
- * Gate the registration of sticky mixers to prevent confusing userspace, so
- * that they won't cause ineffective volume control. However, for mixers with
- * effective SET_CUR but broken GET_CUR, the registration can continue normally
- * but further GET_CUR requests will be gated.
+ * Instead, mark GET_CUR as broken regardless and only provide mixer value from
+ * the cache. Users may opt into soft mixer in userspace audio stack if they
+ * need it.
*/
static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
int channel, int saved)
@@ -1271,24 +1277,13 @@ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
return 0;
}
- if (cval->head.mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_GET_CUR_BROKEN) {
- usb_audio_info(cval->head.mixer->chip,
- "%d:%d: broken mixer GET_CUR (%d/%d/%d => %d)\n",
- cval->head.id, mixer_ctrl_intf(cval->head.mixer),
- cval->min, cval->max, cval->res, saved);
-
- cval->get_cur_broken = 1;
- return -ENXIO;
- }
-
- usb_audio_err(cval->head.mixer->chip,
- "%d:%d: sticky mixer values (%d/%d/%d => %d), disabling\n",
- cval->head.id, mixer_ctrl_intf(cval->head.mixer),
- cval->min, cval->max, cval->res, saved);
usb_audio_info(cval->head.mixer->chip,
- "check MIXER_GET_CUR_BROKEN if you believe the mixer is non-sticky");
+ "%d:%d: broken mixer GET_CUR (%d/%d/%d => %d)\n",
+ cval->head.id, mixer_ctrl_intf(cval->head.mixer),
+ cval->min, cval->max, cval->res, saved);
- return -ENODEV;
+ cval->get_cur_broken = 1;
+ return -ENXIO;
}
/*
@@ -1385,8 +1380,6 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
goto no_checks;
ret = check_sticky_volume_control(cval, minchn, saved);
- if (ret == -ENODEV)
- goto sticky;
if (ret)
goto no_checks;
@@ -1455,33 +1448,6 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
return 0;
-
-sticky:
- /*
- * It makes no sense to restore the saved value for a sticky mixer,
- * since setting any value is a no-op.
- *
- * However, in some rare cases, SET_CUR is effective despite GET_CUR
- * always returns a constant value. These mixers are not sticky, but
- * there's no way to distinguish them. Without any additional
- * information, the best thing we can do is to set the mixer value to
- * the maximum before bailing out, so that a soft mixer can still reach
- * the maximum hardware volume if the mixer turns out to be non-sticky.
- * Meanwhile, all channels must be synchronized to prevent imbalance
- * volume.
- */
- if (!cval->cmask) {
- snd_usb_set_cur_mix_value(cval, 0, 0, cval->max);
- } else {
- idx = 0;
- for (i = 0; i < MAX_CHANNELS; i++) {
- if (cval->cmask & BIT(i)) {
- snd_usb_set_cur_mix_value(cval, i + 1, idx, cval->max);
- idx++;
- }
- }
- }
- return ret;
}
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 3/4] ALSA: usb-audio: Reverse MIXER_GET_CUR_BROKEN as MIXER_GET_CUR_OK
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
2026-08-22 18:52 ` [PATCH 1/4] ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE Rong Zhang
2026-08-22 18:52 ` [PATCH 2/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
@ 2026-08-22 18:52 ` Rong Zhang
2026-08-22 18:52 ` [PATCH 4/4] ALSA: usb-audio: Add quirk flags for Logitech PRO X Wireless Rong Zhang
2026-08-23 9:04 ` [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Takashi Iwai
4 siblings, 0 replies; 6+ messages in thread
From: Rong Zhang @ 2026-08-22 18:52 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Cc: Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer, Rong Zhang
The default behavior of sticky check now becomes what
QUIRK_FLAG_MIXER_GET_CUR_BROKEN originally does, so the quirk flag is no
longer needed.
On some devices, whether their GET_CUR being sticky depends on whether
hotpluggable components are present. When the hotpluggable components
are missing on probe, their GET_CUR behavior is classified as broken.
Therefore, reverse QUIRK_FLAG_MIXER_GET_CUR_BROKEN as
QUIRK_FLAG_MIXER_GET_CUR_OK, so that it can be set to prevent the
heuristics from gating GET_CUR.
Note that even if the quirk flag is set, init_cur_mix_raw() should still
initialize the mixer value to cval->min, otherwise restoring the bogus
saved value on the first channel could lead to unbalanced channels.
Signed-off-by: Rong Zhang <i@rong.moe>
---
Documentation/sound/alsa-configuration.rst | 20 ++++++++------------
sound/usb/mixer.c | 8 ++++++++
sound/usb/quirks.c | 16 +++-------------
sound/usb/usbaudio.h | 20 +++++++-------------
4 files changed, 26 insertions(+), 38 deletions(-)
diff --git a/Documentation/sound/alsa-configuration.rst b/Documentation/sound/alsa-configuration.rst
index 71733e807a7c..e500ec84e3ef 100644
--- a/Documentation/sound/alsa-configuration.rst
+++ b/Documentation/sound/alsa-configuration.rst
@@ -2316,6 +2316,9 @@ quirk_flags
applies the ``mixer_playback_min_mute`` flag and clears the
``ignore_ctl_error`` flag for the device 1234:abcd, and applies the
``skip_sample_rate`` flag for all devices.
+ New quirk flags may replace old ones by reusing the latter's bits, so the
+ new usage is preferred. Despite that, depending on the order of probing is
+ fragile, so it'd better migrate to the new usage anyway.
* bit 0: ``get_sample_rate``
Skip reading sample rate for devices
@@ -2389,18 +2392,11 @@ 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_get_cur_broken``
- Some mixers are sticky, which means that setting their current volume
- is a no-op, and reading the current volume returns a constant value.
- The sticky check disables these mixers to prevent confusing userspace.
- However, some devices do have a tunable volume despite the reported
- current volume being constant. As the sticky check can't distinguish
- between the two categories, setting this flag tells that the device
- should fall into the second category when GET_CUR returns a constant
- value, resulting in the sticky check being non-fatal and only
- disabling GET_CUR instead of the whole mixer. The current volume will
- then be provided by the internal cache that stores the last set
- volume
+ * bit 30: ``mixer_get_cur_ok``
+ On some devices, whether their GET_CUR being sticky depends on whether
+ hotpluggable components are present. When the hotpluggable components
+ are missing on probe, their GET_CUR behavior is classified as broken.
+ Set the flag to prevent the heuristics from gating GET_CUR.
* bit 31: ``playback_urb_fixup``
Some devices show the stuttering at playback, and this quirk
works around it by enforcing the fixed max URBs (12) instead of
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 3aa9a9c12557..ecaa8bc08d7c 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1447,6 +1447,14 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
}
+ /*
+ * When GET_CUR is sticky, the saved value is bogus, so mixer values set
+ * by the sanity checks must be discarded through init_cur_mix_raw().
+ * After that, we can clear the flag as per QUIRK_FLAG_MIXER_GET_CUR_OK.
+ */
+ if (cval->head.mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_GET_CUR_OK)
+ cval->get_cur_broken = 0;
+
return 0;
}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index eb1750def067..b62168a11e32 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2215,8 +2215,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x03f0, 0x654a, /* HP 320 FHD Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
- DEVICE_FLG(0x040b, 0x0897, /* Weltrend Semiconductor, sold as Redragon H510-PRO Wireless headset */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x041e, 0x3000, /* Creative SB Extigy */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x041e, 0x4080, /* Creative Live Cam VF0610 */
@@ -2256,8 +2254,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x046d, 0x0a8f, /* Logitech H390 headset */
QUIRK_FLAG_CTL_MSG_DELAY_1M |
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
- DEVICE_FLG(0x046d, 0x0af7, /* Logitech PRO X 2 LIGHTSPEED */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
@@ -2329,9 +2325,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x0763, 0x2031, /* M-Audio Fast Track C600 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0763, 0x2080, /* M-Audio Fast Track Ultra */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0763, 0x2081, /* M-Audio Fast Track Ultra */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x07fd, 0x000b, /* MOTU M Series 2nd hardware revision */
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x08bb, 0x2702, /* LineX FM Transmitter */
@@ -2370,8 +2366,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x1038, 0x1294, /* SteelSeries Arctis Pro Wireless */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
- DEVICE_FLG(0x1038, 0x2232, /* SteelSeries Arctis Nova 5 */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x1101, 0x0003, /* Audioengine D1 */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x12d1, 0x3a07, /* HUAWEI USB-C HEADSET */
@@ -2379,8 +2373,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
- DEVICE_FLG(0x1377, 0x6004, /* Sennheiser MOMENTUM 3 */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
@@ -2505,8 +2497,6 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x2d99, 0x0026, /* HECATE G2 GAMING HEADSET */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
- DEVICE_FLG(0x2d99, 0xa024, /* Edifier MF200 */
- QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x2fc6, 0xf06b, /* MOONDROP Moonriver2 Ti */
QUIRK_FLAG_CTL_MSG_DELAY),
DEVICE_FLG(0x2fc6, 0xf0b5, /* iBasso DC-Elite */
@@ -2647,7 +2637,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_GET_CUR_BROKEN),
+ QUIRK_STRING_ENTRY(MIXER_GET_CUR_OK),
QUIRK_STRING_ENTRY(PLAYBACK_URB_FIXUP),
QUIRK_STRING_ENTRY(ALWAYS_SET_RATE),
NULL
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index abc2d7e579de..24436473931d 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -243,17 +243,11 @@ 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_GET_CUR_BROKEN
- * Some mixers are sticky, which means that setting their current volume is a
- * no-op, and reading the current volume returns a constant value. The sticky
- * check disables these mixers to prevent confusing userspace. However, some
- * devices do have a tunable volume despite the reported current volume being
- * constant. As the sticky check can't distinguish between the two categories,
- * setting this flag tells that the device should fall into the second
- * category when GET_CUR returns a constant value, resulting in the sticky
- * check being non-fatal and only disabling GET_CUR instead of the whole mixer.
- * The current volume will then be provided by the internal cache that stores
- * the last set volume
+ * QUIRK_FLAG_MIXER_GET_CUR_OK
+ * On some devices, whether their GET_CUR being sticky depends on whether
+ * hotpluggable components are present. When the hotpluggable components are
+ * missing on probe, their GET_CUR behavior is classified as broken. Set the
+ * flag to prevent the heuristics from gating GET_CUR.
* QUIRK_FLAG_PLAYBACK_URB_FIXUP
* Set URB_ISO_ASAP flag for isochronous URBs and force nurbs to MAX_URBS.
* This is needed for devices that exhibit boot-time audio stuttering due
@@ -297,7 +291,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_GET_CUR_BROKEN = 30,
+ QUIRK_TYPE_MIXER_GET_CUR_OK = 30,
QUIRK_TYPE_PLAYBACK_URB_FIXUP = 31,
QUIRK_TYPE_ALWAYS_SET_RATE = 32,
/* Please also edit snd_usb_audio_quirk_flag_names and alsa-configuration.rst */
@@ -335,7 +329,7 @@ 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_GET_CUR_BROKEN QUIRK_FLAG(MIXER_GET_CUR_BROKEN)
+#define QUIRK_FLAG_MIXER_GET_CUR_OK QUIRK_FLAG(MIXER_GET_CUR_OK)
#define QUIRK_FLAG_PLAYBACK_URB_FIXUP QUIRK_FLAG(PLAYBACK_URB_FIXUP)
#define QUIRK_FLAG_ALWAYS_SET_RATE QUIRK_FLAG(ALWAYS_SET_RATE)
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* [PATCH 4/4] ALSA: usb-audio: Add quirk flags for Logitech PRO X Wireless
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
` (2 preceding siblings ...)
2026-08-22 18:52 ` [PATCH 3/4] ALSA: usb-audio: Reverse MIXER_GET_CUR_BROKEN as MIXER_GET_CUR_OK Rong Zhang
@ 2026-08-22 18:52 ` Rong Zhang
2026-08-23 9:04 ` [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Takashi Iwai
4 siblings, 0 replies; 6+ messages in thread
From: Rong Zhang @ 2026-08-22 18:52 UTC (permalink / raw)
To: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap
Cc: Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer, Rong Zhang
The Logitech PRO X Wireless is a wireless headset with a hotpluggable
microphone.
Its Playback mixer's GET_CUR somehow becomes broken when the microphone
is detached, so set QUIRK_FLAG_MIXER_GET_CUR_OK to prevent the mixer
behavior from depending on whether the microphone is attached.
Meanwhile, the Playback mixer's minimum value doesn't work properly,
thus set QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE to prevent userspace audio
stack from using the minimum mixer value to tune volume (setting it
when muted is OK).
Reported-by: Alexander Niemeyer <adventureFAN@gmx.de>
Closes: https://msgid.link/6262cbbd-d1f2-4c9d-a1c7-9c5d12636f4b@gmx.de
Closes: https://msgid.link/7984832b-86f6-4934-bfc0-1ed70218973a@gmx.de
Signed-off-by: Rong Zhang <i@rong.moe>
---
sound/usb/quirks.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index b62168a11e32..1e5a261f9c10 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2254,6 +2254,9 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
DEVICE_FLG(0x046d, 0x0a8f, /* Logitech H390 headset */
QUIRK_FLAG_CTL_MSG_DELAY_1M |
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
+ DEVICE_FLG(0x046d, 0x0aba, /* Logitech PRO X Wireless */
+ QUIRK_FLAG_MIXER_GET_CUR_OK |
+ QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
--
2.55.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
` (3 preceding siblings ...)
2026-08-22 18:52 ` [PATCH 4/4] ALSA: usb-audio: Add quirk flags for Logitech PRO X Wireless Rong Zhang
@ 2026-08-23 9:04 ` Takashi Iwai
4 siblings, 0 replies; 6+ messages in thread
From: Takashi Iwai @ 2026-08-23 9:04 UTC (permalink / raw)
To: Rong Zhang
Cc: Jaroslav Kysela, Takashi Iwai, Jonathan Corbet, Shuah Khan,
Randy Dunlap, Takashi Iwai, linux-sound, linux-doc, linux-kernel,
Alexander Niemeyer
On Sat, 22 Aug 2026 20:52:27 +0200,
Rong Zhang wrote:
>
> Currently, a mixer is disabled when its GET_CUR is sticky, causing
> userspace to fall back to soft mixers, unless
> QUIRK_FLAG_MIXER_GET_CUR_BROKEN is set. This leads to issues on some
> wireless headphones with broken GET_CUR but effective SET_CUR, which use
> poorly-performed lossy codecs and are prone to audible distortion at low
> volume. They have to set the quirk flag to reeanble the mixer.
>
> Considering that users can always opt into soft mixers if they need it,
> i.e., when SET_CUR is stubbed, demote the severity of sticky GET_CUR by
> marking GET_CUR as broken and only provide mixer values from the cache.
> The mixer itself is still registered.
>
> The default behavior of sticky check now becomes what
> QUIRK_FLAG_MIXER_GET_CUR_BROKEN originally does, so the quirk flag is no
> longer needed.
>
> On some devices, whether their GET_CUR being sticky depends on whether
> hotpluggable components are present. When the hotpluggable components
> are missing on probe, their GET_CUR behavior is classified as broken.
> Therefore, reverse QUIRK_FLAG_MIXER_GET_CUR_BROKEN as
> QUIRK_FLAG_MIXER_GET_CUR_OK, so that it can be set to prevent the
> heuristics from gating GET_CUR.
>
> Note that even if the quirk flag is set, init_cur_mix_raw() should still
> initialize the mixer value to cval->min, otherwise restoring the bogus
> saved value on the first channel could lead to unbalanced channels.
>
> The first user of QUIRK_FLAG_MIXER_GET_CUR_OK is Logitech PRO X
> Wireless, whose Playback mixer's GET_CUR somehow becomes broken when the
> microphone is detached, so set QUIRK_FLAG_MIXER_GET_CUR_OK to prevent
> the mixer behavior from depending on whether the microphone is attached.
> The device also needs QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE as the minimum
> mixer value doesn't work properly.
>
> Reported-by: Alexander Niemeyer <adventureFAN@gmx.de>
> Closes: https://msgid.link/6262cbbd-d1f2-4c9d-a1c7-9c5d12636f4b@gmx.de
> Closes: https://msgid.link/7984832b-86f6-4934-bfc0-1ed70218973a@gmx.de
> Signed-off-by: Rong Zhang <i@rong.moe>
Applied all four patches now. Thanks.
Takashi
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-08-23 9:05 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-22 18:52 [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
2026-08-22 18:52 ` [PATCH 1/4] ALSA: doc: usb-audio: Add doc for QUIRK_FLAG_ALWAYS_SET_RATE Rong Zhang
2026-08-22 18:52 ` [PATCH 2/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Rong Zhang
2026-08-22 18:52 ` [PATCH 3/4] ALSA: usb-audio: Reverse MIXER_GET_CUR_BROKEN as MIXER_GET_CUR_OK Rong Zhang
2026-08-22 18:52 ` [PATCH 4/4] ALSA: usb-audio: Add quirk flags for Logitech PRO X Wireless Rong Zhang
2026-08-23 9:04 ` [PATCH 0/4] ALSA: usb-audio: Demote the severity of sticky GET_CUR Takashi Iwai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox