alsa-devel.alsa-project.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ALSA: VIA HDA: Add new power management function
@ 2011-03-23  7:13 Lydia Wang
  2011-03-23  7:48 ` Takashi Iwai
  0 siblings, 1 reply; 4+ messages in thread
From: Lydia Wang @ 2011-03-23  7:13 UTC (permalink / raw)
  To: alsa-devel; +Cc: tiwai, HaraldWelte, lydiawang

From: Lydia Wang <lydiawang@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@viatech.com.cn>
---
 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;
 }

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] ALSA: VIA HDA: Add new power management function
  2011-03-23  7:13 [PATCH] ALSA: VIA HDA: Add new power management function Lydia Wang
@ 2011-03-23  7:48 ` Takashi Iwai
       [not found]   ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ABA@exchbj03.viatech.com.bj>
  0 siblings, 1 reply; 4+ messages in thread
From: Takashi Iwai @ 2011-03-23  7:48 UTC (permalink / raw)
  To: Lydia Wang; +Cc: alsa-devel, HaraldWelte

At Wed, 23 Mar 2011 15:13:28 +0800,
Lydia Wang wrote:
> 
> From: Lydia Wang <lydiawang@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@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;
>  }
>  
> 

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: 答复: [PATCH] ALSA: VIA HDA: Add new power management function
       [not found]   ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ABA@exchbj03.viatech.com.bj>
@ 2011-03-23  7:57     ` Takashi Iwai
       [not found]       ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ACB@exchbj03.viatech.com.bj>
  0 siblings, 1 reply; 4+ messages in thread
From: Takashi Iwai @ 2011-03-23  7:57 UTC (permalink / raw)
  To: LydiaWang; +Cc: alsa-devel, HaraldWelte

At Wed, 23 Mar 2011 15:52:04 +0800,
<LydiaWang@viatech.com.cn> wrote:
> 
> 
> > -----邮件原件-----
> > 发件人: Takashi Iwai [mailto:tiwai@suse.de]
> > 发送时间: 2011年3月23日 15:49
> > 收件人: Lydia Wang
> > 抄送: alsa-devel@alsa-project.org; Harald Welte
> > 主题: Re: [PATCH] ALSA: VIA HDA: Add new power management function
> > 
> > At Wed, 23 Mar 2011 15:13:28 +0800,
> > Lydia Wang wrote:
> > >
> > > From: Lydia Wang <lydiawang@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@viatech.com.cn>
> > 
> > Applied now.  Thanks.
> > 
> > 
> > Takashi
> > 
> Thank you!
> Can I continue to submit the rest patches?

Sure.


Takashi
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: 答复: 答复: [PATCH] ALSA: VIA HDA: Add new power management function
       [not found]       ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ACB@exchbj03.viatech.com.bj>
@ 2011-03-23  8:55         ` Takashi Iwai
  0 siblings, 0 replies; 4+ messages in thread
From: Takashi Iwai @ 2011-03-23  8:55 UTC (permalink / raw)
  To: LydiaWang; +Cc: alsa-devel, HaraldWelte

At Wed, 23 Mar 2011 16:39:16 +0800,
<LydiaWang@viatech.com.cn> wrote:
> 
> 
> 
> > -----邮件原件-----
> > 发件人: Takashi Iwai [mailto:tiwai@suse.de]
> > 发送时间: 2011年3月23日 15:58
> > 收件人: Lydia Wang
> > 抄送: alsa-devel@alsa-project.org; Harald Welte
> > 主题: Re: 答复: [PATCH] ALSA: VIA HDA: Add new power management function
> > 
> > At Wed, 23 Mar 2011 15:52:04 +0800,
> > <LydiaWang@viatech.com.cn> wrote:
> > >
> > >
> > > > -----邮件原件-----
> > > > 发件人: Takashi Iwai [mailto:tiwai@suse.de]
> > > > 发送时间: 2011年3月23日 15:49
> > > > 收件人: Lydia Wang
> > > > 抄送: alsa-devel@alsa-project.org; Harald Welte
> > > > 主题: Re: [PATCH] ALSA: VIA HDA: Add new power management function
> > > >
> > > > At Wed, 23 Mar 2011 15:13:28 +0800,
> > > > Lydia Wang wrote:
> > > > >
> > > > > From: Lydia Wang <lydiawang@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@viatech.com.cn>
> > > >
> > > > Applied now.  Thanks.
> > > >
> > > >
> > > > Takashi
> > > >
> > > Thank you!
> > > Can I continue to submit the rest patches?
> > 
> > Sure.
> > 
> > 
> > Takashi
> 
> Sorry. I found forget pm function for VT1708S, so I submit a patch to add it. Is it ok or should I submit a new patch to replace the first one?

I fixed the original commit (amened).


thanks,

Takashi
_______________________________________________
Alsa-devel mailing list
Alsa-devel@alsa-project.org
http://mailman.alsa-project.org/mailman/listinfo/alsa-devel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2011-03-23  8:55 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-23  7:13 [PATCH] ALSA: VIA HDA: Add new power management function Lydia Wang
2011-03-23  7:48 ` Takashi Iwai
     [not found]   ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ABA@exchbj03.viatech.com.bj>
2011-03-23  7:57     ` 答复: " Takashi Iwai
     [not found]       ` <5B2BE0DB92BC8F4694F815C2F34E0D5F660ACB@exchbj03.viatech.com.bj>
2011-03-23  8:55         ` 答复: " Takashi Iwai

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).