| From ee52e56e7b12834476cd0031c5986254ba1b6317 Mon Sep 17 00:00:00 2001 | 
 | From: Takashi Iwai <tiwai@suse.de> | 
 | Date: Mon, 27 Apr 2015 10:36:11 +0200 | 
 | Subject: ALSA: hda - Fix mute-LED fixed mode | 
 | MIME-Version: 1.0 | 
 | Content-Type: text/plain; charset=UTF-8 | 
 | Content-Transfer-Encoding: 8bit | 
 |  | 
 | From: Takashi Iwai <tiwai@suse.de> | 
 |  | 
 | commit ee52e56e7b12834476cd0031c5986254ba1b6317 upstream. | 
 |  | 
 | The mute-LED mode control has the fixed on/off states that are | 
 | supposed to remain on/off regardless of the master switch.  However, | 
 | this doesn't work actually because the vmaster hook is called in the | 
 | vmaster code itself. | 
 |  | 
 | This patch fixes it by calling the hook indirectly after checking the | 
 | mute LED mode. | 
 |  | 
 | Reported-and-tested-by: Pali Rohár <pali.rohar@gmail.com> | 
 | Signed-off-by: Takashi Iwai <tiwai@suse.de> | 
 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 
 |  | 
 | --- | 
 |  sound/pci/hda/hda_codec.c |   21 ++++++++++++--------- | 
 |  1 file changed, 12 insertions(+), 9 deletions(-) | 
 |  | 
 | --- a/sound/pci/hda/hda_codec.c | 
 | +++ b/sound/pci/hda/hda_codec.c | 
 | @@ -2078,6 +2078,16 @@ int snd_hda_codec_amp_init_stereo(struct | 
 |  } | 
 |  EXPORT_SYMBOL_HDA(snd_hda_codec_amp_init_stereo); | 
 |   | 
 | +/* meta hook to call each driver's vmaster hook */ | 
 | +static void vmaster_hook(void *private_data, int enabled) | 
 | +{ | 
 | +	struct hda_vmaster_mute_hook *hook = private_data; | 
 | + | 
 | +	if (hook->mute_mode != HDA_VMUTE_FOLLOW_MASTER) | 
 | +		enabled = hook->mute_mode; | 
 | +	hook->hook(hook->codec, enabled); | 
 | +} | 
 | + | 
 |  /** | 
 |   * snd_hda_codec_resume_amp - Resume all AMP commands from the cache | 
 |   * @codec: HD-audio codec | 
 | @@ -2772,9 +2782,9 @@ int snd_hda_add_vmaster_hook(struct hda_ | 
 |   | 
 |  	if (!hook->hook || !hook->sw_kctl) | 
 |  		return 0; | 
 | -	snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec); | 
 |  	hook->codec = codec; | 
 |  	hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER; | 
 | +	snd_ctl_add_vmaster_hook(hook->sw_kctl, vmaster_hook, hook); | 
 |  	if (!expose_enum_ctl) | 
 |  		return 0; | 
 |  	kctl = snd_ctl_new1(&vmaster_mute_mode, hook); | 
 | @@ -2797,14 +2807,7 @@ void snd_hda_sync_vmaster_hook(struct hd | 
 |  	 */ | 
 |  	if (hook->codec->bus->shutdown) | 
 |  		return; | 
 | -	switch (hook->mute_mode) { | 
 | -	case HDA_VMUTE_FOLLOW_MASTER: | 
 | -		snd_ctl_sync_vmaster_hook(hook->sw_kctl); | 
 | -		break; | 
 | -	default: | 
 | -		hook->hook(hook->codec, hook->mute_mode); | 
 | -		break; | 
 | -	} | 
 | +	snd_ctl_sync_vmaster_hook(hook->sw_kctl); | 
 |  } | 
 |  EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook); | 
 |   |