mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Takashi Iwai <tiwai@suse.de>
To: Rithvik Vibhu <rithvikvibhu@gmail.com>
Cc: Takashi Iwai <tiwai@suse.com>, Jaroslav Kysela <perex@perex.cz>,
	linux-sound@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH] ALSA: hda/realtek: Fix Acer Nitro 5 AN515-57 mic resume
Date: Mon, 14 Sep 2026 18:23:56 +0200	[thread overview]
Message-ID: <871pavol7n.wl-tiwai@suse.de> (raw)
In-Reply-To: <20260904231545.33505-1-rithvikvibhu@gmail.com>

On Sat, 05 Sep 2026 01:15:45 +0200,
Rithvik Vibhu wrote:
> 
> The existing pin-configuration quirk exposes headset mic pin 0x19, but
> the ALC295 loses the correct combo-jack state across suspend-to-RAM
> (S3). After resume, pin 0x19 can remain falsely present after unplug and
> the capture mixer can remain routed away from the internal mic on pin
> 0x12. The failure occurs on both 6.12 and v7.2-rc7.
> 
> Give subsystem 1025:1539 a model-specific fixup which initializes the
> Acer combo-jack coefficients, enables the full Realtek CTIA/OMTP
> headset state machine, gates the headset mic with the reliable
> headphone pin 0x21, and feeds the corrected cached jack state through
> generic HDA mic autoswitching. This keeps the actual capture mux
> synchronized across boot, hotplug, unplug and S3 resume.
> 
> Apply the correction from both the headphone and microphone callback
> paths. A direct event from mic pin 0x19 otherwise bypasses the headphone
> hook and can restore the unreliable raw pin sense. Invalidate and
> refetch pin 0x21 when handling such an event before deriving the
> corrected microphone state.
> 
> Pin 0x21 indicates that a combo-jack plug is present but cannot
> distinguish three-pole headphones from a four-pole headset.
> Consequently, as with other headphone-gated mic configurations, a
> three-pole plug is exposed as a headset mic.
> 
> Tested with cold boot and repeated S3 cycles in the unplugged and
> four-pole-headset states, including unplug and reinsert after resume.
> 
> Fixes: 51db05283f7c ("ALSA: hda/realtek: Enable headset mic for Acer Nitro 5")
> Cc: stable@vger.kernel.org # 6.12+
> Assisted-by: LLM
> Signed-off-by: Rithvik Vibhu <rithvikvibhu@gmail.com>

Thanks for the patch.

I guess I understand most of the intentions in your code, but it looks
a bit too complex and handling things unnaturally.  After all, there
is no similar code there, which already appearing suspicious.

Can this be handled better with the gating stuff in
sound/hda/common/jack.c, instead?


Takashi


> ---
> The 6.12.y backport requires adaptation because the Realtek codec code
> is located in sound/pci/hda/patch_realtek.c there.
> 
> base-commit: 3b26ceef88c110f4d188387cffa0df78657be904
> 
>  sound/hda/codecs/realtek/alc269.c | 105 +++++++++++++++++++++++++++++-
>  1 file changed, 104 insertions(+), 1 deletion(-)
> 
> diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
> index 95b40a177..f1a83908e 100644
> --- a/sound/hda/codecs/realtek/alc269.c
> +++ b/sound/hda/codecs/realtek/alc269.c
> @@ -3740,6 +3740,103 @@ static void alc2xx_fixup_headset_mic(struct hda_codec *codec,
>  	}
>  }
>  
> +static void alc295_acer_nitro_mic_autoswitch(struct hda_codec *codec,
> +					     struct hda_jack_callback *jack)
> +{
> +	struct alc_spec *spec = codec->spec;
> +	struct hda_jack_tbl *hp_jack, *mic_jack;
> +	hda_nid_t hp_pin = alc_get_hp_pin(spec);
> +	bool auto_mic = spec->gen.auto_mic;
> +	bool hp_present;
> +
> +	hp_jack = snd_hda_jack_tbl_get(codec, hp_pin);
> +	mic_jack = snd_hda_jack_tbl_get(codec, 0x19);
> +	if (!hp_jack || !mic_jack) {
> +		codec_warn(codec, "failed to find Acer Nitro combo-jack entries\n");
> +		return;
> +	}
> +
> +	/* A mic callback must not reuse a possibly stale cached HP sense. */
> +	if (jack && jack->nid == 0x19)
> +		hp_jack->jack_dirty = 1;
> +	hp_present = snd_hda_jack_detect(codec, hp_pin);
> +
> +	/*
> +	 * The codec reports a stale or inverted presence state for mic pin 0x19
> +	 * after S3.  Pin 0x21 continues to track the shared combo jack reliably,
> +	 * so use it as the presence source for 0x19.  Leave the entry clean so
> +	 * the normal report pass does not immediately replace this value with a
> +	 * broken raw pin-sense read.
> +	 */
> +	mic_jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
> +	if (hp_present)
> +		mic_jack->pin_sense |= AC_PINSENSE_PRESENCE;
> +	mic_jack->jack_dirty = 0;
> +
> +	/* Route the actual capture mux from the corrected jack state. */
> +	spec->gen.auto_mic = 1;
> +	snd_hda_gen_mic_autoswitch(codec, jack);
> +	spec->gen.auto_mic = auto_mic;
> +}
> +
> +static void alc295_acer_nitro_hp_automute(struct hda_codec *codec,
> +					  struct hda_jack_callback *jack)
> +{
> +	/* Refresh the reliable HP jack and the Realtek headset mode first. */
> +	alc_update_headset_jack_cb(codec, jack);
> +	alc295_acer_nitro_mic_autoswitch(codec, jack);
> +}
> +
> +static void alc295_fixup_acer_nitro_headset_mode(struct hda_codec *codec,
> +						 const struct hda_fixup *fix,
> +						 int action)
> +{
> +	struct alc_spec *spec = codec->spec;
> +	static const struct hda_pintbl pincfgs[] = {
> +		{ 0x19, 0x03a1103c },
> +		{ }
> +	};
> +
> +	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
> +		snd_hda_apply_pincfgs(codec, pincfgs);
> +		alc_update_coef_idx(codec, 0x45, 0xf << 12 | 1 << 10, 5 << 12);
> +		spec->parse_flags |= HDA_PINCFG_HEADSET_MIC;
> +	}
> +
> +	alc271_hp_gate_mic_jack(codec, fix, action);
> +	alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
> +
> +	if (action == HDA_FIXUP_ACT_PROBE) {
> +		int int_mic_idx = -1, headset_mic_idx = -1;
> +		int i;
> +
> +		for (i = 0; i < spec->gen.input_mux.num_items; i++) {
> +			if (spec->gen.imux_pins[i] == 0x12)
> +				int_mic_idx = i;
> +			else if (spec->gen.imux_pins[i] == 0x19)
> +				headset_mic_idx = i;
> +		}
> +		if (int_mic_idx < 0 || headset_mic_idx < 0) {
> +			codec_warn(codec,
> +				   "failed to find Acer Nitro mic mux entries\n");
> +			return;
> +		}
> +
> +		spec->gen.am_num_entries = 2;
> +		spec->gen.am_entry[0] = (struct automic_entry) {
> +			.pin = 0x12,
> +			.idx = int_mic_idx,
> +		};
> +		spec->gen.am_entry[1] = (struct automic_entry) {
> +			.pin = 0x19,
> +			.idx = headset_mic_idx,
> +		};
> +		spec->gen.hp_automute_hook = alc295_acer_nitro_hp_automute;
> +		spec->gen.mic_autoswitch_hook =
> +			alc295_acer_nitro_mic_autoswitch;
> +	}
> +}
> +
>  static void alc245_fixup_hp_spectre_x360_eu0xxx(struct hda_codec *codec,
>  					  const struct hda_fixup *fix, int action)
>  {
> @@ -4335,6 +4432,7 @@ enum {
>  	ALC287_FIXUP_THINKPAD_I2S_SPK,
>  	ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD,
>  	ALC2XX_FIXUP_HEADSET_MIC,
> +	ALC295_FIXUP_ACER_NITRO_HEADSET_MODE,
>  	ALC289_FIXUP_DELL_CS35L41_SPI_2,
>  	ALC256_FIXUP_ACER_SFG16_MICMUTE_LED,
>  	ALC256_FIXUP_HEADPHONE_AMP_VOL,
> @@ -6854,6 +6952,10 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.type = HDA_FIXUP_FUNC,
>  		.v.func = alc2xx_fixup_headset_mic,
>  	},
> +	[ALC295_FIXUP_ACER_NITRO_HEADSET_MODE] = {
> +		.type = HDA_FIXUP_FUNC,
> +		.v.func = alc295_fixup_acer_nitro_headset_mode,
> +	},
>  	[ALC289_FIXUP_DELL_CS35L41_SPI_2] = {
>  		.type = HDA_FIXUP_FUNC,
>  		.v.func = cs35l41_fixup_spi_two,
> @@ -7177,7 +7279,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
>  	SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
>  	SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
> -	SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57", ALC2XX_FIXUP_HEADSET_MIC),
> +	SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57",
> +		      ALC295_FIXUP_ACER_NITRO_HEADSET_MODE),
>  	SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC287_FIXUP_ACER_MICMUTE_LED),
>  	SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
>  	SND_PCI_QUIRK(0x1025, 0x159e, "Acer Nitro 5 AN515-46", ALC2XX_FIXUP_HEADSET_MIC),
> -- 
> 2.55.0

  reply	other threads:[~2026-09-14 16:24 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04 23:15 Rithvik Vibhu
2026-09-14 16:23 ` Takashi Iwai [this message]
2026-09-15  1:06   ` [PATCH v2 0/2] ALSA: hda: Fix Acer Nitro 5 AN515-57 mic switching Rithvik Vibhu
2026-09-15  1:06     ` [PATCH v2 1/2] ALSA: hda: Allow jack presence to follow another pin Rithvik Vibhu
2026-09-15  1:06     ` [PATCH v2 2/2] ALSA: hda/realtek: Fix Acer Nitro 5 AN515-57 mic switching Rithvik Vibhu

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=871pavol7n.wl-tiwai@suse.de \
    --to=tiwai@suse.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-sound@vger.kernel.org \
    --cc=perex@perex.cz \
    --cc=rithvikvibhu@gmail.com \
    --cc=tiwai@suse.com \
    /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

all inboxes | Powered by JetHome®