2021-05-07 02:55:10

by Daniel Cordova A

[permalink] [raw]
Subject: [PATCH] ALSA: hda: fixup headset for ASUS GU502 laptop

The GU502 requires a few steps to make headset i/o works properly:
pincfg, verbs to unmute headphone out and callback to toggle output
between speakers and headphone using jack.

Signed-off-by: Daniel Cordova A. <[email protected]>
---
sound/pci/hda/patch_realtek.c | 62 +++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index bd7bfd7c9ee7..d91ab7521496 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -6210,6 +6210,35 @@ static void alc294_fixup_gx502_hp(struct hda_codec *codec,
}
}

+static void alc294_gu502_toggle_output(struct hda_codec *codec,
+ struct hda_jack_callback *cb)
+{
+ /* Windows sets 0x10 to 0x8420 for Node 0x20 which is
+ * responsible from changes between speakers and headphones
+ */
+ if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
+ alc_write_coef_idx(codec, 0x10, 0x8420);
+ else
+ alc_write_coef_idx(codec, 0x10, 0x0a20);
+}
+
+static void alc294_fixup_gu502_hp(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (!is_jack_detectable(codec, 0x21))
+ return;
+
+ switch (action) {
+ case HDA_FIXUP_ACT_PRE_PROBE:
+ snd_hda_jack_detect_enable_callback(codec, 0x21,
+ alc294_gu502_toggle_output);
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ alc294_gu502_toggle_output(codec, NULL);
+ break;
+ }
+}
+
static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -6427,6 +6456,9 @@ enum {
ALC294_FIXUP_ASUS_GX502_HP,
ALC294_FIXUP_ASUS_GX502_PINS,
ALC294_FIXUP_ASUS_GX502_VERBS,
+ ALC294_FIXUP_ASUS_GU502_HP,
+ ALC294_FIXUP_ASUS_GU502_PINS,
+ ALC294_FIXUP_ASUS_GU502_VERBS,
ALC285_FIXUP_HP_GPIO_LED,
ALC285_FIXUP_HP_MUTE_LED,
ALC236_FIXUP_HP_GPIO_LED,
@@ -7665,6 +7697,35 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc294_fixup_gx502_hp,
},
+ [ALC294_FIXUP_ASUS_GU502_PINS] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x19, 0x01a11050 }, /* rear HP mic */
+ { 0x1a, 0x01a11830 }, /* rear external mic */
+ { 0x21, 0x012110f0 }, /* rear HP out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_GU502_VERBS
+ },
+ [ALC294_FIXUP_ASUS_GU502_VERBS] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* set 0x15 to HP-OUT ctrl */
+ { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
+ /* unmute the 0x15 amp */
+ { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
+ /* set 0x1b to HP-OUT */
+ { 0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC294_FIXUP_ASUS_GU502_HP
+ },
+ [ALC294_FIXUP_ASUS_GU502_HP] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc294_fixup_gu502_hp,
+ },
[ALC294_FIXUP_ASUS_COEF_1B] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -8163,6 +8224,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
+ SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
--
2.31.1


2021-05-07 11:42:12

by Takashi Iwai

[permalink] [raw]
Subject: Re: [PATCH] ALSA: hda: fixup headset for ASUS GU502 laptop

On Thu, 06 May 2021 23:21:05 +0200,
Daniel Cordova A wrote:
>
> The GU502 requires a few steps to make headset i/o works properly:
> pincfg, verbs to unmute headphone out and callback to toggle output
> between speakers and headphone using jack.
>
> Signed-off-by: Daniel Cordova A. <[email protected]>

Just a minor nitpick: could you put the quirk entry in the PCI SSID
order?


thanks,

Takashi

> ---
> sound/pci/hda/patch_realtek.c | 62 +++++++++++++++++++++++++++++++++++
> 1 file changed, 62 insertions(+)
>
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index bd7bfd7c9ee7..d91ab7521496 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -6210,6 +6210,35 @@ static void alc294_fixup_gx502_hp(struct hda_codec *codec,
> }
> }
>
> +static void alc294_gu502_toggle_output(struct hda_codec *codec,
> + struct hda_jack_callback *cb)
> +{
> + /* Windows sets 0x10 to 0x8420 for Node 0x20 which is
> + * responsible from changes between speakers and headphones
> + */
> + if (snd_hda_jack_detect_state(codec, 0x21) == HDA_JACK_PRESENT)
> + alc_write_coef_idx(codec, 0x10, 0x8420);
> + else
> + alc_write_coef_idx(codec, 0x10, 0x0a20);
> +}
> +
> +static void alc294_fixup_gu502_hp(struct hda_codec *codec,
> + const struct hda_fixup *fix, int action)
> +{
> + if (!is_jack_detectable(codec, 0x21))
> + return;
> +
> + switch (action) {
> + case HDA_FIXUP_ACT_PRE_PROBE:
> + snd_hda_jack_detect_enable_callback(codec, 0x21,
> + alc294_gu502_toggle_output);
> + break;
> + case HDA_FIXUP_ACT_INIT:
> + alc294_gu502_toggle_output(codec, NULL);
> + break;
> + }
> +}
> +
> static void alc285_fixup_hp_gpio_amp_init(struct hda_codec *codec,
> const struct hda_fixup *fix, int action)
> {
> @@ -6427,6 +6456,9 @@ enum {
> ALC294_FIXUP_ASUS_GX502_HP,
> ALC294_FIXUP_ASUS_GX502_PINS,
> ALC294_FIXUP_ASUS_GX502_VERBS,
> + ALC294_FIXUP_ASUS_GU502_HP,
> + ALC294_FIXUP_ASUS_GU502_PINS,
> + ALC294_FIXUP_ASUS_GU502_VERBS,
> ALC285_FIXUP_HP_GPIO_LED,
> ALC285_FIXUP_HP_MUTE_LED,
> ALC236_FIXUP_HP_GPIO_LED,
> @@ -7665,6 +7697,35 @@ static const struct hda_fixup alc269_fixups[] = {
> .type = HDA_FIXUP_FUNC,
> .v.func = alc294_fixup_gx502_hp,
> },
> + [ALC294_FIXUP_ASUS_GU502_PINS] = {
> + .type = HDA_FIXUP_PINS,
> + .v.pins = (const struct hda_pintbl[]) {
> + { 0x19, 0x01a11050 }, /* rear HP mic */
> + { 0x1a, 0x01a11830 }, /* rear external mic */
> + { 0x21, 0x012110f0 }, /* rear HP out */
> + { }
> + },
> + .chained = true,
> + .chain_id = ALC294_FIXUP_ASUS_GU502_VERBS
> + },
> + [ALC294_FIXUP_ASUS_GU502_VERBS] = {
> + .type = HDA_FIXUP_VERBS,
> + .v.verbs = (const struct hda_verb[]) {
> + /* set 0x15 to HP-OUT ctrl */
> + { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
> + /* unmute the 0x15 amp */
> + { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000 },
> + /* set 0x1b to HP-OUT */
> + { 0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
> + { }
> + },
> + .chained = true,
> + .chain_id = ALC294_FIXUP_ASUS_GU502_HP
> + },
> + [ALC294_FIXUP_ASUS_GU502_HP] = {
> + .type = HDA_FIXUP_FUNC,
> + .v.func = alc294_fixup_gu502_hp,
> + },
> [ALC294_FIXUP_ASUS_COEF_1B] = {
> .type = HDA_FIXUP_VERBS,
> .v.verbs = (const struct hda_verb[]) {
> @@ -8163,6 +8224,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
> SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
> SND_PCI_QUIRK(0x1043, 0x17d1, "ASUS UX431FL", ALC294_FIXUP_ASUS_DUAL_SPK),
> SND_PCI_QUIRK(0x1043, 0x1881, "ASUS Zephyrus S/M", ALC294_FIXUP_ASUS_GX502_PINS),
> + SND_PCI_QUIRK(0x1043, 0x1e51, "ASUS Zephyrus M15", ALC294_FIXUP_ASUS_GU502_PINS),
> SND_PCI_QUIRK(0x1043, 0x18b1, "Asus MJ401TA", ALC256_FIXUP_ASUS_HEADSET_MIC),
> SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
> SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
> --
> 2.31.1
>