]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: hda/ca0132: Disable auto-detect on manual output select
authorMatt DeVillier <matt.devillier@gmail.com>
Thu, 7 May 2026 14:58:41 +0000 (09:58 -0500)
committerTakashi Iwai <tiwai@suse.de>
Fri, 15 May 2026 09:19:48 +0000 (11:19 +0200)
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@gmail.com>
Link: https://lore.kernel.org/CAFTm+6AfeXKf=b2frG4xC5yC4jjM9TkD6c8+dOWWFw6BDjDESw@mail.gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/hda/codecs/ca0132.c

index ad533b04ab29cf277ef86b8a9129beefde39b4ed..be565ffaade0abac94b1262b0ed4ddd5f869d30b 100644 (file)
@@ -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;
 }