ALSA: hda - Improve input control names for IDT/STAC codecs

Changing the way the input controls are named using port connection
type and jack location info.

Signed-off-by: Vitaliy Kulikov <Vitaliy.Kulikov@idt.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 82d1e43..7f09e14 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -191,6 +191,11 @@
 	signed char dmux_idx;
 };
 
+struct unique_input_names {
+	int num;
+	char uname[HDA_MAX_NUM_INPUTS][32];
+};
+
 struct sigmatel_spec {
 	struct snd_kcontrol_new *mixers[4];
 	unsigned int num_mixers;
@@ -307,6 +312,7 @@
 	struct hda_input_mux private_imux;
 	struct hda_input_mux private_smux;
 	struct hda_input_mux private_mono_mux;
+	struct unique_input_names private_u_inp_names;
 };
 
 static hda_nid_t stac9200_adc_nids[1] = {
@@ -3452,6 +3458,76 @@
 	return 1;
 }
 
+static const char *get_input_src_label(struct hda_codec *codec, hda_nid_t nid)
+{
+	unsigned int def_conf;
+
+	def_conf = snd_hda_codec_get_pincfg(codec, nid);
+
+	switch (get_defcfg_device(def_conf)) {
+	case AC_JACK_MIC_IN:
+		if (get_defcfg_connect(def_conf) == AC_JACK_PORT_FIXED ||
+				((get_defcfg_location(def_conf) & 0xf0)
+						== AC_JACK_LOC_INTERNAL))
+			return "Internal Mic";
+		if ((get_defcfg_location(def_conf) & 0xf0)
+						== AC_JACK_LOC_SEPARATE)
+			return "Dock Mic";
+		if (get_defcfg_location(def_conf) == AC_JACK_LOC_REAR)
+			return "Rear Mic";
+		return "Mic";
+	case AC_JACK_LINE_IN:
+		if ((get_defcfg_location(def_conf) & 0xf0)
+						== AC_JACK_LOC_SEPARATE)
+			return "Dock Line";
+		return "Line";
+	case AC_JACK_AUX:
+		return "Aux";
+	case AC_JACK_CD:
+		return "CD";
+	case AC_JACK_SPDIF_IN:
+		return "SPDIF In";
+	case AC_JACK_DIG_OTHER_IN:
+		return "Digital In";
+	}
+
+	snd_printd("invalid inp pin %02x device config %08x", nid, def_conf);
+	return NULL;
+}
+
+static const char *get_unique_inp_src_label(struct hda_codec *codec,
+				hda_nid_t nid)
+{
+	int i, n;
+	const char *label;
+	struct sigmatel_spec *spec = codec->spec;
+	struct hda_input_mux *imux = &spec->private_imux;
+	struct hda_input_mux *dimux = &spec->private_dimux;
+	struct unique_input_names *unames = &spec->private_u_inp_names;
+
+	label = get_input_src_label(codec, nid);
+	n = 0;
+
+	for (i = 0; i < imux->num_items; i++) {
+		if (!strncmp(label, imux->items[i].label, strlen(label)))
+			n++;
+	}
+	if (snd_hda_get_bool_hint(codec, "separate_dmux") == 1) {
+		for (i = 0; i < dimux->num_items; i++) {
+			if (!strncmp(label, dimux->items[i].label,
+					strlen(label)))
+				n++;
+		}
+	}
+	if (n > 0 && unames->num < HDA_MAX_NUM_INPUTS) {
+		sprintf(&unames->uname[unames->num][0], "%.28s %d", label, n);
+		label = &unames->uname[unames->num][0];
+		unames->num++;
+	}
+
+	return label;
+}
+
 /* create playback/capture controls for input pins on dmic capable codecs */
 static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
 						const struct auto_pin_cfg *cfg)
@@ -3459,24 +3535,13 @@
 	struct sigmatel_spec *spec = codec->spec;
 	struct hda_input_mux *imux = &spec->private_imux;
 	struct hda_input_mux *dimux = &spec->private_dimux;
-	int err, i, active_mics;
+	int err, i;
 	unsigned int def_conf;
 
 	dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];
 	dimux->items[dimux->num_items].index = 0;
 	dimux->num_items++;
 
-	active_mics = 0;
-	for (i = 0; i < spec->num_dmics; i++) {
-		/* check the validity: sometimes it's a dead vendor-spec node */
-		if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i]))
-		    != AC_WID_PIN)
-			continue;
-		def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]);
-		if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE)
-			active_mics++;
-	}
-
 	for (i = 0; i < spec->num_dmics; i++) {
 		hda_nid_t nid;
 		int index;
@@ -3493,10 +3558,9 @@
 		if (index < 0)
 			continue;
 
-		if (active_mics == 1)
-			label = "Digital Mic";
-		else
-			label = stac92xx_dmic_labels[dimux->num_items];
+		label = get_unique_inp_src_label(codec, nid);
+		if (label == NULL)
+			return -EINVAL;
 
 		err = create_elem_capture_vol(codec, nid, label, 0, HDA_INPUT);
 		if (err < 0)
@@ -3618,6 +3682,7 @@
 	struct sigmatel_spec *spec = codec->spec;
 	struct hda_input_mux *imux = &spec->private_imux;
 	int i, j, type_idx = 0;
+	const char *label;
 
 	for (i = 0; i < cfg->num_inputs; i++) {
 		hda_nid_t nid = cfg->inputs[i].pin;
@@ -3637,14 +3702,18 @@
 			type_idx++;
 		else
 			type_idx = 0;
+
+		label = get_unique_inp_src_label(codec, nid);
+		if (label == NULL)
+			return -EINVAL;
+
 		err = create_elem_capture_vol(codec, nid,
-					      auto_pin_cfg_labels[i], type_idx,
+					      label, type_idx,
 					      HDA_INPUT);
 		if (err < 0)
 			return err;
 
-		imux->items[imux->num_items].label =
-			snd_hda_get_input_pin_label(cfg, i);
+		imux->items[imux->num_items].label = label;
 		imux->items[imux->num_items].index = index;
 		imux->num_items++;
 	}