}
 EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
 
+/* get a unique suffix or an index number */
+static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
+                                   int num_pins, int *indexp)
+{
+       static const char * const channel_sfx[] = {
+               " Front", " Surrount", " CLFE", " Side"
+       };
+       int i;
+
+       for (i = 0; i < num_pins; i++) {
+               if (pins[i] == nid) {
+                       if (num_pins == 1)
+                               return "";
+                       if (num_pins > ARRAY_SIZE(channel_sfx)) {
+                               if (indexp)
+                                       *indexp = i;
+                               return "";
+                       }
+                       return channel_sfx[i];
+               }
+       }
+       return NULL;
+}
+
+static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
+                              const struct auto_pin_cfg *cfg,
+                              const char *name, char *label, int maxlen,
+                              int *indexp)
+{
+       unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+       int attr = snd_hda_get_input_pin_attr(def_conf);
+       const char *pfx = "", *sfx = "";
+
+       /* handle as a speaker if it's a fixed line-out */
+       if (!strcmp(name, "Line-Out") && attr == INPUT_PIN_ATTR_INT)
+               name = "Speaker";
+       /* check the location */
+       switch (attr) {
+       case INPUT_PIN_ATTR_DOCK:
+               pfx = "Dock ";
+               break;
+       case INPUT_PIN_ATTR_FRONT:
+               pfx = "Front ";
+               break;
+       }
+       if (cfg) {
+               /* try to give a unique suffix if needed */
+               sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
+                                      indexp);
+               if (!sfx)
+                       sfx = check_output_sfx(nid, cfg->hp_pins, cfg->hp_outs,
+                                              indexp);
+               if (!sfx)
+                       sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
+                                              indexp);
+               if (!sfx)
+                       sfx = "";
+       }
+       snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
+       return 1;
+}
+
 /**
  * snd_hda_get_pin_label - Get a label for the given I/O pin
  *
  * Get a label for the given pin.  This function works for both input and
  * output pins.  When @cfg is given as non-NULL, the function tries to get
  * an optimized label using hda_get_autocfg_input_label().
+ *
+ * This function tries to give a unique label string for the pin as much as
+ * possible.  For example, when the multiple line-outs are present, it adds
+ * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
+ * If no unique name with a suffix is available and @indexp is non-NULL, the
+ * index number is stored in the pointer.
  */
-const char *snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
-                                 const struct auto_pin_cfg *cfg)
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+                         const struct auto_pin_cfg *cfg,
+                         char *label, int maxlen, int *indexp)
 {
        unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
-       int attr;
+       const char *name = NULL;
        int i;
 
+       if (indexp)
+               *indexp = 0;
        if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
-               return NULL;
+               return 0;
 
-       attr = snd_hda_get_input_pin_attr(def_conf);
        switch (get_defcfg_device(def_conf)) {
        case AC_JACK_LINE_OUT:
-               switch (attr) {
-               case INPUT_PIN_ATTR_INT:
-                       return "Speaker";
-               case INPUT_PIN_ATTR_DOCK:
-                       return "Dock Line-Out";
-               case INPUT_PIN_ATTR_FRONT:
-                       return "Front Line-Out";
-               default:
-                       return "Line-Out";
-               }
+               return fill_audio_out_name(codec, nid, cfg, "Line-Out",
+                                          label, maxlen, indexp);
        case AC_JACK_SPEAKER:
-               return "Speaker";
+               return fill_audio_out_name(codec, nid, cfg, "Speaker",
+                                          label, maxlen, indexp);
        case AC_JACK_HP_OUT:
-               switch (attr) {
-               case INPUT_PIN_ATTR_DOCK:
-                       return "Dock Headphone";
-               case INPUT_PIN_ATTR_FRONT:
-                       return "Front Headphone";
-               default:
-                       return "Headphone";
-               }
+               return fill_audio_out_name(codec, nid, cfg, "Headphone",
+                                          label, maxlen, indexp);
        case AC_JACK_SPDIF_OUT:
        case AC_JACK_DIG_OTHER_OUT:
                if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)
-                       return "HDMI";
+                       name = "HDMI";
                else
-                       return "SPDIF";
-       }
-
-       if (cfg) {
-               for (i = 0; i < cfg->num_inputs; i++)
-                       if (cfg->inputs[i].pin == nid)
-                               return hda_get_autocfg_input_label(codec, cfg, i);
+                       name = "SPDIF";
+               if (cfg && indexp) {
+                       for (i = 0; i < cfg->dig_outs; i++)
+                               if (cfg->dig_out_pins[i] == nid) {
+                                       *indexp = i;
+                                       break;
+                               }
+               }
+               break;
+       default:
+               if (cfg) {
+                       for (i = 0; i < cfg->num_inputs; i++) {
+                               if (cfg->inputs[i].pin != nid)
+                                       continue;
+                               name = hda_get_autocfg_input_label(codec, cfg, i);
+                               if (name)
+                                       break;
+                       }
+               }
+               if (!name)
+                       name = hda_get_input_pin_label(codec, nid, true);
+               break;
        }
-       return hda_get_input_pin_label(codec, nid, true);
+       if (!name)
+               return 0;
+       strlcpy(label, name, maxlen);
+       return 1;
 }
 EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
 
 
 }
 EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
 
-static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
+static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
                         const struct auto_pin_cfg *cfg)
 {
        unsigned int def_conf, conn;
-       int err;
+       char name[44];
+       int idx, err;
 
        if (!nid)
                return 0;
        if (conn != AC_JACK_PORT_COMPLEX)
                return 0;
 
-       err = snd_hda_jack_add_kctl(codec, nid,
-                                    snd_hda_get_pin_label(codec, nid, cfg),
-                                    idx);
+       snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+       err = snd_hda_jack_add_kctl(codec, nid, name, idx);
        if (err < 0)
                return err;
        return snd_hda_jack_detect_enable(codec, nid, 0);
        int i, err;
 
        for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, i, cfg);
+               err = add_jack_kctl(codec, *p, cfg);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, i, cfg);
+               err = add_jack_kctl(codec, *p, cfg);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
                if (*p == *cfg->line_out_pins) /* might be duplicated */
                        break;
-               err = add_jack_kctl(codec, *p, i, cfg);
+               err = add_jack_kctl(codec, *p, cfg);
                if (err < 0)
                        return err;
        }
        for (i = 0; i < cfg->num_inputs; i++) {
-               err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg);
+               err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg);
                if (err < 0)
                        return err;
        }
        for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
-               err = add_jack_kctl(codec, *p, i, cfg);
+               err = add_jack_kctl(codec, *p, cfg);
                if (err < 0)
                        return err;
        }
-       err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg);
+       err = add_jack_kctl(codec, cfg->dig_in_pin, cfg);
        if (err < 0)
                return err;
-       err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg);
+       err = add_jack_kctl(codec, cfg->mono_out_pin, cfg);
        if (err < 0)
                return err;
        return 0;
 
 const char *hda_get_autocfg_input_label(struct hda_codec *codec,
                                        const struct auto_pin_cfg *cfg,
                                        int input);
-const char *snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
-                                 const struct auto_pin_cfg *cfg);
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+                         const struct auto_pin_cfg *cfg,
+                         char *label, int maxlen, int *indexp);
 int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
                          int index, int *type_index_ret);
 
 
        hda_nid_t dig_out;
        hda_nid_t dig_in;
        unsigned int num_inputs;
-       const char *input_labels[AUTO_PIN_LAST];
+       char input_labels[AUTO_PIN_LAST][32];
        struct hda_pcm pcm_rec[2];      /* PCM information */
 };
 
                if (j >= cfg->num_inputs)
                        continue;
                spec->input_pins[n] = pin;
-               spec->input_labels[n] = snd_hda_get_pin_label(codec, pin, NULL);
+               snd_hda_get_pin_label(codec, pin, cfg,
+                                     spec->input_labels[n],
+                                     sizeof(spec->input_labels[n]), NULL);
                spec->adcs[n] = nid;
                n++;
        }
 
        if (uinfo->value.enumerated.item >= spec->num_inputs)
                uinfo->value.enumerated.item = spec->num_inputs - 1;
        idx = spec->input_idx[uinfo->value.enumerated.item];
-       strcpy(uinfo->value.enumerated.name,
-              snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, NULL));
+       snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, cfg,
+                             uinfo->value.enumerated.name,
+                             sizeof(uinfo->value.enumerated.name), NULL);
        return 0;
 }
 
 
        }
 
        if (control) {
-               strcpy(name, snd_hda_get_pin_label(codec, nid, NULL));
+               snd_hda_get_pin_label(codec, nid, &spec->autocfg,
+                                     name, sizeof(name), NULL);
                return stac92xx_add_control(codec->spec, control,
                                        strcat(name, " Jack Mode"), nid);
        }
        for (i = 0; i < spec->num_dmics; i++) {
                hda_nid_t nid;
                int index, type_idx;
-               const char *label;
+               char label[32];
 
                nid = spec->dmic_nids[i];
                if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
                if (index < 0)
                        continue;
 
-               label = snd_hda_get_pin_label(codec, nid, NULL);
+               snd_hda_get_pin_label(codec, nid, &spec->autocfg,
+                                     label, sizeof(label), NULL);
                snd_hda_add_imux_item(dimux, label, index, &type_idx);
                if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1)
                        snd_hda_add_imux_item(imux, label, index, &type_idx);