diff mbox series

[v2] ALSA: hda: Support for Ideapad hotkey mute LEDs

Message ID 20241224083316.20222-1-xy-jackie@139.com (mailing list archive)
State New
Headers show
Series [v2] ALSA: hda: Support for Ideapad hotkey mute LEDs | expand

Commit Message

Jackie Dong Dec. 24, 2024, 8:33 a.m. UTC
New ideapad helper file with support for handling FN key mute LEDs.
Update conexant and realtec codec to add LED support.

Suggested-by: Mark Pearson <mpearson-lenovo@squebb.ca>
Signed-off-by: Jackie Dong  <xy-jackie@139.com>
---
Changes in v2:
 - Add a new enum CXT_FIXUP_LENOVO_XPAD_ACPI and define it as an entry in patch_conexant.c
 - Add a new enum ALC269_FIXUP_LENOVO_XPAD_ACPI and define it as an entry in patch_realtek.c

 sound/pci/hda/ideapad_hotkey_led_helper.c | 36 +++++++++++++++++++++++
 sound/pci/hda/patch_conexant.c            | 13 +++++++-
 sound/pci/hda/patch_realtek.c             | 20 ++++++++++++-
 3 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 sound/pci/hda/ideapad_hotkey_led_helper.c

Comments

Takashi Iwai Dec. 29, 2024, 9:04 a.m. UTC | #1
On Tue, 24 Dec 2024 09:33:16 +0100,
Jackie Dong wrote:
> 
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -6934,6 +6934,16 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
>  	hda_fixup_thinkpad_acpi(codec, fix, action);
>  }
>  
> +/* for hda_fixup_ideapad_acpi() */
> +#include "ideapad_hotkey_led_helper.c"
> +
> +static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
> +				   const struct hda_fixup *fix, int action)
> +{
> +	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
> +	hda_fixup_ideapad_acpi(codec, fix, action);
> +}

So this unconditionally call alc_fixup_no_shutup(), and this
introduces another behavior to the existing entry -- i.e. there is a
chance of breakage.

If we want to be very conservative, this call should be limited to
Ideapad.


thanks,

Takashi
Jackie EG1 Dong Dec. 30, 2024, 12:33 a.m. UTC | #2
> On Tue, 24 Dec 2024 09:33:16 +0100,
 > Jackie Dong wrote:
 >>
 >> --- a/sound/pci/hda/patch_realtek.c
 >> +++ b/sound/pci/hda/patch_realtek.c
 >> @@ -6934,6 +6934,16 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
 >>   	hda_fixup_thinkpad_acpi(codec, fix, action);
 >>   }
 >>
 >> +/* for hda_fixup_ideapad_acpi() */
 >> +#include "ideapad_hotkey_led_helper.c"
 >> +
 >> +static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
 >> +				   const struct hda_fixup *fix, int action)
 >> +{
 >> +	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
 >> +	hda_fixup_ideapad_acpi(codec, fix, action);
 >> +}
 >
 > So this unconditionally call alc_fixup_no_shutup(), and this  > introduces another behavior to the existing entry -- i.e. there is a  > chance of breakage.
 >
 > If we want to be very conservative, this call should be limited to  > Ideapad.
 > For alc_fixup_no_shutup(codec, fix, action),
 I want to keep same behavior with alc_fixup_thinkpad_apci() and alc_fixup_idea_acpi() for one sound card. So, I add alc_fixup_no_shutup() in alc_fixup_ideapad_acpi().
----------Related source code of patch_reatek.c are FYR as below.
static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
                                     const struct hda_fixup *fix, int
action)
{
         alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
         hda_fixup_thinkpad_acpi(codec, fix, action); }

/* for hda_fixup_ideapad_acpi() */
#include "ideapad_hotkey_led_helper.c"

static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
                                    const struct hda_fixup *fix, int action) {
         alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
         hda_fixup_ideapad_acpi(codec, fix, action);
}
Thanks, 
Jackie
> thanks, 
>  
> Takashi  
>
Takashi Iwai Jan. 3, 2025, 3:17 p.m. UTC | #3
On Mon, 30 Dec 2024 01:33:01 +0100,
Jackie EG1 Dong wrote:
> 
> > On Tue, 24 Dec 2024 09:33:16 +0100,
>  > Jackie Dong wrote:
>  >>
>  >> --- a/sound/pci/hda/patch_realtek.c
>  >> +++ b/sound/pci/hda/patch_realtek.c
>  >> @@ -6934,6 +6934,16 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
>  >>   	hda_fixup_thinkpad_acpi(codec, fix, action);
>  >>   }
>  >>
>  >> +/* for hda_fixup_ideapad_acpi() */
>  >> +#include "ideapad_hotkey_led_helper.c"
>  >> +
>  >> +static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
>  >> +				   const struct hda_fixup *fix, int action)
>  >> +{
>  >> +	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>  >> +	hda_fixup_ideapad_acpi(codec, fix, action);
>  >> +}
>  >
>  > So this unconditionally call alc_fixup_no_shutup(), and this  > introduces another behavior to the existing entry -- i.e. there is a  > chance of breakage.
>  >
>  > If we want to be very conservative, this call should be limited to  > Ideapad.
>  > For alc_fixup_no_shutup(codec, fix, action),
>  I want to keep same behavior with alc_fixup_thinkpad_apci() and alc_fixup_idea_acpi() for one sound card. So, I add alc_fixup_no_shutup() in alc_fixup_ideapad_acpi().
> ----------Related source code of patch_reatek.c are FYR as below.
> static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
>                                      const struct hda_fixup *fix, int
> action)
> {
>          alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>          hda_fixup_thinkpad_acpi(codec, fix, action); }
> 
> /* for hda_fixup_ideapad_acpi() */
> #include "ideapad_hotkey_led_helper.c"
> 
> static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
>                                     const struct hda_fixup *fix, int action) {
>          alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>          hda_fixup_ideapad_acpi(codec, fix, action);
> }

Oh yeah, but then it can be bad in other way round; the chain call of
alc_fixup_thinkpad_acpi() contains alc_fixup_no_shutup() and the
alc_fixup_ideadpad_acpi() also contains alc_fixup_no_shutup().
That is, alc_fixup_no_shutup() will be called twice for Thinkpad.

Instead, you can change like:

--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6925,11 +6925,16 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
-static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
-				    const struct hda_fixup *fix, int action)
+/* for hda_fixup_ideapad_acpi() */
+#include "ideapad_hotkey_led_helper.c"
+
+/* generic fixup for both Lenovo Thinkpad and Ideapad */
+static void alc_fixup_xpad_acpi(struct hda_codec *codec,
+				const struct hda_fixup *fix, int action)
 {
 	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
 	hda_fixup_thinkpad_acpi(codec, fix, action);
+	hda_fixup_ideapad_acpi(codec, fix, action);
 }
 
 /* Fixup for Lenovo Legion 15IMHg05 speaker output on headset removal. */
@@ -8321,7 +8326,7 @@ static const struct hda_fixup alc269_fixups[] = {
 	},
 	[ALC269_FIXUP_THINKPAD_ACPI] = {
 		.type = HDA_FIXUP_FUNC,
-		.v.func = alc_fixup_thinkpad_acpi,
+		.v.func = alc_fixup_xpad_acpi,
 		.chained = true,
 		.chain_id = ALC269_FIXUP_SKU_IGNORE,
 	},

Since hda_fixup_ideapad_acpi() is NOP except for Ideapad, this
shouldn't break other models, while it covers the Ideadpad now.


thanks,

Takashi
Jackie Dong Jan. 6, 2025, 12:49 p.m. UTC | #4
On 2025/1/3 23:17, Takashi Iwai wrote:
> On Mon, 30 Dec 2024 01:33:01 +0100,
> Jackie EG1 Dong wrote:
>>
>>> On Tue, 24 Dec 2024 09:33:16 +0100,
>>   > Jackie Dong wrote:
>>   >>
>>   >> --- a/sound/pci/hda/patch_realtek.c
>>   >> +++ b/sound/pci/hda/patch_realtek.c
>>   >> @@ -6934,6 +6934,16 @@ static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
>>   >>   	hda_fixup_thinkpad_acpi(codec, fix, action);
>>   >>   }
>>   >>
>>   >> +/* for hda_fixup_ideapad_acpi() */
>>   >> +#include "ideapad_hotkey_led_helper.c"
>>   >> +
>>   >> +static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
>>   >> +				   const struct hda_fixup *fix, int action)
>>   >> +{
>>   >> +	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>>   >> +	hda_fixup_ideapad_acpi(codec, fix, action);
>>   >> +}
>>   >
>>   > So this unconditionally call alc_fixup_no_shutup(), and this  > introduces another behavior to the existing entry -- i.e. there is a  > chance of breakage.
>>   >
>>   > If we want to be very conservative, this call should be limited to  > Ideapad.
>>   > For alc_fixup_no_shutup(codec, fix, action),
>>   I want to keep same behavior with alc_fixup_thinkpad_apci() and alc_fixup_idea_acpi() for one sound card. So, I add alc_fixup_no_shutup() in alc_fixup_ideapad_acpi().
>> ----------Related source code of patch_reatek.c are FYR as below.
>> static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
>>                                       const struct hda_fixup *fix, int
>> action)
>> {
>>           alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>>           hda_fixup_thinkpad_acpi(codec, fix, action); }
>>
>> /* for hda_fixup_ideapad_acpi() */
>> #include "ideapad_hotkey_led_helper.c"
>>
>> static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
>>                                      const struct hda_fixup *fix, int action) {
>>           alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>>           hda_fixup_ideapad_acpi(codec, fix, action);
>> }
> 
> Oh yeah, but then it can be bad in other way round; the chain call of
> alc_fixup_thinkpad_acpi() contains alc_fixup_no_shutup() and the
> alc_fixup_ideadpad_acpi() also contains alc_fixup_no_shutup().
> That is, alc_fixup_no_shutup() will be called twice for Thinkpad.
> 
Many thanks to Takashi for your detail comments  and sample code, I 
understand it now.

I'll check the logic of the code and update the patch later.

Best Regards,

Jackie Dong
> Instead, you can change like:
> 
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -6925,11 +6925,16 @@ static void alc285_fixup_hp_envy_x360(struct hda_codec *codec,
>   /* for hda_fixup_thinkpad_acpi() */
>   #include "thinkpad_helper.c"
>   
> -static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
> -				    const struct hda_fixup *fix, int action)
> +/* for hda_fixup_ideapad_acpi() */
> +#include "ideapad_hotkey_led_helper.c"
> +
> +/* generic fixup for both Lenovo Thinkpad and Ideapad */
> +static void alc_fixup_xpad_acpi(struct hda_codec *codec,
> +				const struct hda_fixup *fix, int action)
>   {
>   	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
>   	hda_fixup_thinkpad_acpi(codec, fix, action);
> +	hda_fixup_ideapad_acpi(codec, fix, action);
>   }
>   
>   /* Fixup for Lenovo Legion 15IMHg05 speaker output on headset removal. */
> @@ -8321,7 +8326,7 @@ static const struct hda_fixup alc269_fixups[] = {
>   	},
>   	[ALC269_FIXUP_THINKPAD_ACPI] = {
>   		.type = HDA_FIXUP_FUNC,
> -		.v.func = alc_fixup_thinkpad_acpi,
> +		.v.func = alc_fixup_xpad_acpi,
>   		.chained = true,
>   		.chain_id = ALC269_FIXUP_SKU_IGNORE,
>   	},
> 
> Since hda_fixup_ideapad_acpi() is NOP except for Ideapad, this
> shouldn't break other models, while it covers the Ideadpad now.
> 
> 
> thanks,
> 
> Takashi
diff mbox series

Patch

diff --git a/sound/pci/hda/ideapad_hotkey_led_helper.c b/sound/pci/hda/ideapad_hotkey_led_helper.c
new file mode 100644
index 000000000000..c10d97964d49
--- /dev/null
+++ b/sound/pci/hda/ideapad_hotkey_led_helper.c
@@ -0,0 +1,36 @@ 
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Ideapad helper functions for Lenovo Ideapad LED control,
+ * It should be included from codec driver.
+ */
+
+#if IS_ENABLED(CONFIG_IDEAPAD_LAPTOP)
+
+#include <linux/acpi.h>
+#include <linux/leds.h>
+
+static bool is_ideapad(struct hda_codec *codec)
+{
+	return (codec->core.subsystem_id >> 16 == 0x17aa) &&
+	       (acpi_dev_found("LHK2019") || acpi_dev_found("VPC2004"));
+}
+
+static void hda_fixup_ideapad_acpi(struct hda_codec *codec,
+				   const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+		if (!is_ideapad(codec))
+			return;
+		snd_hda_gen_add_mute_led_cdev(codec, NULL);
+		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
+	}
+}
+
+#else /* CONFIG_IDEAPAD_LAPTOP */
+
+static void hda_fixup_ideapad_acpi(struct hda_codec *codec,
+				   const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_IDEAPAD_LAPTOP */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 538c37a78a56..4985e72b9094 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -291,6 +291,7 @@  enum {
 	CXT_FIXUP_GPIO1,
 	CXT_FIXUP_ASPIRE_DMIC,
 	CXT_FIXUP_THINKPAD_ACPI,
+	CXT_FIXUP_LENOVO_XPAD_ACPI,
 	CXT_FIXUP_OLPC_XO,
 	CXT_FIXUP_CAP_MIX_AMP,
 	CXT_FIXUP_TOSHIBA_P105,
@@ -313,6 +314,9 @@  enum {
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
+/* for hda_fixup_ideapad_acpi() */
+#include "ideapad_hotkey_led_helper.c"
+
 static void cxt_fixup_stereo_dmic(struct hda_codec *codec,
 				  const struct hda_fixup *fix, int action)
 {
@@ -928,6 +932,12 @@  static const struct hda_fixup cxt_fixups[] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = hda_fixup_thinkpad_acpi,
 	},
+	[CXT_FIXUP_LENOVO_XPAD_ACPI] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = hda_fixup_ideapad_acpi,
+		.chained = true,
+		.chain_id = CXT_FIXUP_THINKPAD_ACPI,
+	},
 	[CXT_FIXUP_OLPC_XO] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = cxt_fixup_olpc_xo,
@@ -1119,7 +1129,7 @@  static const struct hda_quirk cxt5066_fixups[] = {
 	SND_PCI_QUIRK(0x17aa, 0x3977, "Lenovo IdeaPad U310", CXT_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo G50-70", CXT_FIXUP_STEREO_DMIC),
 	SND_PCI_QUIRK(0x17aa, 0x397b, "Lenovo S205", CXT_FIXUP_STEREO_DMIC),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", CXT_FIXUP_THINKPAD_ACPI),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad/Ideapad", CXT_FIXUP_LENOVO_XPAD_ACPI),
 	SND_PCI_QUIRK(0x1c06, 0x2011, "Lemote A1004", CXT_PINCFG_LEMOTE_A1004),
 	SND_PCI_QUIRK(0x1c06, 0x2012, "Lemote A1205", CXT_PINCFG_LEMOTE_A1205),
 	HDA_CODEC_QUIRK(0x2782, 0x12c3, "Sirius Gen1", CXT_PINCFG_TOP_SPEAKER),
@@ -1133,6 +1143,7 @@  static const struct hda_model_fixup cxt5066_fixup_models[] = {
 	{ .id = CXT_FIXUP_HEADPHONE_MIC_PIN, .name = "headphone-mic-pin" },
 	{ .id = CXT_PINCFG_LENOVO_TP410, .name = "tp410" },
 	{ .id = CXT_FIXUP_THINKPAD_ACPI, .name = "thinkpad" },
+	{ .id = CXT_FIXUP_LENOVO_XPAD_ACPI, .name = "thinkpad-ideapad" },
 	{ .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" },
 	{ .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" },
 	{ .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" },
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 61ba5dc35b8b..5f9927401322 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6934,6 +6934,16 @@  static void alc_fixup_thinkpad_acpi(struct hda_codec *codec,
 	hda_fixup_thinkpad_acpi(codec, fix, action);
 }
 
+/* for hda_fixup_ideapad_acpi() */
+#include "ideapad_hotkey_led_helper.c"
+
+static void alc_fixup_ideapad_acpi(struct hda_codec *codec,
+				   const struct hda_fixup *fix, int action)
+{
+	alc_fixup_no_shutup(codec, fix, action); /* reduce click noise */
+	hda_fixup_ideapad_acpi(codec, fix, action);
+}
+
 /* Fixup for Lenovo Legion 15IMHg05 speaker output on headset removal. */
 static void alc287_fixup_legion_15imhg05_speakers(struct hda_codec *codec,
 						  const struct hda_fixup *fix,
@@ -7556,6 +7566,7 @@  enum {
 	ALC290_FIXUP_SUBWOOFER,
 	ALC290_FIXUP_SUBWOOFER_HSJACK,
 	ALC269_FIXUP_THINKPAD_ACPI,
+	ALC269_FIXUP_LENOVO_XPAD_ACPI,
 	ALC269_FIXUP_DMIC_THINKPAD_ACPI,
 	ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
 	ALC269VC_FIXUP_INFINIX_Y4_MAX,
@@ -8327,6 +8338,12 @@  static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chain_id = ALC269_FIXUP_SKU_IGNORE,
 	},
+	[ALC269_FIXUP_LENOVO_XPAD_ACPI] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_ideapad_acpi,
+		.chained = true,
+		.chain_id = ALC269_FIXUP_THINKPAD_ACPI,
+	},
 	[ALC269_FIXUP_DMIC_THINKPAD_ACPI] = {
 		.type = HDA_FIXUP_FUNC,
 		.v.func = alc_fixup_inv_dmic,
@@ -11065,7 +11082,7 @@  static const struct hda_quirk alc269_fixup_vendor_tbl[] = {
 	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
 	SND_PCI_QUIRK_VENDOR(0x103c, "HP", ALC269_FIXUP_HP_MUTE_LED),
 	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
-	SND_PCI_QUIRK_VENDOR(0x17aa, "Thinkpad", ALC269_FIXUP_THINKPAD_ACPI),
+	SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo XPAD", ALC269_FIXUP_LENOVO_XPAD_ACPI),
 	SND_PCI_QUIRK_VENDOR(0x19e5, "Huawei Matebook", ALC255_FIXUP_MIC_MUTE_LED),
 	{}
 };
@@ -11130,6 +11147,7 @@  static const struct hda_model_fixup alc269_fixup_models[] = {
 	{.id = ALC290_FIXUP_MONO_SPEAKERS_HSJACK, .name = "mono-speakers"},
 	{.id = ALC290_FIXUP_SUBWOOFER_HSJACK, .name = "alc290-subwoofer"},
 	{.id = ALC269_FIXUP_THINKPAD_ACPI, .name = "thinkpad"},
+	{.id = ALC269_FIXUP_LENOVO_XPAD_ACPI, .name = "lenovo xpad led"},
 	{.id = ALC269_FIXUP_DMIC_THINKPAD_ACPI, .name = "dmic-thinkpad"},
 	{.id = ALC255_FIXUP_ACER_MIC_NO_PRESENCE, .name = "alc255-acer"},
 	{.id = ALC255_FIXUP_ASUS_MIC_NO_PRESENCE, .name = "alc255-asus"},