All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2] ALSA: hda/realtek: Add inverted LED quirk for HP ZBook 8 G2a
@ 2026-07-13  2:08 Chris Chiu
  2026-07-13 10:09 ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: Chris Chiu @ 2026-07-13  2:08 UTC (permalink / raw)
  To: tiwai, kailang; +Cc: linux-sound, linux-kernel, Chris Chiu

HP ZBook 8 G2a 14 and 16 (SSIDs 0x103c:0x8f94, 0x103c:0x8f95) use
Realtek ALC245 codec with TAS2781 amplifier via I2C. These models
require inverted speaker mute LED handling compared to the existing
ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED quirk.

The existing quirk produces opposite LED behavior: when speaker is
muted, the LED turns off (should be on), and when unmuted, the LED
turns on (should be off). This patch adds a dedicated quirk that
properly handles the inverted LED polarity.

Code flow explanation:
- With HP pin (hp_pin != 0): Uses standard HDA LED framework via
  alc245_fixup_hp_mute_led_coefbit() for full control interface
  support, enabling both manual control and direct hardware updates.
  
- Without HP pin (hp_pin == 0, speaker-only laptops): Registers
  direct vmaster_mute hook (alc245_hp_spk_mute_led_update_inverted)
  to control LED during mute operations, ensuring LED feedback
  without headphone jack detection capability.

Both paths use inverted LED update logic to correct polarity and
maintain backward compatibility with existing systems.

Signed-off-by: Chris Chiu <chris.chiu@canonical.com>
---
 sound/hda/codecs/realtek/alc269.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 56 insertions(+)

diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index b26ed9c1f09f..e04b5adce075a 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -3776,6 +3776,15 @@ static void alc245_hp_spk_mute_led_update(void *private_data, int enabled)
 	alc_update_coef_idx(codec, 0x0b, 0x0c, val);
 }
 
+static void alc245_hp_spk_mute_led_update_inverted(void *private_data, int enabled)
+{
+	struct hda_codec *codec = private_data;
+	unsigned int val;
+
+	val = enabled ? 0x04 : 0x08;	/* inverted: 0x04 off, 0x08 on */
+	alc_update_coef_idx(codec, 0x0b, 0x0c, val);
+}
+
 /* JD2: mute led GPIO3: micmute led */
 static void alc245_tas2781_i2c_hp_fixup_muteled(struct hda_codec *codec,
 					 const struct hda_fixup *fix, int action)
@@ -3804,6 +3813,42 @@ static void alc245_tas2781_i2c_hp_fixup_muteled(struct hda_codec *codec,
 		alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
 	alc285_fixup_hp_coef_micmute_led(codec, fix, action);
 }
+
+/* Inverted LED version for HP ZBook 8 G2a models (SSIDs 0x8f94, 0x8f95)
+ * This fixup handles systems where the speaker mute LED polarity is reversed
+/* Inverted LED quirk for HP ZBook 8 G2a (SSIDs 0x8f94, 0x8f95)
+ * Speaker mute LED polarity is reversed vs standard behavior.
+ * Code flow depends on HP pin detection availability:
+ * - With HP pin: Uses HDA LED framework for full control support
+ * - Without HP pin: Registers vmaster_mute hook for direct control
+ */
+static void alc245_tas2781_i2c_hp_fixup_muteled_inverted(struct hda_codec *codec,
+const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	hda_nid_t hp_pin = alc_get_hp_pin(spec);
+	static const hda_nid_t conn[] = { 0x02 };
+
+	switch (action) {
+	case HDA_FIXUP_ACT_PRE_PROBE:
+		if (!hp_pin) {
+			/* Speaker-only config without HP pin detection */
+			spec->gen.vmaster_mute.hook = alc245_hp_spk_mute_led_update_inverted;
+			spec->gen.vmaster_mute_led = 1;
+		}
+		spec->gen.auto_mute_via_amp = 1;
+		snd_hda_override_conn_list(codec, 0x17, ARRAY_SIZE(conn), conn);
+		break;
+	case HDA_FIXUP_ACT_INIT:
+		if (!hp_pin)
+			alc245_hp_spk_mute_led_update_inverted(codec, !spec->gen.master_mute);
+		break;
+	}
+
+	tas2781_fixup_txnw_i2c(codec, fix, action);
+	if (hp_pin)
+		alc245_fixup_hp_mute_led_coefbit(codec, fix, action);
+	alc285_fixup_hp_coef_micmute_led(codec, fix, action);
+}
 /*
  * Clear COEF 0x0d (PCBEEP passthrough) bit 0x40 where BIOS sets it wrongly
  * at PM resume
@@ -4164,6 +4209,7 @@ enum {
 	ALC256_FIXUP_VAIO_RPL_MIC_NO_PRESENCE,
 	ALC245_FIXUP_HP_TAS2781_SPI_MUTE_LED,
 	ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED,
+	ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED,
 	ALC288_FIXUP_SURFACE_SWAP_DACS,
 	ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO,
 	ALC233_FIXUP_LENOVO_GPIO2_MIC_HOTKEY,
@@ -4481,6 +4527,10 @@ static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chain_before = true,
 		.chain_to = ALC269_FIXUP_HEADSET_MIC,
+	},
+	[ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc245_tas2781_i2c_hp_fixup_muteled_inverted,
 	},
 	[ALC288_FIXUP_SURFACE_SWAP_DACS] = {
 		.type = HDA_FIXUP_FUNC,
@@ -4785,6 +4835,8 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x103c, 0x8e86, "HP", ALC285_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x8ec0, "HP", ALC285_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x8f94, "HP", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
+	SND_PCI_QUIRK(0x103c, 0x8f95, "HP", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED_INVERTED),
 	SND_PCI_QUIRK(0x103c, 0x91c6, "HP", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_GPIO),
 	SND_PCI_QUIRK(0x103c, 0x221c, "HP", ALC285_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x1080, "ASUS K53UT", ALC269_FIXUP_SSID_IGNORED),

^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-07-14  5:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-13  2:08 [PATCH v2] ALSA: hda/realtek: Add inverted LED quirk for HP ZBook 8 G2a Chris Chiu
2026-07-13 10:09 ` Takashi Iwai
2026-07-14  1:55   ` Chris Chiu
2026-07-14  5:33     ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.