]> git.karo-electronics.de Git - linux-beck.git/blobdiff - sound/pci/hda/patch_sigmatel.c
ALSA: hda - Improve input control names for IDT/STAC codecs
[linux-beck.git] / sound / pci / hda / patch_sigmatel.c
index d226edd1e14370208dc03d4adb8b215d93a05f94..7f09e140953eb0c159b317987cb21034ffa2c66a 100644 (file)
@@ -191,6 +191,11 @@ struct sigmatel_mic_route {
        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 sigmatel_spec {
        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] = {
@@ -382,6 +388,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = {
        0x03, 0x0c, 0x20, 0x40,
 };
 
+#define STAC92HD83XXX_NUM_DMICS         2
+static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = {
+       0x11, 0x20, 0
+};
+
 #define STAC92HD83XXX_NUM_CAPS 2
 static unsigned long stac92hd83xxx_capvols[] = {
        HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
@@ -3447,6 +3458,76 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid,
        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)
@@ -3454,24 +3535,13 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
        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;
@@ -3488,10 +3558,9 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
                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)
@@ -3613,6 +3682,7 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
        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;
@@ -3632,14 +3702,18 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const
                        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++;
        }
@@ -4695,6 +4769,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
        }
 }
 
+/* get the pin connection (fixed, none, etc) */
+static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       unsigned int cfg;
+
+       cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
+       return get_defcfg_connect(cfg);
+}
+
+static int stac92xx_connected_ports(struct hda_codec *codec,
+                                        hda_nid_t *nids, int num_nids)
+{
+       struct sigmatel_spec *spec = codec->spec;
+       int idx, num;
+       unsigned int def_conf;
+
+       for (num = 0; num < num_nids; num++) {
+               for (idx = 0; idx < spec->num_pins; idx++)
+                       if (spec->pin_nids[idx] == nids[num])
+                               break;
+               if (idx >= spec->num_pins)
+                       break;
+               def_conf = stac_get_defcfg_connect(codec, idx);
+               if (def_conf == AC_JACK_PORT_NONE)
+                       break;
+       }
+       return num;
+}
+
 static void stac92xx_mic_detect(struct hda_codec *codec)
 {
        struct sigmatel_spec *spec = codec->spec;
@@ -5325,6 +5429,8 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
        spec->linear_tone_beep = 1;
        codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
        spec->digbeep_nid = 0x21;
+       spec->dmic_nids = stac92hd83xxx_dmic_nids;
+       spec->dmux_nids = stac92hd83xxx_mux_nids;
        spec->mux_nids = stac92hd83xxx_mux_nids;
        spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids);
        spec->adc_nids = stac92hd83xxx_adc_nids;
@@ -5370,9 +5476,13 @@ again:
        case 0x111d76d4:
        case 0x111d7605:
        case 0x111d76d5:
+       case 0x111d76e7:
                if (spec->board_config == STAC_92HD83XXX_PWR_REF)
                        break;
                spec->num_pwrs = 0;
+               spec->num_dmics = stac92xx_connected_ports(codec,
+                               stac92hd83xxx_dmic_nids,
+                               STAC92HD83XXX_NUM_DMICS);
                break;
        }
 
@@ -5431,36 +5541,6 @@ again:
        return 0;
 }
 
-/* get the pin connection (fixed, none, etc) */
-static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx)
-{
-       struct sigmatel_spec *spec = codec->spec;
-       unsigned int cfg;
-
-       cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]);
-       return get_defcfg_connect(cfg);
-}
-
-static int stac92hd71bxx_connected_ports(struct hda_codec *codec,
-                                        hda_nid_t *nids, int num_nids)
-{
-       struct sigmatel_spec *spec = codec->spec;
-       int idx, num;
-       unsigned int def_conf;
-
-       for (num = 0; num < num_nids; num++) {
-               for (idx = 0; idx < spec->num_pins; idx++)
-                       if (spec->pin_nids[idx] == nids[num])
-                               break;
-               if (idx >= spec->num_pins)
-                       break;
-               def_conf = stac_get_defcfg_connect(codec, idx);
-               if (def_conf == AC_JACK_PORT_NONE)
-                       break;
-       }
-       return num;
-}
-
 static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec,
                                          hda_nid_t dig0pin)
 {
@@ -5599,7 +5679,7 @@ again:
        case 0x111d76b5:
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
                break;
@@ -5631,7 +5711,7 @@ again:
                snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0);
                snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3);
                stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS - 1);
                break;
@@ -5645,7 +5725,7 @@ again:
        default:
                spec->init = stac92hd71bxx_core_init;
                codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs;
-               spec->num_dmics = stac92hd71bxx_connected_ports(codec,
+               spec->num_dmics = stac92xx_connected_ports(codec,
                                        stac92hd71bxx_dmic_nids,
                                        STAC92HD71BXX_NUM_DMICS);
                break;
@@ -6327,6 +6407,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
        { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
        { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
        { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
+       { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx},
+       { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx},
        {} /* terminator */
 };