Commit 15509b63 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda: generic: Add vmaster mute LED helper



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: default avatarKai-Heng Feng <kai.heng.feng@canonical.com>
Link: https://lore.kernel.org/r/20200618110842.27238-9-tiwai@suse.de


Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent fe1a1621
Loading
Loading
Loading
Loading
+59 −12
Original line number Diff line number Diff line
@@ -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;
+3 −0
Original line number Diff line number Diff line
@@ -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));