On this machine, the mic mute hotkey is connected to GPIO2. We therefore
create an extra input device for this key.
Also enable LEDs connected to GPIO3 and GPIO4.
(Note: if this patch is backported to older kernels, where KEY_MIC_MUTE is
not available, change the KEY_MIC_MUTE to KEY_F20, which was previously used
for mic mute keys.)
On this machine, the mic mute hotkey is connected to GPIO2. We therefore
create an extra input device for this key.
Also enable LEDs connected to GPIO3 and GPIO4.
(Note: if this patch is backported to older kernels, where KEY_MIC_MUTE is
not available, change the KEY_MIC_MUTE to KEY_F20, which was previously used
for mic mute keys.)
BugLink: https:/ /bugs.launchpad .net/bugs/ 1408295 pci/hda/ patch_realtek. c | 86 +++++++ +++++++ +++++++ +++++++ +++++++ +++++++ +
Tested-by: Keng-Yu Lin <email address hidden>
Signed-off-by: David Henningsson <email address hidden>
---
sound/
1 file changed, 86 insertions(+)
diff --git a/sound/ pci/hda/ patch_realtek. c b/sound/ pci/hda/ patch_realtek. c pci/hda/ patch_realtek. c pci/hda/ patch_realtek. c
index 65f1f4e..3338c75 100644
--- a/sound/
+++ b/sound/
@@ -29,6 +29,7 @@
#include <linux/pci.h>
#include <linux/dmi.h>
#include <linux/module.h>
+#include <linux/input.h>
#include <sound/core.h>
#include <sound/jack.h>
#include "hda_codec.h"
@@ -120,6 +121,8 @@ struct alc_spec {
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;
unsigned int coef0;
+
+ struct input_dev *kb_dev;
};
/* fixup_hp_ gpio4(struct hda_codec *codec,
@@ -3472,6 +3475,83 @@ static void alc280_
}
}
+static void gpio2_mic_ hotkey_ event(struct hda_codec *codec, key(spec- >kb_dev, KEY_MICMUTE, 1); spec->kb_ dev); key(spec- >kb_dev, KEY_MICMUTE, 0); spec->kb_ dev); fixup_hp_ gpio2_mic_ hotkey( struct hda_codec *codec, SET_GPIO_ MASK, 0x1e }, SET_GPIO_ DIRECTION, 0x1a }, SET_GPIO_ DATA, 0x02 }, ACT_PRE_ PROBE) { device( ); allocate_ device) \n"); dev->evbit[ 0] = BIT_MASK(EV_KEY); dev->keybit[ BIT_WORD( KEY_MICMUTE) ] = BIT_MASK( KEY_MICMUTE) ; register_ device( spec->kb_ dev)) { "input_ register_ device failed\n"); device( spec->kb_ dev); add_verbs( codec, gpio_init); codec_write_ cache(codec, codec->afg, 0, SET_GPIO_ UNSOLICITED_ RSP_MASK, 0x04); jack_detect_ enable_ callback( codec, codec->afg, hotkey_ event); vmaster_ mute.hook = alc_fixup_ gpio_mute_ hook; cap_sync_ hook = alc_fixup_ gpio_mic_ mute_hook; led_polarity = 0; mute_led_ mask = 0x08; mic_led_ mask = 0x10; ACT_PROBE: hotkey_ event(codec, NULL); r_device( spec->kb_ dev); device( spec->kb_ dev); fixup_hp_ line1_mic1_ led(struct hda_codec *codec, FIXUP_ASPIRE_ V5_PINS, FIXUP_HP_ GPIO4, FIXUP_HP_ GPIO_LED, FIXUP_HP_ GPIO2_MIC_ HOTKEY,
+ struct hda_jack_callback *event)
+{
+ struct alc_spec *spec = codec->spec;
+
+ /* GPIO2 just toggles on a keypress/keyrelease cycle. Therefore
+ send both key on and key off event for every interrupt. */
+ input_report_
+ input_sync(
+ input_report_
+ input_sync(
+}
+
+static void alc280_
+ const struct hda_fixup *fix, int action)
+{
+ /* GPIO1 = set according to SKU external amp
+ GPIO2 = mic mute hotkey
+ GPIO3 = mute LED
+ GPIO4 = mic mute LED */
+ static const struct hda_verb gpio_init[] = {
+ { 0x01, AC_VERB_
+ { 0x01, AC_VERB_
+ { 0x01, AC_VERB_
+ {}
+ };
+
+ struct alc_spec *spec = codec->spec;
+
+ if (action == HDA_FIXUP_
+
+ spec->kb_dev = input_allocate_
+ if (!spec->kb_dev) {
+ snd_printk("Out of memory (input_
+ return;
+ }
+ spec->kb_dev->name = "Microphone Mute Button";
+ spec->kb_
+ spec->kb_
+ if (input_
+ snd_printk(
+ input_free_
+ spec->kb_dev = NULL;
+ return;
+ }
+
+ snd_hda_
+ snd_hda_
+ AC_VERB_
+ snd_hda_
+ gpio2_mic_
+
+ spec->gen.
+ spec->gen.
+ spec->gpio_led = 0;
+ spec->mute_
+ spec->gpio_
+ spec->gpio_
+ return;
+ }
+
+ if (!spec->kb_dev)
+ return;
+
+ switch (action) {
+ case HDA_FIXUP_
+ spec->init_amp = ALC_INIT_DEFAULT;
+ break;
+ case HDA_FIXUP_ACT_INIT:
+ gpio2_mic_
+ break;
+ case HDA_FIXUP_ACT_FREE:
+ input_unregiste
+ input_free_
+ }
+}
+
static void alc269_
const struct hda_fixup *fix, int action)
{
@@ -4341,6 +4421,7 @@ enum {
ALC282_
ALC280_
ALC286_
+ ALC280_
};
static const struct hda_fixup alc269_fixups[] = { fixup_hp_ gpio_led, FIXUP_HP_ GPIO2_MIC_ HOTKEY] = { fixup_hp_ gpio2_mic_ hotkey,
@@ -4814,6 +4895,10 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc286_
},
+ [ALC280_
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc280_
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = { QUIRK(0x103c, 0x1586, "HP", ALC269_ FIXUP_HP_ MUTE_LED_ MIC2), QUIRK(0x103c, 0x18e6, "HP", ALC269_ FIXUP_HP_ GPIO_LED) , QUIRK(0x103c, 0x218b, "HP", ALC269_ FIXUP_LIMIT_ INT_MIC_ BOOST_MUTE_ LED), QUIRK(0x103c, 0x225f, "HP", ALC280_ FIXUP_HP_ GPIO2_MIC_ HOTKEY) , QUIRK(0x103c, 0x2210, "HP", ALC269_ FIXUP_HP_ MUTE_LED_ MIC1), QUIRK(0x103c, 0x2214, "HP", ALC269_ FIXUP_HP_ MUTE_LED_ MIC1),
@@ -4843,6 +4928,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_
SND_PCI_
SND_PCI_
+ SND_PCI_
/* ALC282 */
SND_PCI_
SND_PCI_
--
1.9.1