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 e57698f611aba854a89771d893e68604deb1ed4b..e050f893bf750cf69628fadc673cc9681b3f99f4 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 25f756533bec749d49b689cb3b13dfd058e64dba..394901515d9ef696843c5a7f35dfee5998d623a8 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 13f681480a3837a17e064da29865efedde78d479..ef09716aeb6f90fe0eaa114129571224301843de 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 6bd602bfe0fe5f76c18946b5e12b868805e854d9..09ccfabb4a17c38a608d04d05b4a5979e6dc7ed7 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 0e34554bc45e0ed44ad945eef59d04df7e2c7a82..0ba03878c5e0eed4bdcd30acf7fc581bb81326a0 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 73bf7cd0a6e4266f73582618e68676e15f0a64f2..0988dc4890a1a52a958e1d3fcddc6181c7c5df35 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);