[UTOPIC,1/3] ALSA: hda - add mic mute led hook for dell machines
diff mbox

Message ID 1423211015-18866-1-git-send-email-hui.wang@canonical.com
State New
Headers show

Commit Message

Hui Wang Feb. 6, 2015, 8:23 a.m. UTC
BugLink: http://bugs.launchpad.net/bugs/1418832

commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream

The mic mute led on dell laptops is controlled by the wmi driver.
Followed this part being merged to the kernel, we add the mic mute led
hook in the hda driver.

Signed-off-by: David Henningsson <david.henningsson@canonical.com>
Signed-off-by: Hui Wang <hui.wang@canonical.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>

Conflicts:
	sound/pci/hda/patch_realtek.c

Signed-off-by: Hui Wang <hui.wang@canonical.com>
---
 sound/pci/hda/dell_wmi_helper.c | 76 +++++++++++++++++++++++++++++++++++++++++
 sound/pci/hda/patch_realtek.c   | 12 +++++++
 2 files changed, 88 insertions(+)
 create mode 100644 sound/pci/hda/dell_wmi_helper.c

Comments

Chris J Arges Feb. 6, 2015, 1:41 p.m. UTC | #1
Hi,
Need to add (backported from XXXXX) in patches 1/2 (cherry-pick -x can
do this in the future). The backports make sense because the enum is
slightly different. Looks good overall,

Acked-by: <chris.j.arges@canonical.com>

--chris

On 02/06/2015 02:23 AM, Hui Wang wrote:
> BugLink: http://bugs.launchpad.net/bugs/1418832
> 
> commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream
> 
> The mic mute led on dell laptops is controlled by the wmi driver.
> Followed this part being merged to the kernel, we add the mic mute led
> hook in the hda driver.
> 
> Signed-off-by: David Henningsson <david.henningsson@canonical.com>
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> 
> Conflicts:
> 	sound/pci/hda/patch_realtek.c
> 
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> ---
>  sound/pci/hda/dell_wmi_helper.c | 76 +++++++++++++++++++++++++++++++++++++++++
>  sound/pci/hda/patch_realtek.c   | 12 +++++++
>  2 files changed, 88 insertions(+)
>  create mode 100644 sound/pci/hda/dell_wmi_helper.c
> 
> diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
> new file mode 100644
> index 0000000..9c22f95
> --- /dev/null
> +++ b/sound/pci/hda/dell_wmi_helper.c
> @@ -0,0 +1,76 @@
> +/* Helper functions for Dell Mic Mute LED control;
> + * to be included from codec driver
> + */
> +
> +#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
> +#include <linux/dell-led.h>
> +
> +static int dell_led_value;
> +static int (*dell_led_set_func)(int, int);
> +static void (*dell_old_cap_hook)(struct hda_codec *,
> +			         struct snd_kcontrol *,
> +				 struct snd_ctl_elem_value *);
> +
> +static void update_dell_wmi_micmute_led(struct hda_codec *codec,
> +				        struct snd_kcontrol *kcontrol,
> +					struct snd_ctl_elem_value *ucontrol)
> +{
> +	if (dell_old_cap_hook)
> +		dell_old_cap_hook(codec, kcontrol, ucontrol);
> +
> +	if (!ucontrol || !dell_led_set_func)
> +		return;
> +	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
> +		/* TODO: How do I verify if it's a mono or stereo here? */
> +		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
> +		if (val == dell_led_value)
> +			return;
> +		dell_led_value = val;
> +		if (dell_led_set_func)
> +			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
> +	}
> +}
> +
> +
> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
> +			       const struct hda_fixup *fix, int action)
> +{
> +	struct alc_spec *spec = codec->spec;
> +	bool removefunc = false;
> +
> +	if (action == HDA_FIXUP_ACT_PROBE) {
> +		if (!dell_led_set_func)
> +			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
> +		if (!dell_led_set_func) {
> +			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
> +			return;
> +		}
> +
> +		removefunc = true;
> +		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
> +			dell_led_value = 0;
> +			if (spec->gen.num_adc_nids > 1)
> +				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
> +			else {
> +				dell_old_cap_hook = spec->gen.cap_sync_hook;
> +				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
> +				removefunc = false;
> +			}
> +		}
> +
> +	}
> +
> +	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
> +		symbol_put(dell_app_wmi_led_set);
> +		dell_led_set_func = NULL;
> +		dell_old_cap_hook = NULL;
> +	}
> +}
> +
> +#else /* CONFIG_LEDS_DELL_NETBOOKS */
> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
> +			       const struct hda_fixup *fix, int action)
> +{
> +}
> +
> +#endif /* CONFIG_LEDS_DELL_NETBOOKS */
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index e517902..d70f130 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -4249,6 +4249,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
>  /* for hda_fixup_thinkpad_acpi() */
>  #include "thinkpad_helper.c"
>  
> +/* for dell wmi mic mute led */
> +#include "dell_wmi_helper.c"
> +
>  enum {
>  	ALC269_FIXUP_SONY_VAIO,
>  	ALC275_FIXUP_SONY_VAIO_GPIO2,
> @@ -4310,6 +4313,7 @@ enum {
>  	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
>  	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
>  	ALC292_FIXUP_TPT440_DOCK,
> +	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
>  };
>  
>  static const struct hda_fixup alc269_fixups[] = {
> @@ -4736,6 +4740,12 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.chained = true,
>  		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
>  	},
> +	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
> +		.type = HDA_FIXUP_FUNC,
> +		.v.func = alc_fixup_dell_wmi,
> +		.chained_before = true,
> +		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
> +	},
>  };
>  
>  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
> @@ -4779,10 +4789,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>  	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
> +	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>  	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
>  	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
> +	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>  	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
>  	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
>
Brad Figg Feb. 6, 2015, 5:23 p.m. UTC | #2
On Fri, Feb 06, 2015 at 04:23:33PM +0800, Hui Wang wrote:
> BugLink: http://bugs.launchpad.net/bugs/1418832
> 
> commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream
> 
> The mic mute led on dell laptops is controlled by the wmi driver.
> Followed this part being merged to the kernel, we add the mic mute led
> hook in the hda driver.
> 
> Signed-off-by: David Henningsson <david.henningsson@canonical.com>
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> 
> Conflicts:
> 	sound/pci/hda/patch_realtek.c
> 
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> ---
>  sound/pci/hda/dell_wmi_helper.c | 76 +++++++++++++++++++++++++++++++++++++++++
>  sound/pci/hda/patch_realtek.c   | 12 +++++++
>  2 files changed, 88 insertions(+)
>  create mode 100644 sound/pci/hda/dell_wmi_helper.c
> 
> diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
> new file mode 100644
> index 0000000..9c22f95
> --- /dev/null
> +++ b/sound/pci/hda/dell_wmi_helper.c
> @@ -0,0 +1,76 @@
> +/* Helper functions for Dell Mic Mute LED control;
> + * to be included from codec driver
> + */
> +
> +#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
> +#include <linux/dell-led.h>
> +
> +static int dell_led_value;
> +static int (*dell_led_set_func)(int, int);
> +static void (*dell_old_cap_hook)(struct hda_codec *,
> +			         struct snd_kcontrol *,
> +				 struct snd_ctl_elem_value *);
> +
> +static void update_dell_wmi_micmute_led(struct hda_codec *codec,
> +				        struct snd_kcontrol *kcontrol,
> +					struct snd_ctl_elem_value *ucontrol)
> +{
> +	if (dell_old_cap_hook)
> +		dell_old_cap_hook(codec, kcontrol, ucontrol);
> +
> +	if (!ucontrol || !dell_led_set_func)
> +		return;
> +	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
> +		/* TODO: How do I verify if it's a mono or stereo here? */
> +		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
> +		if (val == dell_led_value)
> +			return;
> +		dell_led_value = val;
> +		if (dell_led_set_func)
> +			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
> +	}
> +}
> +
> +
> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
> +			       const struct hda_fixup *fix, int action)
> +{
> +	struct alc_spec *spec = codec->spec;
> +	bool removefunc = false;
> +
> +	if (action == HDA_FIXUP_ACT_PROBE) {
> +		if (!dell_led_set_func)
> +			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
> +		if (!dell_led_set_func) {
> +			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
> +			return;
> +		}
> +
> +		removefunc = true;
> +		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
> +			dell_led_value = 0;
> +			if (spec->gen.num_adc_nids > 1)
> +				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
> +			else {
> +				dell_old_cap_hook = spec->gen.cap_sync_hook;
> +				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
> +				removefunc = false;
> +			}
> +		}
> +
> +	}
> +
> +	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
> +		symbol_put(dell_app_wmi_led_set);
> +		dell_led_set_func = NULL;
> +		dell_old_cap_hook = NULL;
> +	}
> +}
> +
> +#else /* CONFIG_LEDS_DELL_NETBOOKS */
> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
> +			       const struct hda_fixup *fix, int action)
> +{
> +}
> +
> +#endif /* CONFIG_LEDS_DELL_NETBOOKS */
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index e517902..d70f130 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -4249,6 +4249,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
>  /* for hda_fixup_thinkpad_acpi() */
>  #include "thinkpad_helper.c"
>  
> +/* for dell wmi mic mute led */
> +#include "dell_wmi_helper.c"
> +
>  enum {
>  	ALC269_FIXUP_SONY_VAIO,
>  	ALC275_FIXUP_SONY_VAIO_GPIO2,
> @@ -4310,6 +4313,7 @@ enum {
>  	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
>  	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
>  	ALC292_FIXUP_TPT440_DOCK,
> +	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
>  };
>  
>  static const struct hda_fixup alc269_fixups[] = {
> @@ -4736,6 +4740,12 @@ static const struct hda_fixup alc269_fixups[] = {
>  		.chained = true,
>  		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
>  	},
> +	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
> +		.type = HDA_FIXUP_FUNC,
> +		.v.func = alc_fixup_dell_wmi,
> +		.chained_before = true,
> +		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
> +	},
>  };
>  
>  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
> @@ -4779,10 +4789,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>  	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
> +	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>  	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
>  	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
> +	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>  	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
>  	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
>  	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
> -- 
> 1.9.1
> 
> 
> -- 
> kernel-team mailing list
> kernel-team@lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team

Applied to Utopic master-next
Hui Wang Feb. 9, 2015, 2:24 a.m. UTC | #3
On 02/06/2015 09:41 PM, Chris J Arges wrote:
> Hi,
> Need to add (backported from XXXXX) in patches 1/2 (cherry-pick -x can
> do this in the future). The backports make sense because the enum is
Got it. thanks.

> slightly different. Looks good overall,
>
> Acked-by: <chris.j.arges@canonical.com>
>
> --chris
>
> On 02/06/2015 02:23 AM, Hui Wang wrote:
>> BugLink: http://bugs.launchpad.net/bugs/1418832
>>
>> commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream
>>
>> The mic mute led on dell laptops is controlled by the wmi driver.
>> Followed this part being merged to the kernel, we add the mic mute led
>> hook in the hda driver.
>>
>> Signed-off-by: David Henningsson <david.henningsson@canonical.com>
>> Signed-off-by: Hui Wang <hui.wang@canonical.com>
>> Signed-off-by: Takashi Iwai <tiwai@suse.de>
>>
>> Conflicts:
>> 	sound/pci/hda/patch_realtek.c
>>
>> Signed-off-by: Hui Wang <hui.wang@canonical.com>
>> ---
>>   sound/pci/hda/dell_wmi_helper.c | 76 +++++++++++++++++++++++++++++++++++++++++
>>   sound/pci/hda/patch_realtek.c   | 12 +++++++
>>   2 files changed, 88 insertions(+)
>>   create mode 100644 sound/pci/hda/dell_wmi_helper.c
>>
>> diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
>> new file mode 100644
>> index 0000000..9c22f95
>> --- /dev/null
>> +++ b/sound/pci/hda/dell_wmi_helper.c
>> @@ -0,0 +1,76 @@
>> +/* Helper functions for Dell Mic Mute LED control;
>> + * to be included from codec driver
>> + */
>> +
>> +#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
>> +#include <linux/dell-led.h>
>> +
>> +static int dell_led_value;
>> +static int (*dell_led_set_func)(int, int);
>> +static void (*dell_old_cap_hook)(struct hda_codec *,
>> +			         struct snd_kcontrol *,
>> +				 struct snd_ctl_elem_value *);
>> +
>> +static void update_dell_wmi_micmute_led(struct hda_codec *codec,
>> +				        struct snd_kcontrol *kcontrol,
>> +					struct snd_ctl_elem_value *ucontrol)
>> +{
>> +	if (dell_old_cap_hook)
>> +		dell_old_cap_hook(codec, kcontrol, ucontrol);
>> +
>> +	if (!ucontrol || !dell_led_set_func)
>> +		return;
>> +	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
>> +		/* TODO: How do I verify if it's a mono or stereo here? */
>> +		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
>> +		if (val == dell_led_value)
>> +			return;
>> +		dell_led_value = val;
>> +		if (dell_led_set_func)
>> +			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
>> +	}
>> +}
>> +
>> +
>> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
>> +			       const struct hda_fixup *fix, int action)
>> +{
>> +	struct alc_spec *spec = codec->spec;
>> +	bool removefunc = false;
>> +
>> +	if (action == HDA_FIXUP_ACT_PROBE) {
>> +		if (!dell_led_set_func)
>> +			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
>> +		if (!dell_led_set_func) {
>> +			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
>> +			return;
>> +		}
>> +
>> +		removefunc = true;
>> +		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
>> +			dell_led_value = 0;
>> +			if (spec->gen.num_adc_nids > 1)
>> +				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
>> +			else {
>> +				dell_old_cap_hook = spec->gen.cap_sync_hook;
>> +				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
>> +				removefunc = false;
>> +			}
>> +		}
>> +
>> +	}
>> +
>> +	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
>> +		symbol_put(dell_app_wmi_led_set);
>> +		dell_led_set_func = NULL;
>> +		dell_old_cap_hook = NULL;
>> +	}
>> +}
>> +
>> +#else /* CONFIG_LEDS_DELL_NETBOOKS */
>> +static void alc_fixup_dell_wmi(struct hda_codec *codec,
>> +			       const struct hda_fixup *fix, int action)
>> +{
>> +}
>> +
>> +#endif /* CONFIG_LEDS_DELL_NETBOOKS */
>> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
>> index e517902..d70f130 100644
>> --- a/sound/pci/hda/patch_realtek.c
>> +++ b/sound/pci/hda/patch_realtek.c
>> @@ -4249,6 +4249,9 @@ static void alc290_fixup_mono_speakers(struct hda_codec *codec,
>>   /* for hda_fixup_thinkpad_acpi() */
>>   #include "thinkpad_helper.c"
>>   
>> +/* for dell wmi mic mute led */
>> +#include "dell_wmi_helper.c"
>> +
>>   enum {
>>   	ALC269_FIXUP_SONY_VAIO,
>>   	ALC275_FIXUP_SONY_VAIO_GPIO2,
>> @@ -4310,6 +4313,7 @@ enum {
>>   	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
>>   	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
>>   	ALC292_FIXUP_TPT440_DOCK,
>> +	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
>>   };
>>   
>>   static const struct hda_fixup alc269_fixups[] = {
>> @@ -4736,6 +4740,12 @@ static const struct hda_fixup alc269_fixups[] = {
>>   		.chained = true,
>>   		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
>>   	},
>> +	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
>> +		.type = HDA_FIXUP_FUNC,
>> +		.v.func = alc_fixup_dell_wmi,
>> +		.chained_before = true,
>> +		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
>> +	},
>>   };
>>   
>>   static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>> @@ -4779,10 +4789,12 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
>>   	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>>   	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>>   	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>> +	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>>   	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>>   	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
>>   	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
>>   	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
>> +	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
>>   	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
>>   	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
>>   	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
>>
Andy Whitcroft Feb. 9, 2015, 9:54 a.m. UTC | #4
On Fri, Feb 06, 2015 at 04:23:33PM +0800, Hui Wang wrote:
> BugLink: http://bugs.launchpad.net/bugs/1418832
> 
> commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream
> 
> The mic mute led on dell laptops is controlled by the wmi driver.
> Followed this part being merged to the kernel, we add the mic mute led
> hook in the hda driver.
> 
> Signed-off-by: David Henningsson <david.henningsson@canonical.com>
> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> 
> Conflicts:
> 	sound/pci/hda/patch_realtek.c
> 
> Signed-off-by: Hui Wang <hui.wang@canonical.com>

These first two have Conflicts: but they also look like upstream stable
commits in format, are you backporting from stable or is it you adding
the "commit X upstream" info here ?

-apw
Hui Wang Feb. 9, 2015, 9:59 a.m. UTC | #5
On 2015年02月09日 17:54, Andy Whitcroft wrote:
> On Fri, Feb 06, 2015 at 04:23:33PM +0800, Hui Wang wrote:
>> BugLink: http://bugs.launchpad.net/bugs/1418832
>>
>> commit 00ef99408b6cc8d86ca614ada8025aa3606860db upstream
>>
>> The mic mute led on dell laptops is controlled by the wmi driver.
>> Followed this part being merged to the kernel, we add the mic mute led
>> hook in the hda driver.
>>
>> Signed-off-by: David Henningsson <david.henningsson@canonical.com>
>> Signed-off-by: Hui Wang <hui.wang@canonical.com>
>> Signed-off-by: Takashi Iwai <tiwai@suse.de>
>>
>> Conflicts:
>> 	sound/pci/hda/patch_realtek.c
>>
>> Signed-off-by: Hui Wang <hui.wang@canonical.com>
> These first two have Conflicts: but they also look like upstream stable
> commits in format, are you backporting from stable or is it you adding
> the "commit X upstream" info here ?
I cherry-pick those commits from master branch of upstream.

Regards,
Hui.
> -apw
>
>

Patch
diff mbox

diff --git a/sound/pci/hda/dell_wmi_helper.c b/sound/pci/hda/dell_wmi_helper.c
new file mode 100644
index 0000000..9c22f95
--- /dev/null
+++ b/sound/pci/hda/dell_wmi_helper.c
@@ -0,0 +1,76 @@ 
+/* Helper functions for Dell Mic Mute LED control;
+ * to be included from codec driver
+ */
+
+#if IS_ENABLED(CONFIG_LEDS_DELL_NETBOOKS)
+#include <linux/dell-led.h>
+
+static int dell_led_value;
+static int (*dell_led_set_func)(int, int);
+static void (*dell_old_cap_hook)(struct hda_codec *,
+			         struct snd_kcontrol *,
+				 struct snd_ctl_elem_value *);
+
+static void update_dell_wmi_micmute_led(struct hda_codec *codec,
+				        struct snd_kcontrol *kcontrol,
+					struct snd_ctl_elem_value *ucontrol)
+{
+	if (dell_old_cap_hook)
+		dell_old_cap_hook(codec, kcontrol, ucontrol);
+
+	if (!ucontrol || !dell_led_set_func)
+		return;
+	if (strcmp("Capture Switch", ucontrol->id.name) == 0 && ucontrol->id.index == 0) {
+		/* TODO: How do I verify if it's a mono or stereo here? */
+		int val = (ucontrol->value.integer.value[0] || ucontrol->value.integer.value[1]) ? 0 : 1;
+		if (val == dell_led_value)
+			return;
+		dell_led_value = val;
+		if (dell_led_set_func)
+			dell_led_set_func(DELL_LED_MICMUTE, dell_led_value);
+	}
+}
+
+
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+	struct alc_spec *spec = codec->spec;
+	bool removefunc = false;
+
+	if (action == HDA_FIXUP_ACT_PROBE) {
+		if (!dell_led_set_func)
+			dell_led_set_func = symbol_request(dell_app_wmi_led_set);
+		if (!dell_led_set_func) {
+			codec_warn(codec, "Failed to find dell wmi symbol dell_app_wmi_led_set\n");
+			return;
+		}
+
+		removefunc = true;
+		if (dell_led_set_func(DELL_LED_MICMUTE, false) >= 0) {
+			dell_led_value = 0;
+			if (spec->gen.num_adc_nids > 1)
+				codec_dbg(codec, "Skipping micmute LED control due to several ADCs");
+			else {
+				dell_old_cap_hook = spec->gen.cap_sync_hook;
+				spec->gen.cap_sync_hook = update_dell_wmi_micmute_led;
+				removefunc = false;
+			}
+		}
+
+	}
+
+	if (dell_led_set_func && (action == HDA_FIXUP_ACT_FREE || removefunc)) {
+		symbol_put(dell_app_wmi_led_set);
+		dell_led_set_func = NULL;
+		dell_old_cap_hook = NULL;
+	}
+}
+
+#else /* CONFIG_LEDS_DELL_NETBOOKS */
+static void alc_fixup_dell_wmi(struct hda_codec *codec,
+			       const struct hda_fixup *fix, int action)
+{
+}
+
+#endif /* CONFIG_LEDS_DELL_NETBOOKS */
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index e517902..d70f130 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4249,6 +4249,9 @@  static void alc290_fixup_mono_speakers(struct hda_codec *codec,
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
+/* for dell wmi mic mute led */
+#include "dell_wmi_helper.c"
+
 enum {
 	ALC269_FIXUP_SONY_VAIO,
 	ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4310,6 +4313,7 @@  enum {
 	ALC255_FIXUP_HEADSET_MODE_NO_HP_MIC,
 	ALC293_FIXUP_DELL1_MIC_NO_PRESENCE,
 	ALC292_FIXUP_TPT440_DOCK,
+	ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -4736,6 +4740,12 @@  static const struct hda_fixup alc269_fixups[] = {
 		.chained = true,
 		.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
 	},
+	[ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED] = {
+		.type = HDA_FIXUP_FUNC,
+		.v.func = alc_fixup_dell_wmi,
+		.chained_before = true,
+		.chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
+	},
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -4779,10 +4789,12 @@  static const struct snd_pci_quirk alc269_fixup_tbl[] = {
 	SND_PCI_QUIRK(0x1028, 0x0606, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0608, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0609, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
+	SND_PCI_QUIRK(0x1028, 0x0610, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0613, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0614, "Dell Inspiron 3135", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x0615, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x0616, "Dell Vostro 5470", ALC290_FIXUP_SUBWOOFER_HSJACK),
+	SND_PCI_QUIRK(0x1028, 0x061f, "Dell", ALC255_FIXUP_DELL_WMI_MIC_MUTE_LED),
 	SND_PCI_QUIRK(0x1028, 0x0638, "Dell Inspiron 5439", ALC290_FIXUP_MONO_SPEAKERS_HSJACK),
 	SND_PCI_QUIRK(0x1028, 0x063f, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE),
 	SND_PCI_QUIRK(0x1028, 0x064a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),