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;
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] = {
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),
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)
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;
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)
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;
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++;
}
}
}
+/* 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;
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;
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;
}
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)
{
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;
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;
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;
{ .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 */
};