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@xxxxxxxxxxxxx> Signed-off-by: Takashi Iwai <tiwai@xxxxxxx> --- 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