ALSA: hda - Give more unique names by snd_hda_get_pin_label()
authorTakashi Iwai <tiwai@suse.de>
Wed, 16 Nov 2011 14:33:26 +0000 (15:33 +0100)
committerTakashi Iwai <tiwai@suse.de>
Wed, 16 Nov 2011 14:48:23 +0000 (15:48 +0100)
The function now gives more unique names for the output pins by adding
some prefix and suffix for the location and the channels.  Otherwise, it
can pass the index number.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_jack.c
sound/pci/hda/hda_local.h
sound/pci/hda/patch_ca0110.c
sound/pci/hda/patch_cirrus.c
sound/pci/hda/patch_sigmatel.c

index e57698f..e050f89 100644 (file)
@@ -5066,61 +5066,136 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
 }
 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);
 
index 25f7565..3949015 100644 (file)
@@ -232,11 +232,12 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
 }
 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;
@@ -247,9 +248,8 @@ static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
        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);
@@ -265,38 +265,38 @@ int snd_hda_jack_add_kctls(struct hda_codec *codec,
        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;
index 13f6814..ef09716 100644 (file)
@@ -397,8 +397,9 @@ struct auto_pin_cfg;
 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);
 
index 6bd602b..09ccfab 100644 (file)
@@ -41,7 +41,7 @@ struct ca0110_spec {
        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 */
 };
 
@@ -476,7 +476,9 @@ static void parse_input(struct hda_codec *codec)
                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++;
        }
index 0e34554..0ba0387 100644 (file)
@@ -711,8 +711,9 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
        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;
 }
 
index 73bf7cd..0988dc4 100644 (file)
@@ -2867,7 +2867,8 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
        }
 
        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);
        }
@@ -3545,7 +3546,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
        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)
@@ -3558,7 +3559,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                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);