Commit 56b26497 authored by Takashi Iwai's avatar Takashi Iwai

ALSA: hda/conexant: Add quirk for mute LED control on HP ZBook G5

The mute and mic-mute LEDs on HP ZBook Studio G5 are controlled via
GPIO bits 0x10 and 0x20, respectively, and we need the extra setup for
those.

As the similar code is already present for other HP models but with
different GPIO pins, this patch factors out the common helper code and
applies those GPIO values for each model.

BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=211893
Cc: <stable@vger.kernel.org>
Link: https://lore.kernel.org/r/20210306095018.11746-1-tiwai@suse.deSigned-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 06abcb18
...@@ -149,6 +149,21 @@ static int cx_auto_vmaster_mute_led(struct led_classdev *led_cdev, ...@@ -149,6 +149,21 @@ static int cx_auto_vmaster_mute_led(struct led_classdev *led_cdev,
return 0; return 0;
} }
static void cxt_init_gpio_led(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
unsigned int mask = spec->gpio_mute_led_mask | spec->gpio_mic_led_mask;
if (mask) {
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
mask);
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
mask);
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
spec->gpio_led);
}
}
static int cx_auto_init(struct hda_codec *codec) static int cx_auto_init(struct hda_codec *codec)
{ {
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
...@@ -156,6 +171,7 @@ static int cx_auto_init(struct hda_codec *codec) ...@@ -156,6 +171,7 @@ static int cx_auto_init(struct hda_codec *codec)
if (!spec->dynamic_eapd) if (!spec->dynamic_eapd)
cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true); cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
cxt_init_gpio_led(codec);
snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT); snd_hda_apply_fixup(codec, HDA_FIXUP_ACT_INIT);
return 0; return 0;
...@@ -215,6 +231,7 @@ enum { ...@@ -215,6 +231,7 @@ enum {
CXT_FIXUP_HP_SPECTRE, CXT_FIXUP_HP_SPECTRE,
CXT_FIXUP_HP_GATE_MIC, CXT_FIXUP_HP_GATE_MIC,
CXT_FIXUP_MUTE_LED_GPIO, CXT_FIXUP_MUTE_LED_GPIO,
CXT_FIXUP_HP_ZBOOK_MUTE_LED,
CXT_FIXUP_HEADSET_MIC, CXT_FIXUP_HEADSET_MIC,
CXT_FIXUP_HP_MIC_NO_PRESENCE, CXT_FIXUP_HP_MIC_NO_PRESENCE,
}; };
...@@ -654,31 +671,36 @@ static int cxt_gpio_micmute_update(struct led_classdev *led_cdev, ...@@ -654,31 +671,36 @@ static int cxt_gpio_micmute_update(struct led_classdev *led_cdev,
return 0; return 0;
} }
static void cxt_setup_mute_led(struct hda_codec *codec,
static void cxt_fixup_mute_led_gpio(struct hda_codec *codec, unsigned int mute, unsigned int mic_mute)
const struct hda_fixup *fix, int action)
{ {
struct conexant_spec *spec = codec->spec; struct conexant_spec *spec = codec->spec;
static const struct hda_verb gpio_init[] = {
{ 0x01, AC_VERB_SET_GPIO_MASK, 0x03 },
{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03 },
{}
};
if (action == HDA_FIXUP_ACT_PRE_PROBE) { spec->gpio_led = 0;
spec->mute_led_polarity = 0;
if (mute) {
snd_hda_gen_add_mute_led_cdev(codec, cxt_gpio_mute_update); snd_hda_gen_add_mute_led_cdev(codec, cxt_gpio_mute_update);
spec->gpio_led = 0; spec->gpio_mute_led_mask = mute;
spec->mute_led_polarity = 0; }
spec->gpio_mute_led_mask = 0x01; if (mic_mute) {
spec->gpio_mic_led_mask = 0x02;
snd_hda_gen_add_micmute_led_cdev(codec, cxt_gpio_micmute_update); snd_hda_gen_add_micmute_led_cdev(codec, cxt_gpio_micmute_update);
spec->gpio_mic_led_mask = mic_mute;
} }
snd_hda_add_verbs(codec, gpio_init);
if (spec->gpio_led)
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
spec->gpio_led);
} }
static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE)
cxt_setup_mute_led(codec, 0x01, 0x02);
}
static void cxt_fixup_hp_zbook_mute_led(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
if (action == HDA_FIXUP_ACT_PRE_PROBE)
cxt_setup_mute_led(codec, 0x10, 0x20);
}
/* ThinkPad X200 & co with cxt5051 */ /* ThinkPad X200 & co with cxt5051 */
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = { static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
...@@ -839,6 +861,10 @@ static const struct hda_fixup cxt_fixups[] = { ...@@ -839,6 +861,10 @@ static const struct hda_fixup cxt_fixups[] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_mute_led_gpio, .v.func = cxt_fixup_mute_led_gpio,
}, },
[CXT_FIXUP_HP_ZBOOK_MUTE_LED] = {
.type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_hp_zbook_mute_led,
},
[CXT_FIXUP_HEADSET_MIC] = { [CXT_FIXUP_HEADSET_MIC] = {
.type = HDA_FIXUP_FUNC, .type = HDA_FIXUP_FUNC,
.v.func = cxt_fixup_headset_mic, .v.func = cxt_fixup_headset_mic,
...@@ -917,6 +943,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = { ...@@ -917,6 +943,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO), SND_PCI_QUIRK(0x103c, 0x8402, "HP ProBook 645 G4", CXT_FIXUP_MUTE_LED_GPIO),
SND_PCI_QUIRK(0x103c, 0x8427, "HP ZBook Studio G5", CXT_FIXUP_HP_ZBOOK_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8456, "HP Z2 G4 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE), SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
...@@ -956,6 +983,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { ...@@ -956,6 +983,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
{ .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" }, { .id = CXT_FIXUP_MUTE_LED_EAPD, .name = "mute-led-eapd" },
{ .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" }, { .id = CXT_FIXUP_HP_DOCK, .name = "hp-dock" },
{ .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" }, { .id = CXT_FIXUP_MUTE_LED_GPIO, .name = "mute-led-gpio" },
{ .id = CXT_FIXUP_HP_ZBOOK_MUTE_LED, .name = "hp-zbook-mute-led" },
{ .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" }, { .id = CXT_FIXUP_HP_MIC_NO_PRESENCE, .name = "hp-mic-fix" },
{} {}
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment