Linux Sound subsystem development
 help / color / mirror / Atom feed
From: Alexander Niemeyer <adventureFAN@gmx.de>
To: linux-sound@vger.kernel.org
Cc: regressions@lists.linux.dev, tiwai@suse.de, perex@perex.cz
Subject: Re: [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky
Date: Fri, 14 Aug 2026 16:02:45 +0200	[thread overview]
Message-ID: <defedf81-5f14-4a50-9237-cb180eaab39e@gmx.de> (raw)
In-Reply-To: <c61e9568284fd0cd1580eb2b568700074c73e123.camel@rong.moe>

Thanks Rong.
I'd be happy to test your patch on the Logitech PRO X Wireless as soon 
as it's ready.

Am 14.08.26 um 15:17 schrieb Rong Zhang:
> Hi Alexander,
>
> Thanks for the report.
>
> On Fri, 2026-08-14 at 12:41 +0200, Alexander N. wrote:
>> Hello,
>>
>> I found a regression in snd-usb-audio affecting the Logitech PRO X
>> Wireless Gaming Headset (USB ID 046d:0aba).
>>
>> The device has a valid UAC1 playback volume control, but the sticky mixer
>> detection introduced by commit 86aa1ea1f15c ("ALSA: usb-audio: Do not
>> expose sticky mixers") rejects it.
>>
>> Hardware
>> ========
>>
>>     Logitech PRO X Wireless Gaming Headset
>>     USB ID: 046d:0aba
>>
>> Observed kernel
>> ===============
>>
>>     7.1.5-ogc5.1.fc44.x86_64
>>     Bazzite/Fedora 44 OGC kernel
>>
>> The OGC patch for this kernel does not modify sound/usb, and the relevant
>> mixer.c code matches upstream Linux 7.1.5.
>>
>> I have not hardware-tested current mainline 7.2-rc7, but current upstream
>> mixer.c still contains the same immediate SET_CUR -> GET_CUR sticky mixer
>> test and I could not find a device quirk for 046d:0aba.
>>
>> Symptom
>> =======
>>
>> Without a workaround, ALSA only exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pswitch pswitch-joined
>>
>> There is no PCM Playback Volume control.
>>
>> The kernel logs:
>>
>>     usb 1-10: 2:0: sticky mixer values (-16384/0/256 => -3840), disabling
>>
>> I have also observed the same message ending in "=> 0", depending on the
>> hardware volume at probe time.
>>
>> Because the playback volume control is removed, the physical volume wheel
>> changes the headset's hardware volume independently of the PipeWire/KDE
>> system volume.
>>
>> USB Audio control behavior
>> ==========================
>>
>> The device is UAC1.
>>
>> Feature Unit 2 exposes a master playback volume control.
>>
>> Direct control requests, after temporarily unbinding AudioControl
>> interface 0 from snd-usb-audio, report:
>>
>>     GET_MIN = -16384  (-64.00 dB)
>>     GET_MAX =      0  (  0.00 dB)
>>     GET_RES =    256  (  1.00 dB)
>>
>> GET_CUR and SET_CUR both work, but the device has two quirks relevant to
>> the new sticky detection.
>>
>> 1. GET_CUR reflects normal SET_CUR changes with a delay of roughly 50 ms.
> Interesting.
>
>> Measured from 0 dB:
>>
>>     target     result   first visible GET_CUR change
>>
>>      -1 dB     OK       81.3 ms
>>      -2 dB     OK       51.9 ms
>>      -4 dB     OK       47.3 ms
>>      -8 dB     OK       47.1 ms
>>     -16 dB     OK       51.7 ms
>>     -32 dB     OK       47.2 ms
>>
>> 2. The advertised minimum value -64 dB is not functional.
>>
>> A direct SET_CUR to -64 dB returns success, but GET_CUR remains at 0 dB
>> even after 1000 ms.
>>
>> This appears to cause a false positive in check_sticky_volume_control():
>>
>> - cval->min is -16384 (-64 dB)
>> - cval->max is 0
>> - if the saved value is 0, max is skipped
>> - SET_CUR(min) returns success
>> - an immediate GET_CUR still returns the saved value
>> - the mixer is classified as sticky and is not registered
> Super interesting.
>
> Maybe some previously reported devices were broken because of the same
> reason.
>
> I think, the sticky check could be more precise in this manner:
>
>     res = (cval->max - cval->min) / 16; /* Check approximately 16 values. */
>     if (res < cval->res)
>     	res = cval->res;
>     else
>     	res = roundup(res, cval->res);
>     
>     for (i = cval->min; i+= res; i < cval->max) {
>     	if (i == saved)
>     		continue;
>     	SET_CUR(i);
>     	check = GET_CUR(i);
>     	if (check != saved)
>     		break;	/* Fast path. */
>     	/*
>     	 * Wait for asynchronous mixers. This sleeps for no more than 160ms
>     	 * in total, which should provide some time for the mixer to change
>     	 * its value.
>     	 * Note that there is no need to wait between SET_CUR and GET_CUR,
>     	 * as we don't care whether the GET_CUR value matches the SET_CUR one.
>     	 * What we expect is just a GET_CUR value differing from the saved one.
>     	 * It this manner, most devices should go through the fast path without
>     	 * extra sleep.
>     	 */
>     	msleep(10);
>     }
>     [...]
>
> This should classify your device as non-sticky.
>
> I will find some time to write a patch for that. I would be grateful if
> you can test it then.
>
> Thanks,
> Rong
>
>> mixer_get_cur_broken is not appropriate
>> =======================================
>>
>> I tested the mixer_get_cur_broken quirk.
>>
>> GET_CUR on this device is not broken or constant. It correctly reports
>> host SET_CUR changes after the device delay, and it also reports volume
>> changes caused by the physical headset wheel.
>>
>> Using an internal-only cached value would therefore lose useful hardware
>> state.
>>
>> Local proof-of-concept fix
>> ==========================
>>
>> I built a local snd-usb-audio.ko against the running 7.1.5 kernel.
>>
>> For this specific device, Feature Unit 2, UAC_FU_VOLUME, I:
>>
>> - clamp the unusable minimum from -64 dB to -63 dB
>> - skip the probe-time sticky/resolution checks for this control
>>
>> With that module, ALSA exposes:
>>
>>     Simple mixer control 'PCM',0
>>       Capabilities: pvolume pvolume-joined pswitch pswitch-joined
>>       Playback channels: Mono
>>       Limits: Playback 0 - 63
>>
>> /proc/asound/card*/usbmixer shows:
>>
>>     Unit: 2
>>       Control: name="PCM Playback Volume", index=0
>>       Info: id=2, control=2, cmask=0x0, channels=1, type="S16"
>>       Volume: min=-16128, max=0, dBmin=-6300, dBmax=0
>>
>> Most importantly, no userspace workaround is required once the mixer
>> control is restored.
>>
>> Example before rotating the physical headset wheel:
>>
>>     ALSA:     -27 dB / 57%
>>     PipeWire: 0.35
>>
>> After rotating the headset wheel:
>>
>>     ALSA:     -11 dB / 83%
>>     PipeWire: 0.65
>>
>> KDE system volume follows the physical wheel as expected.
>>
>> I attached the proof-of-concept diff and the measured results. I am happy
>> to test a maintainer-preferred implementation or additional diagnostics.
>>
>> My suspicion is that this device exposes two assumptions in the sticky
>> mixer probe that are not universally safe:
>>
>> 1. GET_CUR is assumed to reflect SET_CUR immediately.
>> 2. advertised min/max values are assumed to be usable test values.
>>
>> Thanks.
>>
>> #regzbot introduced: 86aa1ea1f15ce6b56ac1b4c0d9b88a07a5b9bf03

      reply	other threads:[~2026-08-14 14:03 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-14 10:41 [REGRESSION] ALSA: usb-audio: Logitech PRO X Wireless 046d:0aba playback volume rejected as sticky Alexander N.
2026-08-14 11:53 ` Takashi Iwai
2026-08-14 13:17 ` Rong Zhang
2026-08-14 14:02   ` Alexander Niemeyer [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=defedf81-5f14-4a50-9237-cb180eaab39e@gmx.de \
    --to=adventurefan@gmx.de \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=regressions@lists.linux.dev \
    --cc=tiwai@suse.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox