ALSA: hda: generic: Add a helper for mic-mute LED with LED classdev

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>
Link: https://lore.kernel.org/r/20200618110842.27238-3-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c95ccffb..419cfbd 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
  */