|
@@ -263,6 +263,7 @@ struct sigmatel_spec {
|
|
|
|
|
|
struct sigmatel_mic_route ext_mic;
|
|
|
struct sigmatel_mic_route int_mic;
|
|
|
+ struct sigmatel_mic_route dock_mic;
|
|
|
|
|
|
const char **spdif_labels;
|
|
|
|
|
@@ -3488,7 +3489,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
|
|
|
}
|
|
|
|
|
|
static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
|
|
|
- hda_nid_t *fixed, hda_nid_t *ext)
|
|
|
+ hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock)
|
|
|
{
|
|
|
unsigned int cfg;
|
|
|
|
|
@@ -3496,15 +3497,22 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
|
|
|
return 0;
|
|
|
cfg = snd_hda_codec_get_pincfg(codec, nid);
|
|
|
switch (get_defcfg_connect(cfg)) {
|
|
|
+ case AC_JACK_PORT_BOTH:
|
|
|
case AC_JACK_PORT_FIXED:
|
|
|
if (*fixed)
|
|
|
return 1; /* already occupied */
|
|
|
*fixed = nid;
|
|
|
break;
|
|
|
case AC_JACK_PORT_COMPLEX:
|
|
|
- if (*ext)
|
|
|
- return 1; /* already occupied */
|
|
|
- *ext = nid;
|
|
|
+ if ((get_defcfg_location(cfg) & 0xF0) == AC_JACK_LOC_SEPARATE) {
|
|
|
+ if (*dock)
|
|
|
+ return 1; /* already occupied */
|
|
|
+ *dock = nid;
|
|
|
+ } else {
|
|
|
+ if (*ext)
|
|
|
+ return 1; /* already occupied */
|
|
|
+ *ext = nid;
|
|
|
+ }
|
|
|
break;
|
|
|
}
|
|
|
return 0;
|
|
@@ -3519,6 +3527,8 @@ static int set_mic_route(struct hda_codec *codec,
|
|
|
int i;
|
|
|
|
|
|
mic->pin = pin;
|
|
|
+ if (pin == 0)
|
|
|
+ return 0;
|
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
if (pin == cfg->inputs[i].pin)
|
|
|
break;
|
|
@@ -3554,26 +3564,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
|
|
|
{
|
|
|
struct sigmatel_spec *spec = codec->spec;
|
|
|
struct auto_pin_cfg *cfg = &spec->autocfg;
|
|
|
- hda_nid_t fixed, ext;
|
|
|
+ hda_nid_t fixed, ext, dock;
|
|
|
int i;
|
|
|
|
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
|
|
|
return 0; /* must be exclusively mics */
|
|
|
}
|
|
|
- fixed = ext = 0;
|
|
|
+ fixed = ext = dock = 0;
|
|
|
for (i = 0; i < cfg->num_inputs; i++)
|
|
|
- if (check_mic_pin(codec, cfg->inputs[i].pin, &fixed, &ext))
|
|
|
+ if (check_mic_pin(codec, cfg->inputs[i].pin,
|
|
|
+ &fixed, &ext, &dock))
|
|
|
return 0;
|
|
|
for (i = 0; i < spec->num_dmics; i++)
|
|
|
- if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext))
|
|
|
+ if (check_mic_pin(codec, spec->dmic_nids[i],
|
|
|
+ &fixed, &ext, &dock))
|
|
|
return 0;
|
|
|
- if (!fixed || !ext)
|
|
|
- return 0;
|
|
|
+ if (!fixed && !ext && !dock)
|
|
|
+ return 0; /* no input to switch */
|
|
|
if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
|
|
|
return 0; /* no unsol support */
|
|
|
if (set_mic_route(codec, &spec->ext_mic, ext) ||
|
|
|
- set_mic_route(codec, &spec->int_mic, fixed))
|
|
|
+ set_mic_route(codec, &spec->int_mic, fixed) ||
|
|
|
+ set_mic_route(codec, &spec->dock_mic, dock))
|
|
|
return 0; /* something is wrong */
|
|
|
return 1;
|
|
|
}
|
|
@@ -4281,6 +4294,9 @@ static int stac92xx_init(struct hda_codec *codec)
|
|
|
AC_VERB_SET_CONNECT_SEL, 0);
|
|
|
if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
|
|
|
stac_issue_unsol_event(codec, spec->ext_mic.pin);
|
|
|
+ if (enable_pin_detect(codec, spec->dock_mic.pin,
|
|
|
+ STAC_MIC_EVENT))
|
|
|
+ stac_issue_unsol_event(codec, spec->dock_mic.pin);
|
|
|
}
|
|
|
for (i = 0; i < cfg->num_inputs; i++) {
|
|
|
hda_nid_t nid = cfg->inputs[i].pin;
|
|
@@ -4698,6 +4714,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
|
|
|
|
|
|
if (get_pin_presence(codec, spec->ext_mic.pin))
|
|
|
mic = &spec->ext_mic;
|
|
|
+ else if (get_pin_presence(codec, spec->dock_mic.pin))
|
|
|
+ mic = &spec->dock_mic;
|
|
|
else
|
|
|
mic = &spec->int_mic;
|
|
|
if (mic->dmux_idx >= 0)
|