- patches.drivers/alsa-sp2-hda-033-Support-mute-LED-on-HP-AiO-buttons:
[opensuse:kernel-source.git] / patches.drivers / alsa-sp2-hda-033-Support-mute-LED-on-HP-AiO-buttons
1 From: Takashi Iwai <tiwai@suse.de>
2 Subject: [PATCH] ALSA: hda - Support mute LED on HP AiO buttons
3 Patch-mainline: TBD
4 References: bnc#808991
5
6 Signed-off-by: Takashi Iwai <tiwai@suse.de>
7
8 ---
9  sound/pci/hda/patch_realtek.c |   80 ++++++++++++++++++++++++++++++++++++++++++
10  1 file changed, 80 insertions(+)
11
12 --- a/sound/pci/hda/patch_realtek.c
13 +++ b/sound/pci/hda/patch_realtek.c
14 @@ -389,6 +389,7 @@ struct alc_spec {
15         void (*power_hook)(struct hda_codec *codec);
16  #endif
17         void (*shutup)(struct hda_codec *codec);
18 +       void (*capture_mute_hook)(struct hda_codec *codec, bool enabled);
19  
20         /* for pin sensing */
21         unsigned int jack_present: 1;
22 @@ -427,6 +428,8 @@ struct alc_spec {
23         const struct alc_fixup *fixup_list;
24         const char *fixup_name;
25  
26 +       unsigned int gpio_led;
27 +
28         /* multi-io */
29         int multi_ios;
30         struct alc_multi_io multi_io[4];
31 @@ -2780,6 +2783,15 @@ static int alc_cap_sw_get(struct snd_kco
32  static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
33                           struct snd_ctl_elem_value *ucontrol)
34  {
35 +       struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
36 +       struct alc_spec *spec = codec->spec;
37 +
38 +       if (spec->capture_mute_hook) {
39 +               bool enabled = ucontrol->value.integer.value[0] ||
40 +                       ucontrol->value.integer.value[1];
41 +               spec->capture_mute_hook(codec, enabled);
42 +       }
43 +
44         return alc_cap_getput_caller(kcontrol, ucontrol,
45                                      snd_hda_mixer_amp_switch_put, true);
46  }
47 @@ -14733,6 +14745,32 @@ static int alc269_mic2_mute_check_ps(str
48         }
49         return alc_check_power_status(codec, nid);
50  }
51 +
52 +static int alc269_hp_gpio_led(struct hda_codec *codec)
53 +{
54 +       switch (codec->subsystem_id) {
55 +       case 0x103c18e6:
56 +               return 1;
57 +       }
58 +       return 0;
59 +}
60 +
61 +static int alc269_hp_gpio_led_check_ps(struct hda_codec *codec, hda_nid_t nid)
62 +{
63 +       /* update mute-LED according to the speaker mute state */
64 +       if (nid == 0x01 || nid == 0x14) {
65 +               struct alc_spec *spec = codec->spec;
66 +               unsigned int oldval = spec->gpio_led;
67 +               if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
68 +                   HDA_AMP_MUTE)
69 +                       spec->gpio_led |= 0x08;
70 +               else
71 +                       spec->gpio_led &= ~0x08;
72 +               if (spec->gpio_led != oldval)
73 +                       snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, spec->gpio_led);
74 +       }
75 +       return alc_check_power_status(codec, nid);
76 +}
77  #endif /* CONFIG_SND_HDA_POWER_SAVE */
78  
79  static int alc275_setup_dual_adc(struct hda_codec *codec)
80 @@ -14922,6 +14960,40 @@ static void alc271_fixup_dmic(struct hda
81                 snd_hda_sequence_write(codec, verbs);
82  }
83  
84 +static void alc269_fixup_hp_gpio_mic_mute_hook(struct hda_codec *codec, bool enabled)
85 +{
86 +       struct alc_spec *spec = codec->spec;
87 +       int oldval = spec->gpio_led;
88 +
89 +       if (enabled)
90 +               spec->gpio_led &= ~0x10;
91 +       else
92 +               spec->gpio_led |= 0x10;
93 +       if (spec->gpio_led != oldval)
94 +               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
95 +                                   spec->gpio_led);
96 +}
97 +
98 +static void alc269_fixup_hp_gpio_led(struct hda_codec *codec,
99 +                                    const struct alc_fixup *fix, int action)
100 +{
101 +       struct alc_spec *spec = codec->spec;
102 +       switch (action) {
103 +       case ALC_FIXUP_ACT_PRE_PROBE:
104 +               spec->gpio_led = 0;
105 +               spec->capture_mute_hook = alc269_fixup_hp_gpio_mic_mute_hook;
106 +               snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
107 +                                         0x18);
108 +               snd_hda_codec_write_cache(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION,
109 +                                         0x18);
110 +               break;
111 +       case ALC_FIXUP_ACT_INIT:
112 +               snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
113 +                                   spec->gpio_led);
114 +               break;
115 +       }
116 +}
117 +
118  enum {
119         ALC269_FIXUP_SONY_VAIO,
120         ALC275_FIXUP_SONY_VAIO_GPIO2,
121 @@ -14930,6 +15002,7 @@ enum {
122         ALC269_FIXUP_ASUS_G73JW,
123         ALC269_FIXUP_LENOVO_EAPD,
124         ALC275_FIXUP_SONY_HWEQ,
125 +       ALC269_FIXUP_HP_GPIO_LED,
126         ALC271_FIXUP_DMIC,
127  };
128  
129 @@ -14989,9 +15062,14 @@ static const struct alc_fixup alc269_fix
130                 .type = ALC_FIXUP_FUNC,
131                 .v.func = alc271_fixup_dmic,
132         },
133 +       [ALC269_FIXUP_HP_GPIO_LED] = {
134 +               .type = ALC_FIXUP_FUNC,
135 +               .v.func = alc269_fixup_hp_gpio_led,
136 +       },
137  };
138  
139  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
140 +       SND_PCI_QUIRK(0x103c, 0x18e6, "HP", ALC269_FIXUP_HP_GPIO_LED),
141         SND_PCI_QUIRK(0x104d, 0x9073, "Sony VAIO", ALC275_FIXUP_SONY_VAIO_GPIO2),
142         SND_PCI_QUIRK(0x104d, 0x907b, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
143         SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
144 @@ -15391,6 +15469,8 @@ static int patch_alc269(struct hda_codec
145                 spec->loopback.amplist = alc269_loopbacks;
146         if (alc269_mic2_for_mute_led(codec))
147                 codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
148 +       if (alc269_hp_gpio_led(codec))
149 +               codec->patch_ops.check_power_status = alc269_hp_gpio_led_check_ps;
150  #endif
151  
152         return 0;