From 13af8e77ea3e0dff80db9b2e0007535c21d49094 Mon Sep 17 00:00:00 2001
From: Takashi Iwai <tiwai@suse.de>
Date: Mon, 20 Jun 2011 14:05:46 +0200
Subject: [PATCH] ALSA: hda - Create loopback-list dynamically in patch_via.c
Git-commit: 13af8e77ea3e0dff80db9b2e0007535c21d49094
Patch-mainline: 3.1-rc2
References: FATE#314310

Create loopback list dynamically from the parsed input pins for VIA
codecs instead of the fixed arrays.

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 sound/pci/hda/patch_via.c |  164 +++++++---------------------------------------
 1 file changed, 25 insertions(+), 139 deletions(-)

--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -186,6 +186,8 @@ struct via_spec {
 
 #ifdef CONFIG_SND_HDA_POWER_SAVE
 	struct hda_loopback_check loopback;
+	int num_loopbacks;
+	struct hda_amp_list loopback_list[8];
 #endif
 };
 
@@ -1896,6 +1898,24 @@ static const struct snd_kcontrol_new via
 	.put = via_mux_enum_put,
 };
 
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+static void add_loopback_list(struct via_spec *spec, hda_nid_t mix, int idx)
+{
+	struct hda_amp_list *list;
+
+	if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
+		return;
+	list = spec->loopback_list + spec->num_loopbacks;
+	list->nid = mix;
+	list->dir = HDA_INPUT;
+	list->idx = idx;
+	spec->num_loopbacks++;
+	spec->loopback.amplist = spec->loopback_list;
+}
+#else
+#define add_loopback_list(spec, mix, idx) /* NOP */
+#endif
+
 /* create playback/capture controls for input pins */
 static int via_auto_create_analog_input_ctls(struct hda_codec *codec,
 					     const struct auto_pin_cfg *cfg)
@@ -1943,11 +1963,13 @@ static int via_auto_create_analog_input_
 		label = hda_get_autocfg_input_label(codec, cfg, i);
 		idx2 = get_connection_index(codec, spec->aa_mix_nid,
 					    pin_idxs[idx]);
-		if (idx2 >= 0)
+		if (idx2 >= 0) {
 			err = via_new_analog_input(spec, label, type_idx,
 						   idx2, spec->aa_mix_nid);
-		if (err < 0)
-			return err;
+			if (err < 0)
+				return err;
+			add_loopback_list(spec, spec->aa_mix_nid, idx2);
+		}
 		snd_hda_add_imux_item(imux, label, idx, NULL);
 
 		/* remember the label for smart51 control */
@@ -2012,16 +2034,6 @@ static int via_auto_create_analog_input_
 	return 0;
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708_loopbacks[] = {
-	{ 0x17, HDA_INPUT, 1 },
-	{ 0x17, HDA_INPUT, 2 },
-	{ 0x17, HDA_INPUT, 3 },
-	{ 0x17, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void vt1708_set_pinconfig_connect(struct hda_codec *codec, hda_nid_t nid)
 {
 	unsigned int def_conf;
@@ -2286,26 +2298,10 @@ static int patch_vt1708(struct hda_codec
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708_loopbacks;
-#endif
 	INIT_DELAYED_WORK(&spec->vt1708_hp_work, vt1708_update_hp_jack_state);
 	return 0;
 }
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1709_loopbacks[] = {
-	{ 0x18, HDA_INPUT, 1 },
-	{ 0x18, HDA_INPUT, 2 },
-	{ 0x18, HDA_INPUT, 3 },
-	{ 0x18, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static int patch_vt1709_10ch(struct hda_codec *codec)
 {
 	struct via_spec *spec;
@@ -2326,10 +2322,6 @@ static int patch_vt1709_10ch(struct hda_
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1709_loopbacks;
-#endif
-
 	return 0;
 }
 /*
@@ -2355,25 +2347,9 @@ static int patch_vt1709_6ch(struct hda_c
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1709_loopbacks;
-#endif
 	return 0;
 }
 
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708B_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -2478,10 +2454,6 @@ static int patch_vt1708B_8ch(struct hda_
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708B_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 
 	return 0;
@@ -2506,10 +2478,6 @@ static int patch_vt1708B_4ch(struct hda_
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708B_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1708B;
 
 	return 0;
@@ -2576,16 +2544,6 @@ static void fill_dig_in(struct hda_codec
 	}
 }
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1708S_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void override_mic_boost(struct hda_codec *codec, hda_nid_t pin,
 			       int offset, int num_steps, int step_size)
 {
@@ -2621,10 +2579,6 @@ static int patch_vt1708S(struct hda_code
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1708S_loopbacks;
-#endif
-
 	/* correct names for VT1708BCE */
 	if (get_codec_type(codec) == VT1708BCE)	{
 		kfree(codec->chip_name);
@@ -2655,16 +2609,6 @@ static const struct hda_verb vt1702_init
 	{ }
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1702_loopbacks[] = {
-	{ 0x1A, HDA_INPUT, 1 },
-	{ 0x1A, HDA_INPUT, 2 },
-	{ 0x1A, HDA_INPUT, 3 },
-	{ 0x1A, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1702(struct hda_codec *codec)
 {
 	int imux_is_smixer =
@@ -2726,10 +2670,6 @@ static int patch_vt1702(struct hda_codec
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1702_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1702;
 	return 0;
 }
@@ -2745,16 +2685,6 @@ static const struct hda_verb vt1718S_ini
 	{ }
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1718S_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ 0x21, HDA_INPUT, 3 },
-	{ 0x21, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -2846,10 +2776,6 @@ static int patch_vt1718S(struct hda_code
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1718S_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1718S;
 
 	return 0;
@@ -2926,16 +2852,6 @@ static const struct hda_verb vt1716S_ini
 	{ }
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1716S_loopbacks[] = {
-	{ 0x16, HDA_INPUT, 1 },
-	{ 0x16, HDA_INPUT, 2 },
-	{ 0x16, HDA_INPUT, 3 },
-	{ 0x16, HDA_INPUT, 4 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -3059,10 +2975,6 @@ static int patch_vt1716S(struct hda_code
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1716S_loopbacks;
-#endif
-
 	spec->set_widgets_power_state = set_widgets_power_state_vt1716S;
 	return 0;
 }
@@ -3089,15 +3001,6 @@ static const struct hda_verb vt1802_init
 	{ }
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt2002P_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 0 },
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -3238,10 +3141,6 @@ static int patch_vt2002P(struct hda_code
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt2002P_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt2002P;
 	return 0;
 }
@@ -3256,15 +3155,6 @@ static const struct hda_verb vt1812_init
 	{ }
 };
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list vt1812_loopbacks[] = {
-	{ 0x21, HDA_INPUT, 0 },
-	{ 0x21, HDA_INPUT, 1 },
-	{ 0x21, HDA_INPUT, 2 },
-	{ } /* end */
-};
-#endif
-
 static void set_widgets_power_state_vt1812(struct hda_codec *codec)
 {
 	struct via_spec *spec = codec->spec;
@@ -3383,10 +3273,6 @@ static int patch_vt1812(struct hda_codec
 
 	codec->patch_ops = via_patch_ops;
 
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-	spec->loopback.amplist = vt1812_loopbacks;
-#endif
-
 	spec->set_widgets_power_state =  set_widgets_power_state_vt1812;
 	return 0;
 }
