All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently
@ 2020-06-18 11:08 Takashi Iwai
  2020-06-18 11:08 ` [PATCH 01/13] ALSA: hda: generic: Always call led-trigger for mic mute LED Takashi Iwai
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Hi,

this is a patch set inspired by the recent patch Kai-Heng posted about
the HD-audio mic-mute LED control.  Currently HD-audio driver deals
with the mute and mic-mute LED in several different ways: primarily
with the direct callback of vmaster hook and capture sync hook, while
another with the LED class device binding.  The latter has been used
for binding with the platform device LEDs like Thinkpad, Dell,
Huawei.  And, yet, recently we added our own LED classdev for the
mic-mute LED on some HP systems although they are controlled directly
with the callback; it's exposed, however, for the DMIC that is
governed by a different ASoC driver.

This patch set is an attempt to sort out and make them consistent:
namely, 
* All LEDs are now controlled via LED class device
* The generic driver provides helper functions to easily build up the
  LED class dev and the relevant mixer controls
* Conversion of the existing framework and clean ups

The patches are lightly tested in my side with a couple of machines
and also through hda-emu tests.  Some devices receive new kcontrols
for the mute LED behavior (that have been missing so far), but
anything else look good though my tests.


thanks,

Takashi

===

Takashi Iwai (13):
  ALSA: hda: generic: Always call led-trigger for mic mute LED
  ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev
  ALSA: hda/realtek: Convert to cdev-variant of mic-mute LED controls
  ALSA: hda/conexant: Convert to cdev-variant of mic-mute LED controls
  ALSA: hda/sigmatel: Convert to cdev-variant of mic-mute LED controls
  ALSA: hda: generic: Drop unused snd_hda_gen_fixup_micmute_led()
  ALSA: hda: generic: Drop the old mic-mute LED hook
  ALSA: hda: generic: Add vmaster mute LED helper
  ALSA: hda/realtek: Use the new vmaster mute LED helper
  ALSA: hda/conexant: Use the new vmaster mute LED helper
  ALSA: hda/sigmatel: Use the new vmaster mute LED helper
  ALSA: hda/realtek: Unify LED helper code
  ALSA: hda: Let LED cdev handling suspend/resume

 sound/pci/hda/Kconfig           |   9 ++
 sound/pci/hda/hda_generic.c     | 134 ++++++++++++++++--------
 sound/pci/hda/hda_generic.h     |  13 ++-
 sound/pci/hda/patch_conexant.c  |  47 ++++-----
 sound/pci/hda/patch_realtek.c   | 220 +++++++++++++++++++---------------------
 sound/pci/hda/patch_sigmatel.c  |  22 ++--
 sound/pci/hda/thinkpad_helper.c |  19 +---
 7 files changed, 248 insertions(+), 216 deletions(-)

-- 
2.16.4


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

* [PATCH 01/13] ALSA: hda: generic: Always call led-trigger for mic mute LED
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 02/13] ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev Takashi Iwai
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Instead of adding a special hook to trigger the mic-mute LED device,
call it always from the common callback function.  It won't hurt even
if no corresponding led cdev is present.

This is basically a preliminary change for the later patches to
convert the all mic-mute LED handling to LED class cdev.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_generic.c | 18 +++++-------------
 1 file changed, 5 insertions(+), 13 deletions(-)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index f4e9d9445e18..c95ccffbd0cf 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3923,6 +3923,10 @@ static void call_micmute_led_update(struct hda_codec *codec)
 	spec->micmute_led.led_value = val;
 	if (spec->micmute_led.update)
 		spec->micmute_led.update(codec);
+#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
+	ledtrig_audio_set(LED_AUDIO_MICMUTE,
+			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
+#endif
 }
 
 static void update_micmute_led(struct hda_codec *codec,
@@ -4023,16 +4027,6 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led);
 
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
-static void call_ledtrig_micmute(struct hda_codec *codec)
-{
-	struct hda_gen_spec *spec = codec->spec;
-
-	ledtrig_audio_set(LED_AUDIO_MICMUTE,
-			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
-}
-#endif
-
 /**
  * snd_hda_gen_fixup_micmute_led - A fixup for mic-mute LED trigger
  *
@@ -4051,10 +4045,8 @@ static void call_ledtrig_micmute(struct hda_codec *codec)
 void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action)
 {
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
 	if (action == HDA_FIXUP_ACT_PROBE)
-		snd_hda_gen_add_micmute_led(codec, call_ledtrig_micmute);
-#endif
+		snd_hda_gen_add_micmute_led(codec, NULL);
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_fixup_micmute_led);
 
-- 
2.16.4


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

* [PATCH 02/13] ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
  2020-06-18 11:08 ` [PATCH 01/13] ALSA: hda: generic: Always call led-trigger for mic mute LED Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 03/13] ALSA: hda/realtek: Convert to cdev-variant of mic-mute LED controls Takashi Iwai
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

A new helper, snd_hda_gen_add_micmute_led_cdev(), is introduced here
for creating a LED classdev and setting up the hook to the capture
control for controlling the mic-mute LED to follow the capture switch
change.  This will replace the existing users of
snd_hda_gen_add_micmute_led() in later patches.

Also, introduce a new kconfig CONFIG_SND_HDA_GENERIC_LEDS, to indicate
the usage of mute / mic-mute LED helpers.  It's selected by the codec
drivers (Realtek, Conexant and Sigmatel), while it selects the
necessary LED class dependencies.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/Kconfig         |  9 +++++++++
 sound/pci/hda/hda_generic.c   | 47 +++++++++++++++++++++++++++++++++++++++++--
 sound/pci/hda/hda_generic.h   |  5 +++++
 sound/pci/hda/patch_realtek.c | 30 +--------------------------
 4 files changed, 60 insertions(+), 31 deletions(-)

diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index 7ba542e45a3d..3f9abdaef7f5 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -8,6 +8,9 @@ config SND_HDA
 	select SND_JACK
 	select SND_HDA_CORE
 
+config SND_HDA_GENERIC_LEDS
+       bool
+
 config SND_HDA_INTEL
 	tristate "HD Audio PCI"
 	depends on SND_PCI
@@ -91,6 +94,7 @@ config SND_HDA_PATCH_LOADER
 config SND_HDA_CODEC_REALTEK
 	tristate "Build Realtek HD-audio codec support"
 	select SND_HDA_GENERIC
+	select SND_HDA_GENERIC_LEDS
 	help
 	  Say Y or M here to include Realtek HD-audio codec support in
 	  snd-hda-intel driver, such as ALC880.
@@ -111,6 +115,7 @@ comment "Set to Y if you want auto-loading the codec driver"
 config SND_HDA_CODEC_SIGMATEL
 	tristate "Build IDT/Sigmatel HD-audio codec support"
 	select SND_HDA_GENERIC
+	select SND_HDA_GENERIC_LEDS
 	help
 	  Say Y or M here to include IDT (Sigmatel) HD-audio codec support in
 	  snd-hda-intel driver, such as STAC9200.
@@ -155,6 +160,7 @@ comment "Set to Y if you want auto-loading the codec driver"
 config SND_HDA_CODEC_CONEXANT
 	tristate "Build Conexant HD-audio codec support"
 	select SND_HDA_GENERIC
+	select SND_HDA_GENERIC_LEDS
 	help
 	  Say Y or M here to include Conexant HD-audio codec support in
 	  snd-hda-intel driver, such as CX20549.
@@ -215,6 +221,9 @@ comment "Set to Y if you want auto-loading the codec driver"
 
 config SND_HDA_GENERIC
 	tristate "Enable generic HD-audio codec parser"
+	select LEDS_CLASS if SND_HDA_GENERIC_LEDS
+	select LEDS_TRIGGERS if SND_HDA_GENERIC_LEDS
+	select LEDS_TRIGGER_AUDIO if SND_HDA_GENERIC_LEDS
 	help
 	  Say Y or M here to enable the generic HD-audio codec parser
 	  in snd-hda-intel driver.
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c95ccffbd0cf..419cfbd0dc5c 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3887,6 +3887,7 @@ static int parse_mic_boost(struct hda_codec *codec)
 	return 0;
 }
 
+#ifdef CONFIG_SND_HDA_GENERIC_LEDS
 /*
  * mic mute LED hook helpers
  */
@@ -3923,10 +3924,8 @@ static void call_micmute_led_update(struct hda_codec *codec)
 	spec->micmute_led.led_value = val;
 	if (spec->micmute_led.update)
 		spec->micmute_led.update(codec);
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
 	ledtrig_audio_set(LED_AUDIO_MICMUTE,
 			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
-#endif
 }
 
 static void update_micmute_led(struct hda_codec *codec,
@@ -4050,6 +4049,50 @@ void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_fixup_micmute_led);
 
+/**
+ * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
+ * @codec: the HDA codec
+ * @callback: the callback for LED classdev brightness_set_blocking
+ *
+ * Called from the codec drivers for offering the mic mute LED controls.
+ * This creates a LED classdev and sets up the cap_sync_hook that is called at
+ * each time when the capture mixer switch changes.
+ *
+ * When NULL is passed to @callback, no classdev is created but only the
+ * LED-trigger is set up.
+ *
+ * Returns 0 or a negative error.
+ */
+int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
+				     int (*callback)(struct led_classdev *,
+						     enum led_brightness))
+{
+	int err;
+	struct led_classdev *cdev;
+
+	if (callback) {
+		cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
+		if (!cdev)
+			return -ENOMEM;
+
+		cdev->name = "hda::micmute";
+		cdev->max_brightness = 1;
+		cdev->default_trigger = "audio-micmute";
+		cdev->brightness_set_blocking = callback;
+		cdev->brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
+
+		err = devm_led_classdev_register(&codec->core.dev, cdev);
+		if (err) {
+			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
+			return err;
+		}
+	}
+
+	return snd_hda_gen_add_micmute_led(codec, NULL);
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
+#endif /* CONFIG_SND_HDA_GENERIC_LEDS */
+
 /*
  * parse digital I/Os and set up NIDs in BIOS auto-parse mode
  */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index fb9f1a90238b..f56bc8da20b2 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -8,6 +8,8 @@
 #ifndef __SOUND_HDA_GENERIC_H
 #define __SOUND_HDA_GENERIC_H
 
+#include <linux/leds.h>
+
 /* table entry for multi-io paths */
 struct hda_multi_io {
 	hda_nid_t pin;		/* multi-io widget pin NID */
@@ -357,5 +359,8 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
 				void (*hook)(struct hda_codec *));
 void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
 				   const struct hda_fixup *fix, int action);
+int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
+				     int (*callback)(struct led_classdev *,
+						     enum led_brightness));
 
 #endif /* __SOUND_HDA_GENERIC_H */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6d73f8beadb6..1d0fe9a0983f 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4100,16 +4100,6 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled)
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
-static void alc_gpio_micmute_update(struct hda_codec *codec)
-{
-	struct alc_spec *spec = codec->spec;
-
-	alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
-			    spec->micmute_led_polarity,
-			    spec->gen.micmute_led.led_value);
-}
-
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
 static int micmute_led_set(struct led_classdev *led_cdev,
 			   enum led_brightness brightness)
 {
@@ -4121,14 +4111,6 @@ static int micmute_led_set(struct led_classdev *led_cdev,
 	return 0;
 }
 
-static struct led_classdev micmute_led_cdev = {
-	.name = "hda::micmute",
-	.max_brightness = 1,
-	.brightness_set_blocking = micmute_led_set,
-	.default_trigger = "audio-micmute",
-};
-#endif
-
 /* setup mute and mic-mute GPIO bits, add hooks appropriately */
 static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
 				  int action,
@@ -4136,9 +4118,6 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
 				  unsigned int micmute_mask)
 {
 	struct alc_spec *spec = codec->spec;
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
-	int err;
-#endif
 
 	alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
 
@@ -4150,14 +4129,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
 	}
 	if (micmute_mask) {
 		spec->gpio_mic_led_mask = micmute_mask;
-		snd_hda_gen_add_micmute_led(codec, alc_gpio_micmute_update);
-
-#if IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
-		micmute_led_cdev.brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
-		err = devm_led_classdev_register(&codec->core.dev, &micmute_led_cdev);
-		if (err)
-			codec_warn(codec, "failed to register micmute LED\n");
-#endif
+		snd_hda_gen_add_micmute_led_cdev(codec, micmute_led_set);
 	}
 }
 
-- 
2.16.4


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

* [PATCH 03/13] ALSA: hda/realtek: Convert to cdev-variant of mic-mute LED controls
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
  2020-06-18 11:08 ` [PATCH 01/13] ALSA: hda: generic: Always call led-trigger for mic mute LED Takashi Iwai
  2020-06-18 11:08 ` [PATCH 02/13] ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 04/13] ALSA: hda/conexant: " Takashi Iwai
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

This patch converts the remaining user of
snd_hda_gen_add_micmute_led() in Realtek codec driver into the new
snd_hda_gen_add_micmute_led_cdev().

The Thinkpad helper code is updated accordingly, too.

Also, the usage of snd_hda_gen_fixup_micmute_led() is replaced with
either the local alc_fixup_micmute_led() or the explicit call of
snd_hda_gen_add_micmute_led_cdev() with NULL callback.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c   | 39 ++++++++++++++++++++++++++-------------
 sound/pci/hda/thinkpad_helper.c |  2 +-
 2 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 1d0fe9a0983f..6831587fc4d6 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -287,6 +287,13 @@ static void alc_fixup_gpio4(struct hda_codec *codec,
 	alc_fixup_gpio(codec, action, 0x04);
 }
 
+static void alc_fixup_micmute_led(struct hda_codec *codec,
+				  const struct hda_fixup *fix, int action)
+{
+	if (action == HDA_FIXUP_ACT_PROBE)
+		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
+}
+
 /*
  * Fix hardware PLL issue
  * On some codecs, the analog PLL gating control must be off while
@@ -4155,21 +4162,24 @@ static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
 	alc_fixup_hp_gpio_led(codec, action, 0x02, 0x20);
 }
 
-/* turn on/off mic-mute LED per capture hook */
-static void alc_cap_micmute_update(struct hda_codec *codec)
+/* turn on/off mic-mute LED per capture hook via VREF change */
+static int vref_micmute_led_set(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
 {
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 	unsigned int pinval;
 
 	if (!spec->cap_mute_led_nid)
-		return;
+		return 0;
 	pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
 	pinval &= ~AC_PINCTL_VREFEN;
-	if (spec->gen.micmute_led.led_value)
+	if (brightness)
 		pinval |= AC_PINCTL_VREF_80;
 	else
 		pinval |= AC_PINCTL_VREF_HIZ;
 	snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
+	return 0;
 }
 
 static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
@@ -4185,7 +4195,7 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
 		spec->gpio_mask |= 0x10;
 		spec->gpio_dir |= 0x10;
 		spec->cap_mute_led_nid = 0x18;
-		snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 		codec->power_filter = led_power_filter;
 	}
 }
@@ -4198,7 +4208,7 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
 	alc_fixup_hp_gpio_led(codec, action, 0x08, 0);
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->cap_mute_led_nid = 0x18;
-		snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 		codec->power_filter = led_power_filter;
 	}
 }
@@ -4254,16 +4264,19 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 }
 
 /* turn on/off mic-mute LED per capture hook by coef bit */
-static void alc_hp_cap_micmute_update(struct hda_codec *codec)
+static int coef_micmute_led_set(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
 {
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 
-	if (spec->gen.micmute_led.led_value)
+	if (brightness)
 		alc_update_coef_idx(codec, spec->mic_led_coef_idx,
 			spec->mic_led_coefbit_mask, spec->mic_led_coefbit_on);
 	else
 		alc_update_coef_idx(codec, spec->mic_led_coef_idx,
 			spec->mic_led_coefbit_mask, spec->mic_led_coefbit_off);
+	return 0;
 }
 
 static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
@@ -4276,7 +4289,7 @@ static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 		spec->mic_led_coefbit_mask = 1<<13;
 		spec->mic_led_coefbit_on = 1<<13;
 		spec->mic_led_coefbit_off = 0;
-		snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
 	}
 }
 
@@ -4290,7 +4303,7 @@ static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 		spec->mic_led_coefbit_mask = 3<<2;
 		spec->mic_led_coefbit_on = 2<<2;
 		spec->mic_led_coefbit_off = 1<<2;
-		snd_hda_gen_add_micmute_led(codec, alc_hp_cap_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
 	}
 }
 
@@ -4430,7 +4443,7 @@ static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
 	alc269_fixup_hp_mute_led_micx(codec, fix, action, 0x1a);
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->cap_mute_led_nid = 0x18;
-		snd_hda_gen_add_micmute_led(codec, alc_cap_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, vref_micmute_led_set);
 	}
 }
 
@@ -6660,7 +6673,7 @@ static const struct hda_fixup alc269_fixups[] = {
 	},
 	[ALC255_FIXUP_MIC_MUTE_LED] = {
 		.type = HDA_FIXUP_FUNC,
-		.v.func = snd_hda_gen_fixup_micmute_led,
+		.v.func = alc_fixup_micmute_led,
 	},
 	[ALC282_FIXUP_ASPIRE_V5_PINS] = {
 		.type = HDA_FIXUP_PINS,
@@ -6763,7 +6776,7 @@ static const struct hda_fixup alc269_fixups[] = {
 	},
 	[ALC292_FIXUP_DELL_E7X] = {
 		.type = HDA_FIXUP_FUNC,
-		.v.func = snd_hda_gen_fixup_micmute_led,
+		.v.func = alc_fixup_micmute_led,
 		/* micmute fixup must be applied at last */
 		.chained_before = true,
 		.chain_id = ALC292_FIXUP_DELL_E7X_AAMIX,
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
index 4089feb8c68e..cd14d5a55b42 100644
--- a/sound/pci/hda/thinkpad_helper.c
+++ b/sound/pci/hda/thinkpad_helper.c
@@ -35,7 +35,7 @@ static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
 			return;
 		old_vmaster_hook = spec->vmaster_mute.hook;
 		spec->vmaster_mute.hook = update_tpacpi_mute_led;
-		snd_hda_gen_fixup_micmute_led(codec, fix, action);
+		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
 	}
 }
 
-- 
2.16.4


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

* [PATCH 04/13] ALSA: hda/conexant: Convert to cdev-variant of mic-mute LED controls
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (2 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 03/13] ALSA: hda/realtek: Convert to cdev-variant of mic-mute LED controls Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 05/13] ALSA: hda/sigmatel: " Takashi Iwai
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

This patch converts the remaining user of
snd_hda_gen_add_micmute_led() in Conexant codec driver into the new
snd_hda_gen_add_micmute_led_cdev().

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_conexant.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 396b5503038a..5a7c16e39d7a 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -640,12 +640,14 @@ static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
-static void cxt_gpio_micmute_update(struct hda_codec *codec)
+static int cxt_gpio_micmute_update(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
 {
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct conexant_spec *spec = codec->spec;
 
-	cxt_update_gpio_led(codec, spec->gpio_mic_led_mask,
-			    spec->gen.micmute_led.led_value);
+	cxt_update_gpio_led(codec, spec->gpio_mic_led_mask, brightness);
+	return 0;
 }
 
 
@@ -665,7 +667,7 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
 		spec->mute_led_polarity = 0;
 		spec->gpio_mute_led_mask = 0x01;
 		spec->gpio_mic_led_mask = 0x02;
-		snd_hda_gen_add_micmute_led(codec, cxt_gpio_micmute_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, cxt_gpio_micmute_update);
 	}
 	snd_hda_add_verbs(codec, gpio_init);
 	if (spec->gpio_led)
-- 
2.16.4


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

* [PATCH 05/13] ALSA: hda/sigmatel: Convert to cdev-variant of mic-mute LED controls
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (3 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 04/13] ALSA: hda/conexant: " Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 06/13] ALSA: hda: generic: Drop unused snd_hda_gen_fixup_micmute_led() Takashi Iwai
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

This patch converts the remaining user of
snd_hda_gen_add_micmute_led() in IDT/Sigmatel codec driver into the
new snd_hda_gen_add_micmute_led_cdev().

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index a608d0486ae4..3b796d0d7a67 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -320,15 +320,18 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
 }
 
 /* hook for controlling mic-mute LED GPIO */
-static void stac_capture_led_update(struct hda_codec *codec)
+static int stac_capture_led_update(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
 {
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct sigmatel_spec *spec = codec->spec;
 
-	if (spec->gen.micmute_led.led_value)
+	if (brightness)
 		spec->gpio_data |= spec->mic_mute_led_gpio;
 	else
 		spec->gpio_data &= ~spec->mic_mute_led_gpio;
 	stac_gpio_set(codec, spec->gpio_mask, spec->gpio_dir, spec->gpio_data);
+	return 0;
 }
 
 static int stac_vrefout_set(struct hda_codec *codec,
@@ -4636,7 +4639,7 @@ static void stac_setup_gpio(struct hda_codec *codec)
 		spec->gpio_dir |= spec->mic_mute_led_gpio;
 		spec->mic_enabled = 0;
 		spec->gpio_data |= spec->mic_mute_led_gpio;
-		snd_hda_gen_add_micmute_led(codec, stac_capture_led_update);
+		snd_hda_gen_add_micmute_led_cdev(codec, stac_capture_led_update);
 	}
 }
 
-- 
2.16.4


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

* [PATCH 06/13] ALSA: hda: generic: Drop unused snd_hda_gen_fixup_micmute_led()
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (4 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 05/13] ALSA: hda/sigmatel: " Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 07/13] ALSA: hda: generic: Drop the old mic-mute LED hook Takashi Iwai
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

The fixup function is no longer used.  Let's drop.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_generic.c | 23 -----------------------
 sound/pci/hda/hda_generic.h |  2 --
 2 files changed, 25 deletions(-)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 419cfbd0dc5c..53a328d21e96 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -4026,29 +4026,6 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led);
 
-/**
- * snd_hda_gen_fixup_micmute_led - A fixup for mic-mute LED trigger
- *
- * Pass this function to the quirk entry if another driver supports the
- * audio mic-mute LED trigger.  Then this will bind the mixer capture switch
- * change with the LED.
- *
- * Note that this fixup has to be called after other fixup that sets
- * cap_sync_hook.  Otherwise the chaining wouldn't work.
- *
- * @codec: the HDA codec
- * @fix: fixup pointer
- * @action: only supports HDA_FIXUP_ACT_PROBE value
- *
- */
-void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
-				   const struct hda_fixup *fix, int action)
-{
-	if (action == HDA_FIXUP_ACT_PROBE)
-		snd_hda_gen_add_micmute_led(codec, NULL);
-}
-EXPORT_SYMBOL_GPL(snd_hda_gen_fixup_micmute_led);
-
 /**
  * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
  * @codec: the HDA codec
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index f56bc8da20b2..6fcb62ed30c6 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -357,8 +357,6 @@ int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
 
 int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
 				void (*hook)(struct hda_codec *));
-void snd_hda_gen_fixup_micmute_led(struct hda_codec *codec,
-				   const struct hda_fixup *fix, int action);
 int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 				     int (*callback)(struct led_classdev *,
 						     enum led_brightness));
-- 
2.16.4


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

* [PATCH 07/13] ALSA: hda: generic: Drop the old mic-mute LED hook
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (5 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 06/13] ALSA: hda: generic: Drop unused snd_hda_gen_fixup_micmute_led() Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 08/13] ALSA: hda: generic: Add vmaster mute LED helper Takashi Iwai
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Now all users of the old snd_hda_gen_add_micmute_led() have been
converted to the new LED-classdev variant, and we can make it local,
and remove the unused hda_gen_spec.micmute_led.update callback field.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_generic.c | 22 +++-------------------
 sound/pci/hda/hda_generic.h |  3 ---
 2 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 53a328d21e96..c97a1404af6b 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3922,8 +3922,6 @@ static void call_micmute_led_update(struct hda_codec *codec)
 	if (val == spec->micmute_led.led_value)
 		return;
 	spec->micmute_led.led_value = val;
-	if (spec->micmute_led.update)
-		spec->micmute_led.update(codec);
 	ledtrig_audio_set(LED_AUDIO_MICMUTE,
 			  spec->micmute_led.led_value ? LED_ON : LED_OFF);
 }
@@ -3997,20 +3995,8 @@ static const struct snd_kcontrol_new micmute_led_mode_ctl = {
 	.put = micmute_led_mode_put,
 };
 
-/**
- * snd_hda_gen_add_micmute_led - helper for setting up mic mute LED hook
- * @codec: the HDA codec
- * @hook: the callback for updating LED
- *
- * Called from the codec drivers for offering the mic mute LED controls.
- * When established, it sets up cap_sync_hook and triggers the callback at
- * each time when the capture mixer switch changes.  The callback is supposed
- * to update the LED accordingly.
- *
- * Returns 0 if the hook is established or a negative error code.
- */
-int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
-				void (*hook)(struct hda_codec *))
+/* Set up the capture sync hook for controlling the mic-mute LED */
+static int add_micmute_led_hook(struct hda_codec *codec)
 {
 	struct hda_gen_spec *spec = codec->spec;
 
@@ -4018,13 +4004,11 @@ int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
 	spec->micmute_led.capture = 0;
 	spec->micmute_led.led_value = 0;
 	spec->micmute_led.old_hook = spec->cap_sync_hook;
-	spec->micmute_led.update = hook;
 	spec->cap_sync_hook = update_micmute_led;
 	if (!snd_hda_gen_add_kctl(spec, NULL, &micmute_led_mode_ctl))
 		return -ENOMEM;
 	return 0;
 }
-EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led);
 
 /**
  * snd_dha_gen_add_micmute_led_cdev - Create a LED classdev and enable as mic-mute LED
@@ -4065,7 +4049,7 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 		}
 	}
 
-	return snd_hda_gen_add_micmute_led(codec, NULL);
+	return add_micmute_led_hook(codec);
 }
 EXPORT_SYMBOL_GPL(snd_hda_gen_add_micmute_led_cdev);
 #endif /* CONFIG_SND_HDA_GENERIC_LEDS */
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index 6fcb62ed30c6..a59e66f9ff33 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -88,7 +88,6 @@ struct hda_micmute_hook {
 	unsigned int led_mode;
 	unsigned int capture;
 	unsigned int led_value;
-	void (*update)(struct hda_codec *codec);
 	void (*old_hook)(struct hda_codec *codec,
 			 struct snd_kcontrol *kcontrol,
 			 struct snd_ctl_elem_value *ucontrol);
@@ -355,8 +354,6 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
 void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
 int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
 
-int snd_hda_gen_add_micmute_led(struct hda_codec *codec,
-				void (*hook)(struct hda_codec *));
 int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 				     int (*callback)(struct led_classdev *,
 						     enum led_brightness));
-- 
2.16.4


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

* [PATCH 08/13] ALSA: hda: generic: Add vmaster mute LED helper
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (6 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 07/13] ALSA: hda: generic: Drop the old mic-mute LED hook Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 09/13] ALSA: hda/realtek: Use the new " Takashi Iwai
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Like mic-mute LED handling, add a new helper to deal with the master
mute LED with LED classdev.  Unlike the mic-mute case, the playback
master mute is hooked on vmaster, and we suppose no nested hooks
allowed there.

The classdev creation code is factored out to a common function that
is called from both mute and mic-mute LED helpers.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_generic.c | 71 +++++++++++++++++++++++++++++++++++++--------
 sound/pci/hda/hda_generic.h |  3 ++
 2 files changed, 62 insertions(+), 12 deletions(-)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c97a1404af6b..c74519d7096b 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3888,6 +3888,64 @@ static int parse_mic_boost(struct hda_codec *codec)
 }
 
 #ifdef CONFIG_SND_HDA_GENERIC_LEDS
+/*
+ * vmaster mute LED hook helpers
+ */
+
+static int create_mute_led_cdev(struct hda_codec *codec,
+				int (*callback)(struct led_classdev *,
+						enum led_brightness),
+				bool micmute)
+{
+	struct led_classdev *cdev;
+
+	cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
+	if (!cdev)
+		return -ENOMEM;
+
+	cdev->name = micmute ? "hda::micmute" : "hda::mute";
+	cdev->max_brightness = 1;
+	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
+	cdev->brightness_set_blocking = callback;
+	cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE);
+
+	return devm_led_classdev_register(&codec->core.dev, cdev);
+}
+
+static void vmaster_update_mute_led(void *private_data, int enabled)
+{
+	ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
+}
+
+/**
+ * snd_dha_gen_add_mute_led_cdev - Create a LED classdev and enable as vmaster mute LED
+ * @codec: the HDA codec
+ * @callback: the callback for LED classdev brightness_set_blocking
+ */
+int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
+				  int (*callback)(struct led_classdev *,
+						  enum led_brightness))
+{
+	struct hda_gen_spec *spec = codec->spec;
+	int err;
+
+	if (callback) {
+		err = create_mute_led_cdev(codec, callback, false);
+		if (err) {
+			codec_warn(codec, "failed to create a mute LED cdev\n");
+			return err;
+		}
+	}
+
+	if (spec->vmaster_mute.hook)
+		codec_err(codec, "vmaster hook already present before cdev!\n");
+
+	spec->vmaster_mute.hook = vmaster_update_mute_led;
+	spec->vmaster_mute_enum = 1;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hda_gen_add_mute_led_cdev);
+
 /*
  * mic mute LED hook helpers
  */
@@ -4029,20 +4087,9 @@ int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 						     enum led_brightness))
 {
 	int err;
-	struct led_classdev *cdev;
 
 	if (callback) {
-		cdev = devm_kzalloc(&codec->core.dev, sizeof(*cdev), GFP_KERNEL);
-		if (!cdev)
-			return -ENOMEM;
-
-		cdev->name = "hda::micmute";
-		cdev->max_brightness = 1;
-		cdev->default_trigger = "audio-micmute";
-		cdev->brightness_set_blocking = callback;
-		cdev->brightness = ledtrig_audio_get(LED_AUDIO_MICMUTE);
-
-		err = devm_led_classdev_register(&codec->core.dev, cdev);
+		err = create_mute_led_cdev(codec, callback, true);
 		if (err) {
 			codec_warn(codec, "failed to create a mic-mute LED cdev\n");
 			return err;
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h
index a59e66f9ff33..bbd6d2b741f2 100644
--- a/sound/pci/hda/hda_generic.h
+++ b/sound/pci/hda/hda_generic.h
@@ -354,6 +354,9 @@ unsigned int snd_hda_gen_path_power_filter(struct hda_codec *codec,
 void snd_hda_gen_stream_pm(struct hda_codec *codec, hda_nid_t nid, bool on);
 int snd_hda_gen_fix_pin_power(struct hda_codec *codec, hda_nid_t pin);
 
+int snd_hda_gen_add_mute_led_cdev(struct hda_codec *codec,
+				  int (*callback)(struct led_classdev *,
+						  enum led_brightness));
 int snd_hda_gen_add_micmute_led_cdev(struct hda_codec *codec,
 				     int (*callback)(struct led_classdev *,
 						     enum led_brightness));
-- 
2.16.4


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

* [PATCH 09/13] ALSA: hda/realtek: Use the new vmaster mute LED helper
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (7 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 08/13] ALSA: hda: generic: Add vmaster mute LED helper Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 10/13] ALSA: hda/conexant: " Takashi Iwai
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Convert the mute LED handling in Realtek codec to the new vmaster mute
helper.  A point to be cautiously handled is that the value passed to
the callback is inverted; the vmaster passes "enabled" (0 = mute),
while LED classdev passes "brightness" (1 = mute).

The code in Thinkpad helper is also converted.   In that case, just
call the new function and remove the open-code.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c   | 54 +++++++++++++++++++++++------------------
 sound/pci/hda/thinkpad_helper.c | 17 ++-----------
 2 files changed, 32 insertions(+), 39 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 6831587fc4d6..87f7a1c3558d 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -80,7 +80,7 @@ struct alc_spec {
 	unsigned int gpio_data;
 	bool gpio_write_delay;	/* add a delay before writing gpio_data */
 
-	/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */
+	/* mute LED for HP laptops, see vref_mute_led_set() */
 	int mute_led_polarity;
 	int micmute_led_polarity;
 	hda_nid_t mute_led_nid;
@@ -3990,23 +3990,25 @@ static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
 
 
 /* update mute-LED according to the speaker mute state via mic VREF pin */
-static void alc269_fixup_mic_mute_hook(void *private_data, int enabled)
+static int vref_mute_led_set(struct led_classdev *led_cdev,
+			     enum led_brightness brightness)
 {
-	struct hda_codec *codec = private_data;
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 	unsigned int pinval;
 
 	if (spec->mute_led_polarity)
-		enabled = !enabled;
+		brightness = !brightness;
 	pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid);
 	pinval &= ~AC_PINCTL_VREFEN;
-	pinval |= enabled ? AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_80;
+	pinval |= brightness ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ;
 	if (spec->mute_led_nid) {
 		/* temporarily power up/down for setting VREF */
 		snd_hda_power_up_pm(codec);
 		snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
 		snd_hda_power_down_pm(codec);
 	}
+	return 0;
 }
 
 /* Make sure the led works even in runtime suspend */
@@ -4044,8 +4046,7 @@ static void alc269_fixup_hp_mute_led(struct hda_codec *codec,
 			break;
 		spec->mute_led_polarity = pol;
 		spec->mute_led_nid = pin - 0x0a + 0x18;
-		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
-		spec->gen.vmaster_mute_enum = 1;
+		snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set);
 		codec->power_filter = led_power_filter;
 		codec_dbg(codec,
 			  "Detected mute LED for %x:%d\n", spec->mute_led_nid,
@@ -4063,8 +4064,7 @@ static void alc269_fixup_hp_mute_led_micx(struct hda_codec *codec,
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->mute_led_polarity = 0;
 		spec->mute_led_nid = pin;
-		spec->gen.vmaster_mute.hook = alc269_fixup_mic_mute_hook;
-		spec->gen.vmaster_mute_enum = 1;
+		snd_hda_gen_add_mute_led_cdev(codec, vref_mute_led_set);
 		codec->power_filter = led_power_filter;
 	}
 }
@@ -4097,13 +4097,15 @@ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
 }
 
 /* turn on/off mute LED via GPIO per vmaster hook */
-static void alc_fixup_gpio_mute_hook(void *private_data, int enabled)
+static int gpio_mute_led_set(struct led_classdev *led_cdev,
+			     enum led_brightness brightness)
 {
-	struct hda_codec *codec = private_data;
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 
 	alc_update_gpio_led(codec, spec->gpio_mute_led_mask,
-			    spec->mute_led_polarity, enabled);
+			    spec->mute_led_polarity, !brightness);
+	return 0;
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
@@ -4132,7 +4134,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec,
 		return;
 	if (mute_mask) {
 		spec->gpio_mute_led_mask = mute_mask;
-		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
+		snd_hda_gen_add_mute_led_cdev(codec, gpio_mute_led_set);
 	}
 	if (micmute_mask) {
 		spec->gpio_mic_led_mask = micmute_mask;
@@ -4214,19 +4216,25 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
 }
 
 /* update mute-LED according to the speaker mute state via COEF bit */
-static void alc_fixup_mute_led_coefbit_hook(void *private_data, int enabled)
+static int coef_mute_led_set(struct led_classdev *led_cdev,
+			     enum led_brightness brightness)
 {
-	struct hda_codec *codec = private_data;
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 
 	if (spec->mute_led_polarity)
-		enabled = !enabled;
+		brightness = !brightness;
 
 	/* temporarily power up/down for setting COEF bit */
-	enabled ? alc_update_coef_idx(codec, spec->mute_led_coef_idx,
-		spec->mute_led_coefbit_mask, spec->mute_led_coefbit_off) :
-		  alc_update_coef_idx(codec, spec->mute_led_coef_idx,
-		spec->mute_led_coefbit_mask, spec->mute_led_coefbit_on);
+	if (brightness)
+		alc_update_coef_idx(codec, spec->mute_led_coef_idx,
+				    spec->mute_led_coefbit_mask,
+				    spec->mute_led_coefbit_on);
+	else
+		alc_update_coef_idx(codec, spec->mute_led_coef_idx,
+				    spec->mute_led_coefbit_mask,
+				    spec->mute_led_coefbit_off);
+	return 0;
 }
 
 static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
@@ -4241,8 +4249,7 @@ static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 		spec->mute_led_coefbit_mask = 1<<3;
 		spec->mute_led_coefbit_on = 1<<3;
 		spec->mute_led_coefbit_off = 0;
-		spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook;
-		spec->gen.vmaster_mute_enum = 1;
+		snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 	}
 }
 
@@ -4258,8 +4265,7 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 		spec->mute_led_coefbit_mask = 1<<5;
 		spec->mute_led_coefbit_on = 0;
 		spec->mute_led_coefbit_off = 1<<5;
-		spec->gen.vmaster_mute.hook = alc_fixup_mute_led_coefbit_hook;
-		spec->gen.vmaster_mute_enum = 1;
+		snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 	}
 }
 
diff --git a/sound/pci/hda/thinkpad_helper.c b/sound/pci/hda/thinkpad_helper.c
index cd14d5a55b42..6698ae241efc 100644
--- a/sound/pci/hda/thinkpad_helper.c
+++ b/sound/pci/hda/thinkpad_helper.c
@@ -3,13 +3,11 @@
  * to be included from codec driver
  */
 
-#if IS_ENABLED(CONFIG_THINKPAD_ACPI) && IS_REACHABLE(CONFIG_LEDS_TRIGGER_AUDIO)
+#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
 
 #include <linux/acpi.h>
 #include <linux/leds.h>
 
-static void (*old_vmaster_hook)(void *, int);
-
 static bool is_thinkpad(struct hda_codec *codec)
 {
 	return (codec->core.subsystem_id >> 16 == 0x17aa) &&
@@ -17,24 +15,13 @@ static bool is_thinkpad(struct hda_codec *codec)
 		acpi_dev_found("IBM0068"));
 }
 
-static void update_tpacpi_mute_led(void *private_data, int enabled)
-{
-	if (old_vmaster_hook)
-		old_vmaster_hook(private_data, enabled);
-
-	ledtrig_audio_set(LED_AUDIO_MUTE, enabled ? LED_OFF : LED_ON);
-}
-
 static void hda_fixup_thinkpad_acpi(struct hda_codec *codec,
 				    const struct hda_fixup *fix, int action)
 {
-	struct hda_gen_spec *spec = codec->spec;
-
 	if (action == HDA_FIXUP_ACT_PROBE) {
 		if (!is_thinkpad(codec))
 			return;
-		old_vmaster_hook = spec->vmaster_mute.hook;
-		spec->vmaster_mute.hook = update_tpacpi_mute_led;
+		snd_hda_gen_add_mute_led_cdev(codec, NULL);
 		snd_hda_gen_add_micmute_led_cdev(codec, NULL);
 	}
 }
-- 
2.16.4


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

* [PATCH 10/13] ALSA: hda/conexant: Use the new vmaster mute LED helper
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (8 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 09/13] ALSA: hda/realtek: Use the new " Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 11/13] ALSA: hda/sigmatel: " Takashi Iwai
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Convert the mute LED handling in Conexant codec to the new vmaster
mute helper.  A point to be cautiously handled is that the value
passed to the callback is inverted; the vmaster passes "enabled"
(0 = mute), while LED classdev passes "brightness" (1 = mute).

Also the assignment of the default vmaster hook is moved at a later
point after the mute hook is set up.  This assures no nested hook.

Finally, since we enable the mute-LED kcontrols always in the helper
side, the extra vmaster_mute_enum flag set up is dropped.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_conexant.c | 37 +++++++++++++++----------------------
 1 file changed, 15 insertions(+), 22 deletions(-)

diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 5a7c16e39d7a..d796963b80d7 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -137,14 +137,16 @@ static void cx_auto_vmaster_hook(void *private_data, int enabled)
 }
 
 /* turn on/off EAPD according to Master switch (inversely!) for mute LED */
-static void cx_auto_vmaster_hook_mute_led(void *private_data, int enabled)
+static int cx_auto_vmaster_mute_led(struct led_classdev *led_cdev,
+				    enum led_brightness brightness)
 {
-	struct hda_codec *codec = private_data;
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct conexant_spec *spec = codec->spec;
 
 	snd_hda_codec_write(codec, spec->mute_led_eapd, 0,
 			    AC_VERB_SET_EAPD_BTLENABLE,
-			    enabled ? 0x00 : 0x02);
+			    brightness ? 0x02 : 0x00);
+	return 0;
 }
 
 static int cx_auto_init(struct hda_codec *codec)
@@ -566,7 +568,7 @@ static void cxt_fixup_mute_led_eapd(struct hda_codec *codec,
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->mute_led_eapd = 0x1b;
 		spec->dynamic_eapd = 1;
-		spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook_mute_led;
+		snd_hda_gen_add_mute_led_cdev(codec, cx_auto_vmaster_mute_led);
 	}
 }
 
@@ -631,12 +633,14 @@ static void cxt_update_gpio_led(struct hda_codec *codec, unsigned int mask,
 }
 
 /* turn on/off mute LED via GPIO per vmaster hook */
-static void cxt_fixup_gpio_mute_hook(void *private_data, int enabled)
+static int cxt_gpio_mute_update(struct led_classdev *led_cdev,
+				enum led_brightness brightness)
 {
-	struct hda_codec *codec = private_data;
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct conexant_spec *spec = codec->spec;
-	/* muted -> LED on */
-	cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, !enabled);
+
+	cxt_update_gpio_led(codec, spec->gpio_mute_led_mask, brightness);
+	return 0;
 }
 
 /* turn on/off mic-mute LED via GPIO per capture hook */
@@ -662,7 +666,7 @@ static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
 	};
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-		spec->gen.vmaster_mute.hook = cxt_fixup_gpio_mute_hook;
+		snd_hda_gen_add_mute_led_cdev(codec, cxt_gpio_mute_update);
 		spec->gpio_led = 0;
 		spec->mute_led_polarity = 0;
 		spec->gpio_mute_led_mask = 0x01;
@@ -990,8 +994,6 @@ static int patch_conexant_auto(struct hda_codec *codec)
 
 	cx_auto_parse_eapd(codec);
 	spec->gen.own_eapd_ctl = 1;
-	if (spec->dynamic_eapd)
-		spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook;
 
 	switch (codec->core.vendor_id) {
 	case 0x14f15045:
@@ -1024,17 +1026,8 @@ static int patch_conexant_auto(struct hda_codec *codec)
 		break;
 	}
 
-	/* Show mute-led control only on HP laptops
-	 * This is a sort of white-list: on HP laptops, EAPD corresponds
-	 * only to the mute-LED without actualy amp function.  Meanwhile,
-	 * others may use EAPD really as an amp switch, so it might be
-	 * not good to expose it blindly.
-	 */
-	switch (codec->core.subsystem_id >> 16) {
-	case 0x103c:
-		spec->gen.vmaster_mute_enum = 1;
-		break;
-	}
+	if (!spec->gen.vmaster_mute.hook && spec->dynamic_eapd)
+		spec->gen.vmaster_mute.hook = cx_auto_vmaster_hook;
 
 	snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_PRE_PROBE);
 
-- 
2.16.4


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

* [PATCH 11/13] ALSA: hda/sigmatel: Use the new vmaster mute LED helper
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (9 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 10/13] ALSA: hda/conexant: " Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 12/13] ALSA: hda/realtek: Unify LED helper code Takashi Iwai
  2020-06-18 11:08 ` [PATCH 13/13] ALSA: hda: Let LED cdev handling suspend/resume Takashi Iwai
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Convert the mute LED handling in Sigmatel/IDT codec to the new vmaster
mute helper.  A point to be cautiously handled is that the value
passed to the callback is inverted; the vmaster passes "enabled"
(0 = mute), while LED classdev passes "brightness" (1 = mute).

A positive side-effect by this change is that the driver gets also the
enum controls for the mute behavior like other drivers already had.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_sigmatel.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 3b796d0d7a67..d8ed69cb9df1 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -369,10 +369,9 @@ static unsigned int stac_vref_led_power_filter(struct hda_codec *codec,
 }
 
 /* update mute-LED accoring to the master switch */
-static void stac_update_led_status(struct hda_codec *codec, int enabled)
+static void stac_update_led_status(struct hda_codec *codec, bool muted)
 {
 	struct sigmatel_spec *spec = codec->spec;
-	int muted = !enabled;
 
 	if (!spec->gpio_led)
 		return;
@@ -396,9 +395,13 @@ static void stac_update_led_status(struct hda_codec *codec, int enabled)
 }
 
 /* vmaster hook to update mute LED */
-static void stac_vmaster_hook(void *private_data, int val)
+static int stac_vmaster_hook(struct led_classdev *led_cdev,
+			     enum led_brightness brightness)
 {
-	stac_update_led_status(private_data, val);
+	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
+
+	stac_update_led_status(codec, brightness);
+	return 0;
 }
 
 /* automute hook to handle GPIO mute and EAPD updates */
@@ -4316,7 +4319,7 @@ static int stac_parse_auto_config(struct hda_codec *codec)
 #endif
 
 	if (spec->gpio_led)
-		spec->gen.vmaster_mute.hook = stac_vmaster_hook;
+		snd_hda_gen_add_mute_led_cdev(codec, stac_vmaster_hook);
 
 	if (spec->aloopback_ctl &&
 	    snd_hda_get_bool_hint(codec, "loopback") == 1) {
-- 
2.16.4


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

* [PATCH 12/13] ALSA: hda/realtek: Unify LED helper code
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (10 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 11/13] ALSA: hda/sigmatel: " Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  2020-06-18 11:08 ` [PATCH 13/13] ALSA: hda: Let LED cdev handling suspend/resume Takashi Iwai
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Both mute and mic-mute LED callbacks do almost similar tasks with just
different bits.  Factor out the common code and use them from the
callbacks for simplification.

This ended up with covering the forgotten stuff, too; e.g. VREF LED
handling required the temporary power up/down that was missing for the
mute LED, or some forgotten polarity checks are added.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/patch_realtek.c | 125 +++++++++++++++++++++---------------------
 1 file changed, 61 insertions(+), 64 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 87f7a1c3558d..53e0eef8b042 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -67,6 +67,13 @@ struct alc_customize_define {
 	unsigned int  fixup:1; /* Means that this sku is set by driver, not read from hw */
 };
 
+struct alc_coef_led {
+	unsigned int idx;
+	unsigned int mask;
+	unsigned int on;
+	unsigned int off;
+};
+
 struct alc_spec {
 	struct hda_gen_spec gen; /* must be at head */
 
@@ -88,14 +95,8 @@ struct alc_spec {
 
 	unsigned int gpio_mute_led_mask;
 	unsigned int gpio_mic_led_mask;
-	unsigned int mute_led_coef_idx;
-	unsigned int mute_led_coefbit_mask;
-	unsigned int mute_led_coefbit_on;
-	unsigned int mute_led_coefbit_off;
-	unsigned int mic_led_coef_idx;
-	unsigned int mic_led_coefbit_mask;
-	unsigned int mic_led_coefbit_on;
-	unsigned int mic_led_coefbit_off;
+	struct alc_coef_led mute_led_coef;
+	struct alc_coef_led mic_led_coef;
 
 	hda_nid_t headset_mic_pin;
 	hda_nid_t headphone_mic_pin;
@@ -3988,6 +3989,23 @@ static void alc269_fixup_x101_headset_mic(struct hda_codec *codec,
 	}
 }
 
+static void alc_update_vref_led(struct hda_codec *codec, hda_nid_t pin,
+				bool polarity, bool on)
+{
+	unsigned int pinval;
+
+	if (!pin)
+		return;
+	if (polarity)
+		on = !on;
+	pinval = snd_hda_codec_get_pin_target(codec, pin);
+	pinval &= ~AC_PINCTL_VREFEN;
+	pinval |= on ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ;
+	/* temporarily power up/down for setting VREF */
+	snd_hda_power_up_pm(codec);
+	snd_hda_set_pin_ctl_cache(codec, pin, pinval);
+	snd_hda_power_down_pm(codec);
+}
 
 /* update mute-LED according to the speaker mute state via mic VREF pin */
 static int vref_mute_led_set(struct led_classdev *led_cdev,
@@ -3995,19 +4013,9 @@ static int vref_mute_led_set(struct led_classdev *led_cdev,
 {
 	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
-	unsigned int pinval;
 
-	if (spec->mute_led_polarity)
-		brightness = !brightness;
-	pinval = snd_hda_codec_get_pin_target(codec, spec->mute_led_nid);
-	pinval &= ~AC_PINCTL_VREFEN;
-	pinval |= brightness ? AC_PINCTL_VREF_80 : AC_PINCTL_VREF_HIZ;
-	if (spec->mute_led_nid) {
-		/* temporarily power up/down for setting VREF */
-		snd_hda_power_up_pm(codec);
-		snd_hda_set_pin_ctl_cache(codec, spec->mute_led_nid, pinval);
-		snd_hda_power_down_pm(codec);
-	}
+	alc_update_vref_led(codec, spec->mute_led_nid,
+			    spec->mute_led_polarity, brightness);
 	return 0;
 }
 
@@ -4170,17 +4178,9 @@ static int vref_micmute_led_set(struct led_classdev *led_cdev,
 {
 	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
-	unsigned int pinval;
 
-	if (!spec->cap_mute_led_nid)
-		return 0;
-	pinval = snd_hda_codec_get_pin_target(codec, spec->cap_mute_led_nid);
-	pinval &= ~AC_PINCTL_VREFEN;
-	if (brightness)
-		pinval |= AC_PINCTL_VREF_80;
-	else
-		pinval |= AC_PINCTL_VREF_HIZ;
-	snd_hda_set_pin_ctl_cache(codec, spec->cap_mute_led_nid, pinval);
+	alc_update_vref_led(codec, spec->cap_mute_led_nid,
+			    spec->micmute_led_polarity, brightness);
 	return 0;
 }
 
@@ -4215,6 +4215,17 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
 	}
 }
 
+static void alc_update_coef_led(struct hda_codec *codec,
+				struct alc_coef_led *led,
+				bool polarity, bool on)
+{
+	if (polarity)
+		on = !on;
+	/* temporarily power up/down for setting COEF bit */
+	alc_update_coef_idx(codec, led->idx, led->mask,
+			    on ? led->on : led->off);
+}
+
 /* update mute-LED according to the speaker mute state via COEF bit */
 static int coef_mute_led_set(struct led_classdev *led_cdev,
 			     enum led_brightness brightness)
@@ -4222,18 +4233,8 @@ static int coef_mute_led_set(struct led_classdev *led_cdev,
 	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 
-	if (spec->mute_led_polarity)
-		brightness = !brightness;
-
-	/* temporarily power up/down for setting COEF bit */
-	if (brightness)
-		alc_update_coef_idx(codec, spec->mute_led_coef_idx,
-				    spec->mute_led_coefbit_mask,
-				    spec->mute_led_coefbit_on);
-	else
-		alc_update_coef_idx(codec, spec->mute_led_coef_idx,
-				    spec->mute_led_coefbit_mask,
-				    spec->mute_led_coefbit_off);
+	alc_update_coef_led(codec, &spec->mute_led_coef,
+			    spec->mute_led_polarity, brightness);
 	return 0;
 }
 
@@ -4245,10 +4246,10 @@ static void alc285_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->mute_led_polarity = 0;
-		spec->mute_led_coef_idx = 0x0b;
-		spec->mute_led_coefbit_mask = 1<<3;
-		spec->mute_led_coefbit_on = 1<<3;
-		spec->mute_led_coefbit_off = 0;
+		spec->mute_led_coef.idx = 0x0b;
+		spec->mute_led_coef.mask = 1 << 3;
+		spec->mute_led_coef.on = 1 << 3;
+		spec->mute_led_coef.off = 0;
 		snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 	}
 }
@@ -4261,10 +4262,10 @@ static void alc236_fixup_hp_mute_led_coefbit(struct hda_codec *codec,
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
 		spec->mute_led_polarity = 0;
-		spec->mute_led_coef_idx = 0x34;
-		spec->mute_led_coefbit_mask = 1<<5;
-		spec->mute_led_coefbit_on = 0;
-		spec->mute_led_coefbit_off = 1<<5;
+		spec->mute_led_coef.idx = 0x34;
+		spec->mute_led_coef.mask = 1 << 5;
+		spec->mute_led_coef.on = 0;
+		spec->mute_led_coef.off = 1 << 5;
 		snd_hda_gen_add_mute_led_cdev(codec, coef_mute_led_set);
 	}
 }
@@ -4276,12 +4277,8 @@ static int coef_micmute_led_set(struct led_classdev *led_cdev,
 	struct hda_codec *codec = dev_to_hda_codec(led_cdev->dev->parent);
 	struct alc_spec *spec = codec->spec;
 
-	if (brightness)
-		alc_update_coef_idx(codec, spec->mic_led_coef_idx,
-			spec->mic_led_coefbit_mask, spec->mic_led_coefbit_on);
-	else
-		alc_update_coef_idx(codec, spec->mic_led_coef_idx,
-			spec->mic_led_coefbit_mask, spec->mic_led_coefbit_off);
+	alc_update_coef_led(codec, &spec->mic_led_coef,
+			    spec->micmute_led_polarity, brightness);
 	return 0;
 }
 
@@ -4291,10 +4288,10 @@ static void alc285_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 	struct alc_spec *spec = codec->spec;
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-		spec->mic_led_coef_idx = 0x19;
-		spec->mic_led_coefbit_mask = 1<<13;
-		spec->mic_led_coefbit_on = 1<<13;
-		spec->mic_led_coefbit_off = 0;
+		spec->mic_led_coef.idx = 0x19;
+		spec->mic_led_coef.mask = 1 << 13;
+		spec->mic_led_coef.on = 1 << 13;
+		spec->mic_led_coef.off = 0;
 		snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
 	}
 }
@@ -4305,10 +4302,10 @@ static void alc236_fixup_hp_coef_micmute_led(struct hda_codec *codec,
 	struct alc_spec *spec = codec->spec;
 
 	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
-		spec->mic_led_coef_idx = 0x35;
-		spec->mic_led_coefbit_mask = 3<<2;
-		spec->mic_led_coefbit_on = 2<<2;
-		spec->mic_led_coefbit_off = 1<<2;
+		spec->mic_led_coef.idx = 0x35;
+		spec->mic_led_coef.mask = 3 << 2;
+		spec->mic_led_coef.on = 2 << 2;
+		spec->mic_led_coef.off = 1 << 2;
 		snd_hda_gen_add_micmute_led_cdev(codec, coef_micmute_led_set);
 	}
 }
-- 
2.16.4


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

* [PATCH 13/13] ALSA: hda: Let LED cdev handling suspend/resume
  2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
                   ` (11 preceding siblings ...)
  2020-06-18 11:08 ` [PATCH 12/13] ALSA: hda/realtek: Unify LED helper code Takashi Iwai
@ 2020-06-18 11:08 ` Takashi Iwai
  12 siblings, 0 replies; 14+ messages in thread
From: Takashi Iwai @ 2020-06-18 11:08 UTC (permalink / raw)
  To: alsa-devel; +Cc: Kai-Heng Feng

Set LED_CORE_SUSPENDRESUME to LED cdev flags, so that the LED core
would store and restore the LED status at suspend/resume.

In theory, the codec driver should be responsible for all LED bits,
but this might be safer and cover the overlooked cases.

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 sound/pci/hda/hda_generic.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c74519d7096b..9074265d934a 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -3908,6 +3908,7 @@ static int create_mute_led_cdev(struct hda_codec *codec,
 	cdev->default_trigger = micmute ? "audio-micmute" : "audio-mute";
 	cdev->brightness_set_blocking = callback;
 	cdev->brightness = ledtrig_audio_get(micmute ? LED_AUDIO_MICMUTE : LED_AUDIO_MUTE);
+	cdev->flags = LED_CORE_SUSPENDRESUME;
 
 	return devm_led_classdev_register(&codec->core.dev, cdev);
 }
-- 
2.16.4


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

end of thread, other threads:[~2020-06-18 11:17 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-06-18 11:08 [PATCH 00/13] ALSA: hda: Use LED classdev for mute controls consistently Takashi Iwai
2020-06-18 11:08 ` [PATCH 01/13] ALSA: hda: generic: Always call led-trigger for mic mute LED Takashi Iwai
2020-06-18 11:08 ` [PATCH 02/13] ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev Takashi Iwai
2020-06-18 11:08 ` [PATCH 03/13] ALSA: hda/realtek: Convert to cdev-variant of mic-mute LED controls Takashi Iwai
2020-06-18 11:08 ` [PATCH 04/13] ALSA: hda/conexant: " Takashi Iwai
2020-06-18 11:08 ` [PATCH 05/13] ALSA: hda/sigmatel: " Takashi Iwai
2020-06-18 11:08 ` [PATCH 06/13] ALSA: hda: generic: Drop unused snd_hda_gen_fixup_micmute_led() Takashi Iwai
2020-06-18 11:08 ` [PATCH 07/13] ALSA: hda: generic: Drop the old mic-mute LED hook Takashi Iwai
2020-06-18 11:08 ` [PATCH 08/13] ALSA: hda: generic: Add vmaster mute LED helper Takashi Iwai
2020-06-18 11:08 ` [PATCH 09/13] ALSA: hda/realtek: Use the new " Takashi Iwai
2020-06-18 11:08 ` [PATCH 10/13] ALSA: hda/conexant: " Takashi Iwai
2020-06-18 11:08 ` [PATCH 11/13] ALSA: hda/sigmatel: " Takashi Iwai
2020-06-18 11:08 ` [PATCH 12/13] ALSA: hda/realtek: Unify LED helper code Takashi Iwai
2020-06-18 11:08 ` [PATCH 13/13] ALSA: hda: Let LED cdev handling suspend/resume 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.