Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 323daef8 authored by Takashi Iwai's avatar Takashi Iwai Committed by Sasha Levin
Browse files

ALSA: hda/realtek - Clean up mute/mic GPIO LED handling



[ Upstream commit 0f32fd1900e6b972f289416dbd75e92772b630cb ]

There are a few duplicated codes handling the mute and mic-mute LEDs
via GPIO pins.  Let's consolidate to single helpers.  Here we
introduced two new fields to alc_spec, gpio_mute_led_mask and
gpio_mic_led_mask, to contain the bit mask to set/clear.  Also,
mute_led_polarity is evaluated as well.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent e4477a4b
Loading
Loading
Loading
Loading
+40 −41
Original line number Diff line number Diff line
@@ -96,6 +96,8 @@ struct alc_spec {
	hda_nid_t cap_mute_led_nid;

	unsigned int gpio_led; /* used for alc269_fixup_hp_gpio_led() */
	unsigned int gpio_mute_led_mask;
	unsigned int gpio_mic_led_mask;

	hda_nid_t headset_mic_pin;
	hda_nid_t headphone_mic_pin;
@@ -3322,41 +3324,45 @@ static void alc269_fixup_hp_mute_led_mic2(struct hda_codec *codec,
	}
}

/* turn on/off mute LED per vmaster hook */
static void alc269_fixup_hp_gpio_mute_hook(void *private_data, int enabled)
/* update LED status via GPIO */
static void alc_update_gpio_led(struct hda_codec *codec, unsigned int mask,
				bool enabled)
{
	struct hda_codec *codec = private_data;
	struct alc_spec *spec = codec->spec;
	unsigned int oldval = spec->gpio_led;

	if (spec->mute_led_polarity)
		enabled = !enabled;

	if (enabled)
		spec->gpio_led &= ~0x08;
		spec->gpio_led &= ~mask;
	else
		spec->gpio_led |= 0x08;
		spec->gpio_led |= mask;
	if (spec->gpio_led != oldval)
		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
				    spec->gpio_led);
}

/* turn on/off mic-mute LED per capture hook */
static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec,
/* turn on/off mute LED via GPIO per vmaster hook */
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);
}

/* turn on/off mic-mute LED via GPIO per capture hook */
static void alc_fixup_gpio_mic_mute_hook(struct hda_codec *codec,
					 struct snd_kcontrol *kcontrol,
					 struct snd_ctl_elem_value *ucontrol)
{
	struct alc_spec *spec = codec->spec;
	unsigned int oldval = spec->gpio_led;

	if (!ucontrol)
		return;

	if (ucontrol->value.integer.value[0] ||
	    ucontrol->value.integer.value[1])
		spec->gpio_led &= ~0x10;
	else
		spec->gpio_led |= 0x10;
	if (spec->gpio_led != oldval)
		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
				    spec->gpio_led);
	if (ucontrol)
		alc_update_gpio_led(codec, spec->gpio_mic_led_mask,
				    ucontrol->value.integer.value[0] ||
				    ucontrol->value.integer.value[1]);
}

static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
@@ -3370,9 +3376,12 @@ static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
	};

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
		spec->gen.cap_sync_hook = alc269_fixup_hp_gpio_mic_mute_hook;
		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
		spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
		spec->gpio_led = 0;
		spec->mute_led_polarity = 0;
		spec->gpio_mute_led_mask = 0x08;
		spec->gpio_mic_led_mask = 0x10;
		snd_hda_add_verbs(codec, gpio_init);
	}
}
@@ -3414,9 +3423,11 @@ static void alc269_fixup_hp_gpio_mic1_led(struct hda_codec *codec,
	};

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
		spec->gpio_led = 0;
		spec->mute_led_polarity = 0;
		spec->gpio_mute_led_mask = 0x08;
		spec->cap_mute_led_nid = 0x18;
		snd_hda_add_verbs(codec, gpio_init);
		codec->power_filter = led_power_filter;
@@ -3435,9 +3446,11 @@ static void alc280_fixup_hp_gpio4(struct hda_codec *codec,
	};

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->gen.vmaster_mute.hook = alc269_fixup_hp_gpio_mute_hook;
		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
		spec->gen.cap_sync_hook = alc269_fixup_hp_cap_mic_mute_hook;
		spec->gpio_led = 0;
		spec->mute_led_polarity = 0;
		spec->gpio_mute_led_mask = 0x08;
		spec->cap_mute_led_nid = 0x18;
		snd_hda_add_verbs(codec, gpio_init);
		codec->power_filter = led_power_filter;
@@ -5905,22 +5918,6 @@ static void alc_fixup_bass_chmap(struct hda_codec *codec,
	}
}

/* turn on/off mute LED per vmaster hook */
static void alc662_led_gpio1_mute_hook(void *private_data, int enabled)
{
	struct hda_codec *codec = private_data;
	struct alc_spec *spec = codec->spec;
	unsigned int oldval = spec->gpio_led;

	if (enabled)
		spec->gpio_led |= 0x01;
	else
		spec->gpio_led &= ~0x01;
	if (spec->gpio_led != oldval)
		snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
				    spec->gpio_led);
}

/* avoid D3 for keeping GPIO up */
static unsigned int gpio_led_power_filter(struct hda_codec *codec,
					  hda_nid_t nid,
@@ -5943,8 +5940,10 @@ static void alc662_fixup_led_gpio1(struct hda_codec *codec,
	};

	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
		spec->gen.vmaster_mute.hook = alc662_led_gpio1_mute_hook;
		spec->gen.vmaster_mute.hook = alc_fixup_gpio_mute_hook;
		spec->gpio_led = 0;
		spec->mute_led_polarity = 1;
		spec->gpio_mute_led_mask = 0x01;
		snd_hda_add_verbs(codec, gpio_init);
		codec->power_filter = gpio_led_power_filter;
	}