[alsa-devel] [PATCH] ALSA: VIA HDA: Add new power management function

Takashi Iwai tiwai at suse.de
Wed Mar 23 08:48:56 CET 2011


At Wed, 23 Mar 2011 15:13:28 +0800,
Lydia Wang wrote:
> 
> From: Lydia Wang <lydiawang at viatech.com.cn>
> Subject: ALSA: VIA HDA: Add new power management function.
> 
> Use set_widgets_power_state() function to seperately control different 
> codecs' power management actions and to replace the original large 
> function. Also fix some wrong widgets power up sequence which caused 
> no sound issue under Smart5.1 mode and Independent HP mode.
> 
> Signed-off-by: Lydia Wang <lydiawang at viatech.com.cn>

Applied now.  Thanks.


Takashi

> ---
>  sound/pci/hda/patch_via.c |  937 ++++++++++++++++++++++------------------------
>  1 file changed, 452 insertions(+), 485 deletions(-)
> 
> --- a/sound/pci/hda/patch_via.c
> +++ b/sound/pci/hda/patch_via.c
> @@ -154,6 +154,9 @@
>  	struct delayed_work vt1708_hp_work;
>  	int vt1708_jack_detectect;
>  	int vt1708_hp_present;
> +
> +	void (*set_widgets_power_state)(struct hda_codec *codec);
> +
>  #ifdef CONFIG_SND_HDA_POWER_SAVE
>  	struct hda_loopback_check loopback;
>  #endif
> @@ -245,7 +248,6 @@
>  };
>  
>  static void analog_low_current_mode(struct hda_codec *codec, int stream_idle);
> -static void set_jack_power_state(struct hda_codec *codec);
>  static int is_aa_path_mute(struct hda_codec *codec);
>  
>  static void vt1708_start_hp_work(struct via_spec *spec)
> @@ -271,6 +273,12 @@
>  	cancel_delayed_work_sync(&spec->vt1708_hp_work);
>  }
>  
> +static void set_widgets_power_state(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	if (spec->set_widgets_power_state)
> +		spec->set_widgets_power_state(codec);
> +}
>  
>  static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
>  				   struct snd_ctl_elem_value *ucontrol)
> @@ -278,7 +286,7 @@
>  	int change = snd_hda_mixer_amp_switch_put(kcontrol, ucontrol);
>  	struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
>  
> -	set_jack_power_state(codec);
> +	set_widgets_power_state(codec);
>  	analog_low_current_mode(snd_kcontrol_chip(kcontrol), -1);
>  	if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
>  		if (is_aa_path_mute(codec))
> @@ -602,482 +610,6 @@
>  	snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
>  }
>  
> -static void set_jack_power_state(struct hda_codec *codec)
> -{
> -	struct via_spec *spec = codec->spec;
> -	int imux_is_smixer;
> -	unsigned int parm;
> -
> -	if (spec->codec_type == VT1702) {
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
> -		/* inputs */
> -		/* PW 1/2/5 (14h/15h/18h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x14, &parm);
> -		set_pin_power_state(codec, 0x15, &parm);
> -		set_pin_power_state(codec, 0x18, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0; /* SW0 = stereo mixer (idx 3) */
> -		/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
> -		snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* outputs */
> -		/* PW 3/4 (16h/17h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x16, &parm);
> -		set_pin_power_state(codec, 0x17, &parm);
> -		/* MW0 (1ah), AOW 0/1 (10h/1dh) */
> -		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
> -				    imux_is_smixer ? AC_PWRST_D0 : parm);
> -		snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -	} else if (spec->codec_type == VT1708B_8CH
> -		   || spec->codec_type == VT1708B_4CH
> -		   || spec->codec_type == VT1708S) {
> -		/* SW0 (17h) = stereo mixer */
> -		int is_8ch = spec->codec_type != VT1708B_4CH;
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
> -			== ((spec->codec_type == VT1708S)  ? 5 : 0);
> -		/* inputs */
> -		/* PW 1/2/5 (1ah/1bh/1eh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x1a, &parm);
> -		set_pin_power_state(codec, 0x1b, &parm);
> -		set_pin_power_state(codec, 0x1e, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0;
> -		/* SW0 (17h), AIW 0/1 (13h/14h) */
> -		snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* outputs */
> -		/* PW0 (19h), SW1 (18h), AOW1 (11h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x19, &parm);
> -		if (spec->smart51_enabled)
> -			parm = AC_PWRST_D0;
> -		snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* PW6 (22h), SW2 (26h), AOW2 (24h) */
> -		if (is_8ch) {
> -			parm = AC_PWRST_D3;
> -			set_pin_power_state(codec, 0x22, &parm);
> -			if (spec->smart51_enabled)
> -				parm = AC_PWRST_D0;
> -			snd_hda_codec_write(codec, 0x26, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -			snd_hda_codec_write(codec, 0x24, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -		}
> -
> -		/* PW 3/4/7 (1ch/1dh/23h) */
> -		parm = AC_PWRST_D3;
> -		/* force to D0 for internal Speaker */
> -		set_pin_power_state(codec, 0x1c, &parm);
> -		set_pin_power_state(codec, 0x1d, &parm);
> -		if (is_8ch)
> -			set_pin_power_state(codec, 0x23, &parm);
> -		/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
> -		snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
> -				    imux_is_smixer ? AC_PWRST_D0 : parm);
> -		snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		if (is_8ch) {
> -			snd_hda_codec_write(codec, 0x25, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -			snd_hda_codec_write(codec, 0x27, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -		}
> -	}  else if (spec->codec_type == VT1718S) {
> -		/* MUX6 (1eh) = stereo mixer */
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
> -		/* inputs */
> -		/* PW 5/6/7 (29h/2ah/2bh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x29, &parm);
> -		set_pin_power_state(codec, 0x2a, &parm);
> -		set_pin_power_state(codec, 0x2b, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0;
> -		/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
> -		snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* outputs */
> -		/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x27, &parm);
> -		snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* PW2 (26h), AOW2 (ah) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x26, &parm);
> -		snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* PW0/1 (24h/25h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x24, &parm);
> -		set_pin_power_state(codec, 0x25, &parm);
> -		if (!spec->hp_independent_mode) /* check for redirected HP */
> -			set_pin_power_state(codec, 0x28, &parm);
> -		snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
> -		snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
> -				    imux_is_smixer ? AC_PWRST_D0 : parm);
> -		if (spec->hp_independent_mode) {
> -			/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
> -			parm = AC_PWRST_D3;
> -			set_pin_power_state(codec, 0x28, &parm);
> -			snd_hda_codec_write(codec, 0x1b, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -			snd_hda_codec_write(codec, 0x34, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -			snd_hda_codec_write(codec, 0xc, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -		}
> -	} else if (spec->codec_type == VT1716S) {
> -		unsigned int mono_out, present;
> -		/* SW0 (17h) = stereo mixer */
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00) ==  5;
> -		/* inputs */
> -		/* PW 1/2/5 (1ah/1bh/1eh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x1a, &parm);
> -		set_pin_power_state(codec, 0x1b, &parm);
> -		set_pin_power_state(codec, 0x1e, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0;
> -		/* SW0 (17h), AIW0(13h) */
> -		snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x1e, &parm);
> -		/* PW11 (22h) */
> -		if (spec->dmic_enabled)
> -			set_pin_power_state(codec, 0x22, &parm);
> -		else
> -			snd_hda_codec_write(
> -				codec, 0x22, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -
> -		/* SW2(26h), AIW1(14h) */
> -		snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* outputs */
> -		/* PW0 (19h), SW1 (18h), AOW1 (11h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x19, &parm);
> -		/* Smart 5.1 PW2(1bh) */
> -		if (spec->smart51_enabled)
> -			set_pin_power_state(codec, 0x1b, &parm);
> -		snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* PW7 (23h), SW3 (27h), AOW3 (25h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x23, &parm);
> -		/* Smart 5.1 PW1(1ah) */
> -		if (spec->smart51_enabled)
> -			set_pin_power_state(codec, 0x1a, &parm);
> -		snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* Smart 5.1 PW5(1eh) */
> -		if (spec->smart51_enabled)
> -			set_pin_power_state(codec, 0x1e, &parm);
> -		snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* Mono out */
> -		/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
> -		present = snd_hda_jack_detect(codec, 0x1c);
> -		if (present)
> -			mono_out = 0;
> -		else {
> -			present = snd_hda_jack_detect(codec, 0x1d);
> -			if (!spec->hp_independent_mode && present)
> -				mono_out = 0;
> -			else
> -				mono_out = 1;
> -		}
> -		parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
> -		snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -		snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE,
> -				    parm);
> -
> -		/* PW 3/4 (1ch/1dh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x1c, &parm);
> -		set_pin_power_state(codec, 0x1d, &parm);
> -		/* HP Independent Mode, power on AOW3 */
> -		if (spec->hp_independent_mode)
> -			snd_hda_codec_write(codec, 0x25, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* force to D0 for internal Speaker */
> -		/* MW0 (16h), AOW0 (10h) */
> -		snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
> -				    imux_is_smixer ? AC_PWRST_D0 : parm);
> -		snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
> -				    mono_out ? AC_PWRST_D0 : parm);
> -	} else if (spec->codec_type == VT2002P) {
> -		unsigned int present;
> -		/* MUX9 (1eh) = stereo mixer */
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
> -		/* inputs */
> -		/* PW 5/6/7 (29h/2ah/2bh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x29, &parm);
> -		set_pin_power_state(codec, 0x2a, &parm);
> -		set_pin_power_state(codec, 0x2b, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0;
> -		/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
> -		snd_hda_codec_write(codec, 0x1e, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x1f, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x10, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x11, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* outputs */
> -		/* AOW0 (8h)*/
> -		snd_hda_codec_write(codec, 0x8, 0,
> -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -
> -		/* PW4 (26h), MW4 (1ch), MUX4(37h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x26, &parm);
> -		snd_hda_codec_write(codec, 0x1c, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x37,
> -				    0, AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x25, &parm);
> -		snd_hda_codec_write(codec, 0x19, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x35, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		if (spec->hp_independent_mode)	{
> -			snd_hda_codec_write(codec, 0x9, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -		}
> -
> -		/* Class-D */
> -		/* PW0 (24h), MW0(18h), MUX0(34h) */
> -		present = snd_hda_jack_detect(codec, 0x25);
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x24, &parm);
> -		if (present) {
> -			snd_hda_codec_write(
> -				codec, 0x18, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -			snd_hda_codec_write(
> -				codec, 0x34, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -		} else {
> -			snd_hda_codec_write(
> -				codec, 0x18, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -			snd_hda_codec_write(
> -				codec, 0x34, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -		}
> -
> -		/* Mono Out */
> -		/* PW15 (31h), MW8(17h), MUX8(3bh) */
> -		present = snd_hda_jack_detect(codec, 0x26);
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x31, &parm);
> -		if (present) {
> -			snd_hda_codec_write(
> -				codec, 0x17, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -			snd_hda_codec_write(
> -				codec, 0x3b, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -		} else {
> -			snd_hda_codec_write(
> -				codec, 0x17, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -			snd_hda_codec_write(
> -				codec, 0x3b, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -		}
> -
> -		/* MW9 (21h) */
> -		if (imux_is_smixer || !is_aa_path_mute(codec))
> -			snd_hda_codec_write(
> -				codec, 0x21, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -		else
> -			snd_hda_codec_write(
> -				codec, 0x21, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -	} else if (spec->codec_type == VT1812) {
> -		unsigned int present;
> -		/* MUX10 (1eh) = stereo mixer */
> -		imux_is_smixer = snd_hda_codec_read(
> -			codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
> -		/* inputs */
> -		/* PW 5/6/7 (29h/2ah/2bh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x29, &parm);
> -		set_pin_power_state(codec, 0x2a, &parm);
> -		set_pin_power_state(codec, 0x2b, &parm);
> -		if (imux_is_smixer)
> -			parm = AC_PWRST_D0;
> -		/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
> -		snd_hda_codec_write(codec, 0x1e, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x1f, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x10, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x11, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* outputs */
> -		/* AOW0 (8h)*/
> -		snd_hda_codec_write(codec, 0x8, 0,
> -				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -
> -		/* PW4 (28h), MW4 (18h), MUX4(38h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x28, &parm);
> -		snd_hda_codec_write(codec, 0x18, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x38, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x25, &parm);
> -		snd_hda_codec_write(codec, 0x15, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x35, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		if (spec->hp_independent_mode)	{
> -			snd_hda_codec_write(codec, 0x9, 0,
> -					    AC_VERB_SET_POWER_STATE, parm);
> -		}
> -
> -		/* Internal Speaker */
> -		/* PW0 (24h), MW0(14h), MUX0(34h) */
> -		present = snd_hda_jack_detect(codec, 0x25);
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x24, &parm);
> -		if (present) {
> -			snd_hda_codec_write(codec, 0x14, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D3);
> -			snd_hda_codec_write(codec, 0x34, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D3);
> -		} else {
> -			snd_hda_codec_write(codec, 0x14, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D0);
> -			snd_hda_codec_write(codec, 0x34, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D0);
> -		}
> -		/* Mono Out */
> -		/* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
> -		present = snd_hda_jack_detect(codec, 0x28);
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x31, &parm);
> -		if (present) {
> -			snd_hda_codec_write(codec, 0x1c, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D3);
> -			snd_hda_codec_write(codec, 0x3c, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D3);
> -			snd_hda_codec_write(codec, 0x3e, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D3);
> -		} else {
> -			snd_hda_codec_write(codec, 0x1c, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D0);
> -			snd_hda_codec_write(codec, 0x3c, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D0);
> -			snd_hda_codec_write(codec, 0x3e, 0,
> -					    AC_VERB_SET_POWER_STATE,
> -					    AC_PWRST_D0);
> -		}
> -
> -		/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
> -		parm = AC_PWRST_D3;
> -		set_pin_power_state(codec, 0x33, &parm);
> -		snd_hda_codec_write(codec, 0x1d, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -		snd_hda_codec_write(codec, 0x3d, 0,
> -				    AC_VERB_SET_POWER_STATE, parm);
> -
> -		/* MW9 (21h) */
> -		if (imux_is_smixer || !is_aa_path_mute(codec))
> -			snd_hda_codec_write(
> -				codec, 0x21, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> -		else
> -			snd_hda_codec_write(
> -				codec, 0x21, 0,
> -				AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> -	}
> -}
> -
>  /*
>   * input MUX handling
>   */
> @@ -1120,7 +652,7 @@
>  				     spec->mux_nids[adc_idx],
>  				     &spec->cur_mux[adc_idx]);
>  	/* update jack power state */
> -	set_jack_power_state(codec);
> +	set_widgets_power_state(codec);
>  
>  	return ret;
>  }
> @@ -1225,7 +757,7 @@
>  			     spec->hp_independent_mode);
>  	}
>  	/* update jack power state */
> -	set_jack_power_state(codec);
> +	set_widgets_power_state(codec);
>  	return 0;
>  }
>  
> @@ -1443,7 +975,7 @@
>  		}
>  	}
>  	spec->smart51_enabled = *ucontrol->value.integer.value;
> -	set_jack_power_state(codec);
> +	set_widgets_power_state(codec);
>  	return 1;
>  }
>  
> @@ -1967,7 +1499,7 @@
>  	}
>  
>  	/* init power states */
> -	set_jack_power_state(codec);
> +	set_widgets_power_state(codec);
>  	analog_low_current_mode(codec, 1);
>  
>  	via_free_kctls(codec); /* no longer needed */
> @@ -2195,7 +1727,7 @@
>  	if (res & VIA_GPIO_EVENT)
>  		via_gpio_control(codec);
>  	if (res & VIA_JACK_EVENT)
> -		set_jack_power_state(codec);
> +		set_widgets_power_state(codec);
>  	if (res & VIA_MONO_EVENT)
>  		via_mono_automute(codec);
>  	if (res & VIA_SPEAKER_EVENT)
> @@ -3642,6 +3174,74 @@
>  	{ } /* end */
>  };
>  #endif
> +
> +static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	int imux_is_smixer;
> +	unsigned int parm;
> +	int is_8ch = 0;
> +	if (spec->codec_type != VT1708B_4CH)
> +		is_8ch = 1;
> +
> +	/* SW0 (17h) = stereo mixer */
> +	imux_is_smixer =
> +	(snd_hda_codec_read(codec, 0x17, 0, AC_VERB_GET_CONNECT_SEL, 0x00)
> +	 == ((spec->codec_type == VT1708S) ? 5 : 0));
> +	/* inputs */
> +	/* PW 1/2/5 (1ah/1bh/1eh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x1a, &parm);
> +	set_pin_power_state(codec, 0x1b, &parm);
> +	set_pin_power_state(codec, 0x1e, &parm);
> +	if (imux_is_smixer)
> +		parm = AC_PWRST_D0;
> +	/* SW0 (17h), AIW 0/1 (13h/14h) */
> +	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* PW0 (19h), SW1 (18h), AOW1 (11h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x19, &parm);
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x1b, &parm);
> +	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW6 (22h), SW2 (26h), AOW2 (24h) */
> +	if (is_8ch) {
> +		parm = AC_PWRST_D3;
> +		set_pin_power_state(codec, 0x22, &parm);
> +		if (spec->smart51_enabled)
> +			set_pin_power_state(codec, 0x1a, &parm);
> +		snd_hda_codec_write(codec, 0x26, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +		snd_hda_codec_write(codec, 0x24, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +	}
> +
> +	/* PW 3/4/7 (1ch/1dh/23h) */
> +	parm = AC_PWRST_D3;
> +	/* force to D0 for internal Speaker */
> +	set_pin_power_state(codec, 0x1c, &parm);
> +	set_pin_power_state(codec, 0x1d, &parm);
> +	if (is_8ch)
> +		set_pin_power_state(codec, 0x23, &parm);
> +
> +	/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
> +	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
> +			    imux_is_smixer ? AC_PWRST_D0 : parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
> +	if (is_8ch) {
> +		snd_hda_codec_write(codec, 0x25, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +		snd_hda_codec_write(codec, 0x27, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +	}
> +}
> +
>  static int patch_vt1708S(struct hda_codec *codec);
>  static int patch_vt1708B_8ch(struct hda_codec *codec)
>  {
> @@ -3692,6 +3292,8 @@
>  	spec->loopback.amplist = vt1708B_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
> +
>  	return 0;
>  }
>  
> @@ -3742,6 +3344,8 @@
>  	spec->loopback.amplist = vt1708B_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
> +
>  	return 0;
>  }
>  
> @@ -4438,6 +4042,37 @@
>  };
>  #endif
>  
> +static void set_widgets_power_state_vt1702(struct hda_codec *codec)
> +{
> +	int imux_is_smixer =
> +	snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
> +	unsigned int parm;
> +	/* inputs */
> +	/* PW 1/2/5 (14h/15h/18h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x14, &parm);
> +	set_pin_power_state(codec, 0x15, &parm);
> +	set_pin_power_state(codec, 0x18, &parm);
> +	if (imux_is_smixer)
> +		parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
> +	/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
> +	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* PW 3/4 (16h/17h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x17, &parm);
> +	set_pin_power_state(codec, 0x16, &parm);
> +	/* MW0 (1ah), AOW 0/1 (10h/1dh) */
> +	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
> +			    imux_is_smixer ? AC_PWRST_D0 : parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
> +}
> +
>  static int patch_vt1702(struct hda_codec *codec)
>  {
>  	struct via_spec *spec;
> @@ -4484,6 +4119,7 @@
>  	spec->loopback.amplist = vt1702_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt1702;
>  	return 0;
>  }
>  
> @@ -4825,6 +4461,72 @@
>  };
>  #endif
>  
> +static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	int imux_is_smixer;
> +	unsigned int parm;
> +	/* MUX6 (1eh) = stereo mixer */
> +	imux_is_smixer =
> +	snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
> +	/* inputs */
> +	/* PW 5/6/7 (29h/2ah/2bh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x29, &parm);
> +	set_pin_power_state(codec, 0x2a, &parm);
> +	set_pin_power_state(codec, 0x2b, &parm);
> +	if (imux_is_smixer)
> +		parm = AC_PWRST_D0;
> +	/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
> +	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x27, &parm);
> +	snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW2 (26h), AOW2 (ah) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x26, &parm);
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x2b, &parm);
> +	snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW0 (24h), AOW0 (8h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x24, &parm);
> +	if (!spec->hp_independent_mode) /* check for redirected HP */
> +		set_pin_power_state(codec, 0x28, &parm);
> +	snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
> +	/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
> +	snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
> +			    imux_is_smixer ? AC_PWRST_D0 : parm);
> +
> +	/* PW1 (25h), AOW1 (9h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x25, &parm);
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x2a, &parm);
> +	snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	if (spec->hp_independent_mode) {
> +		/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
> +		parm = AC_PWRST_D3;
> +		set_pin_power_state(codec, 0x28, &parm);
> +		snd_hda_codec_write(codec, 0x1b, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +		snd_hda_codec_write(codec, 0x34, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +		snd_hda_codec_write(codec, 0xc, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +	}
> +}
> +
>  static int patch_vt1718S(struct hda_codec *codec)
>  {
>  	struct via_spec *spec;
> @@ -4886,6 +4588,8 @@
>  	spec->loopback.amplist = vt1718S_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt1718S;
> +
>  	return 0;
>  }
>  
> @@ -4925,8 +4629,7 @@
>  	snd_hda_codec_write(codec, 0x26, 0,
>  					       AC_VERB_SET_CONNECT_SEL, index);
>  	spec->dmic_enabled = index;
> -	set_jack_power_state(codec);
> -
> +	set_widgets_power_state(codec);
>  	return 1;
>  }
>  
> @@ -5285,6 +4988,99 @@
>  };
>  #endif
>  
> +static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	int imux_is_smixer;
> +	unsigned int parm;
> +	unsigned int mono_out, present;
> +	/* SW0 (17h) = stereo mixer */
> +	imux_is_smixer =
> +	(snd_hda_codec_read(codec, 0x17, 0,
> +			    AC_VERB_GET_CONNECT_SEL, 0x00) ==  5);
> +	/* inputs */
> +	/* PW 1/2/5 (1ah/1bh/1eh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x1a, &parm);
> +	set_pin_power_state(codec, 0x1b, &parm);
> +	set_pin_power_state(codec, 0x1e, &parm);
> +	if (imux_is_smixer)
> +		parm = AC_PWRST_D0;
> +	/* SW0 (17h), AIW0(13h) */
> +	snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x1e, &parm);
> +	/* PW11 (22h) */
> +	if (spec->dmic_enabled)
> +		set_pin_power_state(codec, 0x22, &parm);
> +	else
> +		snd_hda_codec_write(codec, 0x22, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +
> +	/* SW2(26h), AIW1(14h) */
> +	snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* PW0 (19h), SW1 (18h), AOW1 (11h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x19, &parm);
> +	/* Smart 5.1 PW2(1bh) */
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x1b, &parm);
> +	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW7 (23h), SW3 (27h), AOW3 (25h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x23, &parm);
> +	/* Smart 5.1 PW1(1ah) */
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x1a, &parm);
> +	snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* Smart 5.1 PW5(1eh) */
> +	if (spec->smart51_enabled)
> +		set_pin_power_state(codec, 0x1e, &parm);
> +	snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* Mono out */
> +	/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
> +	present = snd_hda_jack_detect(codec, 0x1c);
> +
> +	if (present)
> +		mono_out = 0;
> +	else {
> +		present = snd_hda_jack_detect(codec, 0x1d);
> +		if (!spec->hp_independent_mode && present)
> +			mono_out = 0;
> +		else
> +			mono_out = 1;
> +	}
> +	parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
> +	snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW 3/4 (1ch/1dh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x1c, &parm);
> +	set_pin_power_state(codec, 0x1d, &parm);
> +	/* HP Independent Mode, power on AOW3 */
> +	if (spec->hp_independent_mode)
> +		snd_hda_codec_write(codec, 0x25, 0,
> +				    AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* force to D0 for internal Speaker */
> +	/* MW0 (16h), AOW0 (10h) */
> +	snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
> +			    imux_is_smixer ? AC_PWRST_D0 : parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
> +			    mono_out ? AC_PWRST_D0 : parm);
> +}
> +
>  static int patch_vt1716S(struct hda_codec *codec)
>  {
>  	struct via_spec *spec;
> @@ -5339,6 +5135,7 @@
>  	spec->loopback.amplist = vt1716S_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
>  	return 0;
>  }
>  
> @@ -5609,6 +5406,83 @@
>  };
>  #endif
>  
> +static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	int imux_is_smixer;
> +	unsigned int parm;
> +	unsigned int present;
> +	/* MUX9 (1eh) = stereo mixer */
> +	imux_is_smixer =
> +	snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
> +	/* inputs */
> +	/* PW 5/6/7 (29h/2ah/2bh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x29, &parm);
> +	set_pin_power_state(codec, 0x2a, &parm);
> +	set_pin_power_state(codec, 0x2b, &parm);
> +	parm = AC_PWRST_D0;
> +	/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
> +	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* AOW0 (8h)*/
> +	snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW4 (26h), MW4 (1ch), MUX4(37h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x26, &parm);
> +	snd_hda_codec_write(codec, 0x1c, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x37, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x25, &parm);
> +	snd_hda_codec_write(codec, 0x19, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x35, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +
> +	if (spec->hp_independent_mode)
> +		snd_hda_codec_write(codec, 0x9, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +
> +	/* Class-D */
> +	/* PW0 (24h), MW0(18h/14h), MUX0(34h) */
> +	present = snd_hda_jack_detect(codec, 0x25);
> +
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x24, &parm);
> +	parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
> +	snd_hda_codec_write(codec, 0x18, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* Mono Out */
> +	present = snd_hda_jack_detect(codec, 0x26);
> +
> +	parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
> +	/* PW15 (31h), MW8(17h), MUX8(3bh) */
> +	snd_hda_codec_write(codec, 0x31, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x17, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x3b, 0,
> +			    AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* MW9 (21h) */
> +	if (imux_is_smixer || !is_aa_path_mute(codec))
> +		snd_hda_codec_write(codec, 0x21, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +	else
> +		snd_hda_codec_write(codec, 0x21, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +}
>  
>  /* patch for vt2002P */
>  static int patch_vt2002P(struct hda_codec *codec)
> @@ -5660,6 +5534,7 @@
>  	spec->loopback.amplist = vt2002P_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt2002P;
>  	return 0;
>  }
>  
> @@ -5931,6 +5806,97 @@
>  };
>  #endif
>  
> +static void set_widgets_power_state_vt1812(struct hda_codec *codec)
> +{
> +	struct via_spec *spec = codec->spec;
> +	int imux_is_smixer =
> +	snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
> +	unsigned int parm;
> +	unsigned int present;
> +	/* MUX10 (1eh) = stereo mixer */
> +	imux_is_smixer =
> +	snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
> +	/* inputs */
> +	/* PW 5/6/7 (29h/2ah/2bh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x29, &parm);
> +	set_pin_power_state(codec, 0x2a, &parm);
> +	set_pin_power_state(codec, 0x2b, &parm);
> +	parm = AC_PWRST_D0;
> +	/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
> +	snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* outputs */
> +	/* AOW0 (8h)*/
> +	snd_hda_codec_write(codec, 0x8, 0,
> +			    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +
> +	/* PW4 (28h), MW4 (18h), MUX4(38h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x28, &parm);
> +	snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +	/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x25, &parm);
> +	snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
> +	if (spec->hp_independent_mode)
> +		snd_hda_codec_write(codec, 0x9, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +
> +	/* Internal Speaker */
> +	/* PW0 (24h), MW0(14h), MUX0(34h) */
> +	present = snd_hda_jack_detect(codec, 0x25);
> +
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x24, &parm);
> +	if (present) {
> +		snd_hda_codec_write(codec, 0x14, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +		snd_hda_codec_write(codec, 0x34, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +	} else {
> +		snd_hda_codec_write(codec, 0x14, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +		snd_hda_codec_write(codec, 0x34, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +	}
> +
> +
> +	/* Mono Out */
> +	/* PW13 (31h), MW13(1ch), MUX13(3ch), MW14(3eh) */
> +	present = snd_hda_jack_detect(codec, 0x28);
> +
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x31, &parm);
> +	if (present) {
> +		snd_hda_codec_write(codec, 0x1c, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +		snd_hda_codec_write(codec, 0x3c, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +		snd_hda_codec_write(codec, 0x3e, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
> +	} else {
> +		snd_hda_codec_write(codec, 0x1c, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +		snd_hda_codec_write(codec, 0x3c, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +		snd_hda_codec_write(codec, 0x3e, 0,
> +				    AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
> +	}
> +
> +	/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
> +	parm = AC_PWRST_D3;
> +	set_pin_power_state(codec, 0x33, &parm);
> +	snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
> +	snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
> +
> +}
>  
>  /* patch for vt1812 */
>  static int patch_vt1812(struct hda_codec *codec)
> @@ -5984,6 +5950,7 @@
>  	spec->loopback.amplist = vt1812_loopbacks;
>  #endif
>  
> +	spec->set_widgets_power_state =  set_widgets_power_state_vt1812;
>  	return 0;
>  }
>  
> 


More information about the Alsa-devel mailing list