Re: [regression] ctxfi: no speaker output when headphones connected on >=7.0.x

From: Matt DeVillier

Date: Thu May 07 2026 - 11:11:25 EST


On Thu, May 7, 2026 at 8:24 AM Takashi Iwai <tiwai@xxxxxxx> wrote:
>
> On Thu, 07 May 2026 14:47:03 +0200,
> Dutch Ingraham wrote:
> >
> > > Sent: Thursday, May 07, 2026 at 1:30 AM
> > > From: "Takashi Iwai" <tiwai@xxxxxxx>
> > > To: "Harin Lee" <me@xxxxxxxxx>
> > > Cc: "Takashi Iwai" <tiwai@xxxxxxx>, "Thorsten Leemhuis" <regressions@xxxxxxxxxxxxx>, "Jaroslav Kysela" <perex@xxxxxxxx>, "Takashi Iwai" <tiwai@xxxxxxxx>, "Linux kernel regressions list" <regressions@xxxxxxxxxxxxxxx>, "Linux Sound System" <linux-sound@xxxxxxxxxxxxxxx>, "LKML" <linux-kernel@xxxxxxxxxxxxxxx>, stoa@xxxxxx
> > > Subject: Re: [regression] ctxfi: no speaker output when headphones connected on >=7.0.x
> > >
> > > On Thu, 07 May 2026 00:06:11 +0200,
> > > Harin Lee wrote:
> > > >
> > > > On 5/6/26 4:05 PM, Takashi Iwai wrote:
> > > > > On Wed, 06 May 2026 08:24:36 +0200,
> > > > > Thorsten Leemhuis wrote:
> > > > >>
> > > > >> Hi! Just FYI, I noticed a regression report in bugzilla:
> > > > >>
> > > > >> https://bugzilla.kernel.org/show_bug.cgi?id=221461
> > > > >>
> > > > >> To quote:
> > > > >>
> > > > >>> Dutch Ingraham 2026-05-03 18:12:49 UTC
> > > > >>>
> > > > >>> Kernels >=7.0.1 contain a regression as to Creative Sound Blaster Z SE
> > > > >>> discrete pci sound card, but not integrated. Kernels 7.0.1, 7.0.2, and
> > > > >>> 7.0.3 tested; 7.0.0 not tested. Reverting to any 6.18.x or 6.12.x does
> > > > >>> not present the issue.
> > > > >>>
> > > > >>> Specifically, using pipewire managed by pavucontrol, on both Gentoo and
> > > > >>> Arch Linux, when both external speakers and headphones are connected,
> > > > >>> all sound is routed through the headphones regardless of whether settings
> > > > >>> are set to Line Out/Speaker or Line Out/Headphones; there is no speaker
> > > > >>> output. If headphones are disconnected, without reboot, speakers work;
> > > > >>> reconnect headphones, without reboot, sound reverts to headphones.
> > > > >>>
> > > > >>> Kernel: 7.0.3, Gentoo compiled from source using olddefconfig on 6.18.24
> > > > >>> .config; Arch standard release
> > > > >>> 'lspci -nnk | grep -i audio' attached
> > > > >>> 'dmesg | grep -i audio' for 7.0.3 and 6.18.24 attached
> > > > >>> pipewire-1.6.4 on both Gentoo and Arch Linux
> > > > >>> alsa-firmware-1.2.4 on both Gentoo and Arch Linux
> > > > >>> 'cat /proc/sys/kernel/tainted' returns 0 for both Gentoo and Arch Linux
> > > > >>>
> > > > >>> Processor : AMD Ryzen7 5700G
> > > > >>> Motherboard : Asus Prime X570-Pro
> > > > >>> RAM : Patriot Viper Steel DDR-4 @3200mHz
> > > > >>> Graphics : ASRock AMD Radeon RX 7600 Challenger 8GB OC
> > > > >>> Sound Card : Creative Sound Blaster Z SE
> > > > >>>
> > > > >>>
> > > > >>> Expected outcome: ability to choose output to either speakers or head-
> > > > >>> phones while both are plugged-in to sound card.
> > > > >>>
> > > > >>> Workaround: none known.
> > > > >>
> > > > >> See the ticket for more details. One of them: 7.1-rc2 is affected as
> > > > >> well. Reporter is CCed. Forwarded this to ensure this report makes it to
> > > > >> the interested parties, as bugzilla might not have forwarded this.
> > > > >>
> > > > >> Dutch Ingraham: if nobody within a few days has an idea why this
> > > > >> happens, you will likely have to use a git bisection to get this resolved.
> > > > >
> > > > > As there have been many significant changes in ctxfi since 6.18, it's
> > > > > hard to tell what broke. Please go git bisect.
> > > > >
> > > > >
> > > > > thanks,
> > > > >
> > > > > Takashi
> > > > >
> > > >
> > > > Creative Sound Blaster Z-series uses the snd_hda_codec_ca0132 driver,
> > > > not snd_ctxfi. The dmesg logs in the bugzilla shows only ca0132
> > > > entries.
> > >
> > > Ah, sorry, then it's easier. The only major change is the
> > > commit 778031e1658d206a52bf9491c91ae5d4f4a2509d
> > > ALSA: hda/ca0132: Set HP/Speaker auto-detect default from headphone pin verb
> > >
> > > Try to revert this one.
> > >
> > >
> > > thanks,
> > >
> > > Takashi
> > >
> >
> > I can confirm this seems like a good candidate. I built and tested 6.19.14
> > and 7.0. On 6.19.14, speakers work as expected; on 7.0, speakers are not
> > working as expected and the offending patch is included in the 7.0 patchset.
> >
> > Thank you all for your work on this issue.
>
> OK, then let's put Matt to the party.
> Matt, could you help for debugging the regression?
>
>
> Takashi


I can confirm the regression here on my 2013 Chromebook Pixel w/CA0132.

Looking more closely, the issue is that tVNID_HP_ASEL and VNID_HP_SEL are
mutually exclusive selection sources in ca0132_select_out() /
ca0132_alt_select_out(),
and auto-detect always "wins." So, enabling auto-detect effectively
disabled user
override.

While reverting would fix this problem, it would reintroduce the
problem of jack-detect being
ignored completely. A better solution would be to default to
auto-detect, but allow manual selection
to override. Here's a quick patch I whipped up that should resolve the
issue (untested though):
---
From: Matt DeVillier <matt.devillier@xxxxxxxxx>
Date: Thu, 7 May 2026 09:58:41 -0500
Subject: [PATCH] ALSA: hda/ca0132: Disable auto-detect on manual output select

Commit 778031e1658d ("ALSA: hda/ca0132: Set HP/Speaker
auto-detect default from headphone pin verb") enables HP/Speaker
auto-detect by default when the headphone pin supports presence detect.

With auto-detect enabled, ca0132_select_out() and ca0132_alt_select_out()
choose the output from jack presence instead of the manual HP/Speaker
selection. This means selecting speaker output while headphones are
plugged in updates the control state, but audio still routes to the
headphones.

Treat an explicit manual output selection as a request to leave
auto-detect mode. Clear the HP/Speaker auto-detect switch before applying
the manual selection, and notify userspace so the auto-detect control
state is updated in mixers. Do this for both the normal HP/Speaker
Playback Switch and the alternate Output Select control used by desktop
cards.

This keeps auto-detect enabled by default for devices with jack presence
detection, while preserving the expected behavior that a manual output
choice takes effect immediately.

Fixes: 778031e1658d ("ALSA: hda/ca0132: Set HP/Speaker auto-detect
default from headphone pin verb")
Signed-off-by: Matt DeVillier <matt.devillier@xxxxxxxxx>
---
sound/hda/codecs/ca0132.c | 44 +++++++++++++++++++++++++++++++-------------
1 file changed, 31 insertions(+), 13 deletions(-)

diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c
index ad533b04ab29..be565ffaade0 100644
--- a/sound/hda/codecs/ca0132.c
+++ b/sound/hda/codecs/ca0132.c
@@ -5498,6 +5498,30 @@ static int zxr_headphone_gain_set(struct
hda_codec *codec, long val)
return 0;
}

+/*
+ * Manual output selection (HP/Speaker Playback Switch or alt Output Select)
+ * is meaningful only when HP/Speaker auto-detect is disabled, since the
+ * select_out path always prefers jack presence when auto-detect is on. When
+ * the user explicitly chooses an output, turn auto-detect off so the manual
+ * choice actually takes effect, and notify userspace so the auto-detect
+ * control reflects the new state.
+ */
+static void ca0132_disable_hp_auto_detect(struct hda_codec *codec)
+{
+ struct ca0132_spec *spec = codec->spec;
+ struct snd_kcontrol *kctl;
+
+ if (!spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID])
+ return;
+
+ spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID] = 0;
+ kctl = snd_hda_find_mixer_ctl(codec,
+ "HP/Speaker Auto Detect Playback Switch");
+ if (kctl)
+ snd_ctl_notify(codec->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &kctl->id);
+}
+
static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -5510,14 +5534,11 @@ static int ca0132_vnode_switch_set(struct
snd_kcontrol *kcontrol,
int auto_jack;

if (nid == VNID_HP_SEL) {
- auto_jack =
- spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
- if (!auto_jack) {
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(codec);
- else
- ca0132_select_out(codec);
- }
+ ca0132_disable_hp_auto_detect(codec);
+ if (ca0132_use_alt_functions(spec))
+ ca0132_alt_select_out(codec);
+ else
+ ca0132_select_out(codec);
return 1;
}

@@ -5978,7 +5999,6 @@ static int ca0132_alt_output_select_put(struct
snd_kcontrol *kcontrol,
struct ca0132_spec *spec = codec->spec;
int sel = ucontrol->value.enumerated.item[0];
unsigned int items = NUM_OF_OUTPUTS;
- unsigned int auto_jack;

if (sel >= items)
return 0;
@@ -5988,10 +6008,8 @@ static int ca0132_alt_output_select_put(struct
snd_kcontrol *kcontrol,

spec->out_enum_val = sel;

- auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
-
- if (!auto_jack)
- ca0132_alt_select_out(codec);
+ ca0132_disable_hp_auto_detect(codec);
+ ca0132_alt_select_out(codec);

return 1;
}
--
2.51.0