[PATCH 1/3] ALSA: hda/realtek - Introduce polarity for micmute LED GPIO
Currently mute LED and micmute LED share the same GPIO polarity.
So split the polarity for mute and micmute, in case they have different polarities.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- sound/pci/hda/patch_realtek.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index c16f63957c5a..3150a61befc5 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -81,6 +81,7 @@ struct alc_spec {
/* mute LED for HP laptops, see alc269_fixup_mic_mute_hook() */ int mute_led_polarity; + int micmute_led_polarity; hda_nid_t mute_led_nid; hda_nid_t cap_mute_led_nid;
@@ -4075,11 +4076,9 @@ static void alc269_fixup_hp_mute_led_mic3(struct hda_codec *codec,
/* update LED status via GPIO */ static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask, - bool enabled) + int polarity, bool enabled) { - struct alc_spec *spec = codec->spec; - - if (spec->mute_led_polarity) + if (polarity) enabled = !enabled; alc_update_gpio_data(codec, mask, !enabled); /* muted -> LED on */ } @@ -4090,7 +4089,8 @@ static void alc_fixup_gpio_mute_hook(void *private_data, int enabled) struct hda_codec *codec = private_data; struct alc_spec *spec = codec->spec;
- alc_update_gpio_led(codec, spec->gpio_mute_led_mask, enabled); + alc_update_gpio_led(codec, spec->gpio_mute_led_mask, + spec->mute_led_polarity, enabled); }
/* turn on/off mic-mute LED via GPIO per capture hook */ @@ -4099,6 +4099,7 @@ 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); }
@@ -5795,7 +5796,8 @@ static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
snd_hda_gen_hp_automute(codec, jack); /* mute_led_polarity is set to 0, so we pass inverted value here */ - alc_update_gpio_led(codec, 0x10, !spec->gen.hp_jack_present); + alc_update_gpio_led(codec, 0x10, spec->mute_led_polarity, + !spec->gen.hp_jack_present); }
/* Manage GPIOs for HP EliteBook Folio 9480m.
Though the system uses DMIC, headset mic still uses the HDA, let's use GPIO 0x1 to control the micmute LED.
The micmute LED GPIO has a different polarity to the mute LED GPIO, we can use the newly added micmute_led_polarity to indicate that.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- sound/pci/hda/patch_realtek.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 3150a61befc5..6f164ccddde3 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -4134,7 +4134,11 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec, static void alc285_fixup_hp_gpio_led(struct hda_codec *codec, const struct hda_fixup *fix, int action) { - alc_fixup_hp_gpio_led(codec, action, 0x04, 0x00); + struct alc_spec *spec = codec->spec; + + spec->micmute_led_polarity = 1; + + alc_fixup_hp_gpio_led(codec, action, 0x04, 0x01); }
static void alc286_fixup_hp_gpio_led(struct hda_codec *codec,
On Thu, 30 Apr 2020 10:32:52 +0200, Kai-Heng Feng wrote:
Though the system uses DMIC, headset mic still uses the HDA, let's use GPIO 0x1 to control the micmute LED.
The micmute LED GPIO has a different polarity to the mute LED GPIO, we can use the newly added micmute_led_polarity to indicate that.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
Applied to for-next branch. Thanks.
Takashi
Currently DMIC controls micmute LED via "audio mute LED trigger".
However, unlike Dell and Lenovo platforms, HP platforms don't provide a way to control micmute LED via ACPI, it's controlled by HDA codec instead.
So let's register an LED class for micmute so other subsystems like DMIC can facilitate the codec-controlled LED.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- sound/pci/hda/patch_realtek.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6f164ccddde3..82eb7624bbba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17,6 +17,7 @@ #include <linux/dmi.h> #include <linux/module.h> #include <linux/input.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/hda_codec.h> @@ -4103,6 +4104,24 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) spec->gen.micmute_led.led_value); }
+static int 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; + + alc_update_gpio_led(codec, spec->gpio_mic_led_mask, + spec->micmute_led_polarity, !!brightness); + 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", +}; + /* setup mute and mic-mute GPIO bits, add hooks appropriately */ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, int action, @@ -4110,6 +4129,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; + int err;
alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
@@ -4122,6 +4142,11 @@ 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); + + 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"); } }
On Thu, 30 Apr 2020 10:32:53 +0200, Kai-Heng Feng wrote:
Currently DMIC controls micmute LED via "audio mute LED trigger".
However, unlike Dell and Lenovo platforms, HP platforms don't provide a way to control micmute LED via ACPI, it's controlled by HDA codec instead.
So let's register an LED class for micmute so other subsystems like DMIC can facilitate the codec-controlled LED.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
I guess this requires the Kconfig change to select CONFIG_LEDS_* or make the code conditionally built. So far the latter strategy is taken for the code in hda_generic.c.
thanks,
Takashi
sound/pci/hda/patch_realtek.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6f164ccddde3..82eb7624bbba 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17,6 +17,7 @@ #include <linux/dmi.h> #include <linux/module.h> #include <linux/input.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/hda_codec.h> @@ -4103,6 +4104,24 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) spec->gen.micmute_led.led_value); }
+static int 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;
- alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
spec->micmute_led_polarity, !!brightness);
- 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",
+};
/* setup mute and mic-mute GPIO bits, add hooks appropriately */ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, int action, @@ -4110,6 +4129,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec;
int err;
alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
@@ -4122,6 +4142,11 @@ 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);
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");
}
-- 2.17.1
Currently DMIC controls micmute LED via "audio mute LED trigger".
However, unlike Dell and Lenovo platforms, HP platforms don't provide a way to control micmute LED via ACPI, it's controlled by HDA codec instead.
So let's register an LED class for micmute so other subsystems like DMIC can facilitate the codec-controlled LED.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com --- v2: - Only compile the code when CONFIG_LEDS_TRIGGER_AUDIO is reachable.
sound/pci/hda/patch_realtek.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 6f164ccddde3..eae672cb6118 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -17,6 +17,7 @@ #include <linux/dmi.h> #include <linux/module.h> #include <linux/input.h> +#include <linux/leds.h> #include <sound/core.h> #include <sound/jack.h> #include <sound/hda_codec.h> @@ -4103,6 +4104,26 @@ static void alc_gpio_micmute_update(struct hda_codec *codec) 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) +{ + 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_mic_led_mask, + spec->micmute_led_polarity, !!brightness); + 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, @@ -4110,6 +4131,7 @@ static void alc_fixup_hp_gpio_led(struct hda_codec *codec, unsigned int micmute_mask) { struct alc_spec *spec = codec->spec; + int err;
alc_fixup_gpio(codec, action, mute_mask | micmute_mask);
@@ -4122,6 +4144,13 @@ 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 } }
On Thu, 30 Apr 2020 15:52:07 +0200, Kai-Heng Feng wrote:
Currently DMIC controls micmute LED via "audio mute LED trigger".
However, unlike Dell and Lenovo platforms, HP platforms don't provide a way to control micmute LED via ACPI, it's controlled by HDA codec instead.
So let's register an LED class for micmute so other subsystems like DMIC can facilitate the codec-controlled LED.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
v2:
- Only compile the code when CONFIG_LEDS_TRIGGER_AUDIO is reachable.
Applied to for-next branch. Thanks.
Takashi
On Thu, 30 Apr 2020 10:32:51 +0200, Kai-Heng Feng wrote:
Currently mute LED and micmute LED share the same GPIO polarity.
So split the polarity for mute and micmute, in case they have different polarities.
Signed-off-by: Kai-Heng Feng kai.heng.feng@canonical.com
Applied to for-next branch. Thanks.
Takashi
participants (2)
-
Kai-Heng Feng
-
Takashi Iwai