ALSA: hda - Fix VIA output-path init for VT2002P/1802/1812

For VT2002P, VT1802 and VT1812 codecs, the original activate_output_path()
function can't initialize output and hp path correctly, since mixers connected to
output pin widgets are not considered. So modify the activate_output_path()
function to satisify this kind of codec.

Signed-off-by: Lydia Wang <lydiawang@viatech.com.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 42d5a91..8f59e0b 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -438,11 +438,62 @@
 #define have_mute(codec, nid, dir) \
 	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)
 
+static bool is_node_in_path(struct nid_path *path, hda_nid_t nid)
+{
+	int i;
+	if (!nid)
+		return false;
+	for (i = 0; i < path->depth; i++) {
+		if (path->path[i] == nid)
+			return true;
+	}
+	return false;
+}
+
+/* enable/disable the output-route mixers */
+static void activate_output_mix(struct hda_codec *codec, struct nid_path *path,
+				 hda_nid_t mix_nid, int aa_mix_idx, bool enable)
+{
+	int i, num, val;
+	bool hp_path, front_path;
+	struct via_spec *spec = codec->spec;
+
+	if (!path)
+		return;
+	num = snd_hda_get_conn_list(codec, mix_nid, NULL);
+	hp_path = is_node_in_path(path, spec->hp_dac_nid);
+	front_path = is_node_in_path(path, spec->multiout.dac_nids[0]);
+
+	for (i = 0; i < num; i++) {
+		if (i == aa_mix_idx) {
+			if (hp_path)
+				val = enable ? AMP_IN_MUTE(i) :
+				AMP_IN_UNMUTE(i);
+			else if (front_path)
+				val = AMP_IN_UNMUTE(i);
+			else
+				val = AMP_IN_MUTE(i);
+		} else {
+			if (hp_path)
+				val = enable ? AMP_IN_UNMUTE(i) :
+				AMP_IN_MUTE(i);
+			else if (front_path)
+				val = AMP_IN_MUTE(i);
+			else
+				val = AMP_IN_UNMUTE(i);
+		}
+		snd_hda_codec_write(codec, mix_nid, 0,
+				    AC_VERB_SET_AMP_GAIN_MUTE, val);
+	}
+}
+
 /* enable/disable the output-route */
 static void activate_output_path(struct hda_codec *codec, struct nid_path *path,
 				 bool enable, bool force)
 {
-	int i;
+	int i, val;
+	struct via_spec *spec = codec->spec;
+	hda_nid_t aa_mix_nid = spec->aa_mix_nid;
 	for (i = 0; i < path->depth; i++) {
 		hda_nid_t src, dst;
 		int idx = path->idx[i];
@@ -459,10 +510,19 @@
 		    && get_wcaps_type(get_wcaps(codec, dst)) == AC_WID_AUD_MIX)
 			continue;
 		if (have_mute(codec, dst, HDA_INPUT)) {
-			int val = enable ? AMP_IN_UNMUTE(idx) :
-				AMP_IN_MUTE(idx);
-			snd_hda_codec_write(codec, dst, 0,
-					    AC_VERB_SET_AMP_GAIN_MUTE, val);
+			if (dst == aa_mix_nid) {
+				val = enable ? AMP_IN_UNMUTE(idx) :
+					AMP_IN_MUTE(idx);
+				snd_hda_codec_write(codec, dst, 0,
+					AC_VERB_SET_AMP_GAIN_MUTE, val);
+			} else {
+				idx = get_connection_index(codec, dst,
+							   aa_mix_nid);
+				if (idx >= 0) {
+					activate_output_mix(codec, path,
+							    dst, idx, enable);
+				}
+			}
 		}
 		if (!force && (src == path->vol_ctl || src == path->mute_ctl))
 			continue;
@@ -493,8 +553,7 @@
 {
 	struct via_spec *spec = codec->spec;
 	unsigned int caps;
-	hda_nid_t pin, nid, pre_nid;
-	int i, idx, j, num;
+	hda_nid_t pin;
 
 	if (!path->depth)
 		return;
@@ -509,39 +568,10 @@
 				    AMP_OUT_MUTE | val);
 	}
 
-	activate_output_path(codec, path, true, force);
-
 	/* initialize the AA-path */
 	if (!spec->aa_mix_nid)
 		return;
-	for (i = path->depth - 1; i > 0; i--) {
-		nid = path->path[i];
-		pre_nid = path->path[i - 1];
-		idx = get_connection_index(codec, nid, spec->aa_mix_nid);
-		if (idx >= 0) {
-			if (have_mute(codec, nid, HDA_INPUT)) {
-				unsigned int mute = with_aa_mix ?
-					AMP_IN_UNMUTE(idx) : AMP_IN_MUTE(idx);
-				snd_hda_codec_write(codec, nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    mute);
-				/* exclusively via aa-mix for front */
-				if (pre_nid == spec->multiout.dac_nids[0]) {
-					num = snd_hda_get_conn_list(codec, nid,
-								    NULL);
-					for (j = 0; j < num; j++) {
-						if (j == idx)
-							continue;
-						snd_hda_codec_write(codec,
-						    nid, 0,
-						    AC_VERB_SET_AMP_GAIN_MUTE,
-						    AMP_IN_MUTE(j));
-					}
-				}
-			}
-			break;
-		}
-	}
+	activate_output_path(codec, path, true, force);
 }
 
 static void via_auto_init_multi_out(struct hda_codec *codec)