[alsa-devel] [PATCH v2 1/2] ALSA: hda - Add mic mute hotkey quirk for Lenovo ThinkCentre AIO

Takashi Iwai tiwai at suse.de
Tue Dec 29 10:05:24 CET 2015


On Mon, 28 Dec 2015 04:35:24 +0100,
Hui Wang wrote:
> 
> From: Kailang <kailang at realtek.com>
> 
> The Lenovo ThinkCenter AIO uses Line2 (NID 0x1b) to implement the
> micmute hotkey, here we register an input device and use Line2 unsol
> event to collect the hotkey pressing or releasing.
> 
> In the meanwhile, the micmute led is controlled by GPIO2, so we
> use an existing function alc_fixup_gpio_mic_mute_hook() to control
> the led.
> 
> [Hui: And there are two places to register the input device, to make
> the code simple and clean, move the two same code sections into a
> function.]
> 
> Cc: <stable at vger.kernel.org>
> Signed-off-by: Kailang <kailang at realtek.com>
> Signed-off-by: Hui Wang <hui.wang at canonical.com>

Applied both patch.  Thanks.


Takashi

> ---
>  sound/pci/hda/patch_realtek.c | 84 ++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 71 insertions(+), 13 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index fe96428..257b839 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -3468,6 +3468,29 @@ static void gpio2_mic_hotkey_event(struct hda_codec *codec,
>  	input_sync(spec->kb_dev);
>  }
>  
> +static int alc_register_micmute_input_device(struct hda_codec *codec)
> +{
> +	struct alc_spec *spec = codec->spec;
> +
> +	spec->kb_dev = input_allocate_device();
> +	if (!spec->kb_dev) {
> +		codec_err(codec, "Out of memory (input_allocate_device)\n");
> +		return -ENOMEM;
> +	}
> +	spec->kb_dev->name = "Microphone Mute Button";
> +	spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
> +	spec->kb_dev->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE);
> +
> +	if (input_register_device(spec->kb_dev)) {
> +		codec_err(codec, "input_register_device failed\n");
> +		input_free_device(spec->kb_dev);
> +		spec->kb_dev = NULL;
> +		return -ENOMEM;
> +	}
> +
> +	return 0;
> +}
> +
>  static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
>  					     const struct hda_fixup *fix, int action)
>  {
> @@ -3485,20 +3508,8 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
>  	struct alc_spec *spec = codec->spec;
>  
>  	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
> -		spec->kb_dev = input_allocate_device();
> -		if (!spec->kb_dev) {
> -			codec_err(codec, "Out of memory (input_allocate_device)\n");
> +		if (alc_register_micmute_input_device(codec) != 0)
>  			return;
> -		}
> -		spec->kb_dev->name = "Microphone Mute Button";
> -		spec->kb_dev->evbit[0] = BIT_MASK(EV_KEY);
> -		spec->kb_dev->keybit[BIT_WORD(KEY_MICMUTE)] = BIT_MASK(KEY_MICMUTE);
> -		if (input_register_device(spec->kb_dev)) {
> -			codec_err(codec, "input_register_device failed\n");
> -			input_free_device(spec->kb_dev);
> -			spec->kb_dev = NULL;
> -			return;
> -		}
>  
>  		snd_hda_add_verbs(codec, gpio_init);
>  		snd_hda_codec_write_cache(codec, codec->core.afg, 0,
> @@ -3528,6 +3539,47 @@ static void alc280_fixup_hp_gpio2_mic_hotkey(struct hda_codec *codec,
>  	}
>  }
>  
> +static void alc233_fixup_lenovo_line2_mic_hotkey(struct hda_codec *codec,
> +					     const struct hda_fixup *fix, int action)
> +{
> +	/* Line2 = mic mute hotkey
> +	   GPIO2 = mic mute LED */
> +	static const struct hda_verb gpio_init[] = {
> +		{ 0x01, AC_VERB_SET_GPIO_MASK, 0x04 },
> +		{ 0x01, AC_VERB_SET_GPIO_DIRECTION, 0x04 },
> +		{}
> +	};
> +
> +	struct alc_spec *spec = codec->spec;
> +
> +	if (action == HDA_FIXUP_ACT_PRE_PROBE) {
> +		if (alc_register_micmute_input_device(codec) != 0)
> +			return;
> +
> +		snd_hda_add_verbs(codec, gpio_init);
> +		snd_hda_jack_detect_enable_callback(codec, 0x1b,
> +						    gpio2_mic_hotkey_event);
> +
> +		spec->gen.cap_sync_hook = alc_fixup_gpio_mic_mute_hook;
> +		spec->gpio_led = 0;
> +		spec->mute_led_polarity = 0;
> +		spec->gpio_mic_led_mask = 0x04;
> +		return;
> +	}
> +
> +	if (!spec->kb_dev)
> +		return;
> +
> +	switch (action) {
> +	case HDA_FIXUP_ACT_PROBE:
> +		spec->init_amp = ALC_INIT_DEFAULT;
> +		break;
> +	case HDA_FIXUP_ACT_FREE:
> +		input_unregister_device(spec->kb_dev);
> +		spec->kb_dev = NULL;
> +	}
> +}
> +
>  static void alc269_fixup_hp_line1_mic1_led(struct hda_codec *codec,
>  				const struct hda_fixup *fix, int action)
>  {
> @@ -4628,6 +4680,7 @@ enum {
>  	ALC275_FIXUP_DELL_XPS,
>  	ALC256_FIXUP_DELL_XPS_13_HEADPHONE_NOISE,
>  	ALC293_FIXUP_LENOVO_SPK_NOISE,
> +	ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
>  };
>  
>  static const struct hda_fixup alc269_fixups[] = {
> @@ -5237,6 +5290,10 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.chained = true,
>  		.chain_id = ALC269_FIXUP_THINKPAD_ACPI
>  	},
> +	[ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY] = {
> +		.type = HDA_FIXUP_FUNC,
> +		.v.func = alc233_fixup_lenovo_line2_mic_hotkey,
> +	},
>  };
>  
>  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
> @@ -5386,6 +5443,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>  	SND_PCI_QUIRK(0x17aa, 0x2223, "ThinkPad T550", ALC292_FIXUP_TPT440_DOCK),
>  	SND_PCI_QUIRK(0x17aa, 0x2226, "ThinkPad X250", ALC292_FIXUP_TPT440_DOCK),
>  	SND_PCI_QUIRK(0x17aa, 0x2233, "Thinkpad", ALC293_FIXUP_LENOVO_SPK_NOISE),
> +	SND_PCI_QUIRK(0x17aa, 0x30bb, "ThinkCentre AIO", ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY),
>  	SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
>  	SND_PCI_QUIRK(0x17aa, 0x3978, "IdeaPad Y410P", ALC269_FIXUP_NO_SHUTUP),
>  	SND_PCI_QUIRK(0x17aa, 0x5013, "Thinkpad", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
> -- 
> 1.9.1
> 


More information about the Alsa-devel mailing list