At Wed, 7 Jan 2015 15:50:13 +0100,
David Henningsson wrote:
>
> 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
> Tested-by: Keng-Yu Lin <email address hidden>
> Signed-off-by: David Henningsson <email address hidden>
> ---
>
> Changes since v1 (which was by mistake not posted to alsa-devel)
> - fixes according to Takashi's review comments
At Wed, 7 Jan 2015 15:50:13 +0100, /bugs.launchpad .net/bugs/ 1408295
David Henningsson wrote:
>
> 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:/
> Tested-by: Keng-Yu Lin <email address hidden>
> Signed-off-by: David Henningsson <email address hidden>
> ---
>
> Changes since v1 (which was by mistake not posted to alsa-devel)
> - fixes according to Takashi's review comments
Thanks, applied now.
Takashi
> hda/patch_ realtek. c | 88 +++++++ +++++++ +++++++ +++++++ +++++++ +++++++ + pci/hda/ patch_realtek. c b/sound/ pci/hda/ patch_realtek. c pci/hda/ patch_realtek. c pci/hda/ patch_realtek. c CONFIG_ INPUT) fixup_hp_ gpio4(struct hda_codec *codec, CONFIG_ INPUT) 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, CONFIG_ INPUT) 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)) { 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: 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, fixup_hp_ gpio_led, FIXUP_HP_ GPIO2_MIC_ HOTKEY] = { fixup_hp_ gpio2_mic_ hotkey, 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),
> sound/pci/
> 1 file changed, 88 insertions(+)
>
> diff --git a/sound/
> index 65f1f4e..09d2131 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,9 @@ struct alc_spec {
> hda_nid_t pll_nid;
> unsigned int pll_coef_idx, pll_coef_bit;
> unsigned int coef0;
> +#if IS_ENABLED(
> + struct input_dev *kb_dev;
> +#endif
> };
>
> /*
> @@ -3472,6 +3476,84 @@ static void alc280_
> }
> }
>
> +#if IS_ENABLED(
> +static void gpio2_mic_
> + 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(
> +}
> +#endif
> +
> +static void alc280_
> + const struct hda_fixup *fix, int action)
> +{
> +#if IS_ENABLED(
> + /* 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) {
> + codec_err(codec, "Out of memory (input_
> + return;
> + }
> + spec->kb_dev->name = "Microphone Mute Button";
> + spec->kb_
> + spec->kb_
> + if (input_
> + codec_err(codec, "input_
> + 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_FREE:
> + input_unregiste
> + input_free_
> + spec->kb_dev = NULL;
> + }
> +#endif
> +}
> +
> static void alc269_
> const struct hda_fixup *fix, int action)
> {
> @@ -4341,6 +4423,7 @@ enum {
> ALC282_
> ALC280_
> ALC286_
> + ALC280_
> };
>
> static const struct hda_fixup alc269_fixups[] = {
> @@ -4814,6 +4897,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[] = {
> @@ -4843,6 +4930,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
>