Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9907790a authored by Charles Chin's avatar Charles Chin Committed by Takashi Iwai
Browse files

ALSA: hda - Fix automatic MIC switching and include dock MIC for IDT codecs



Signed-off-by: default avatarCharles Chin <Charles.Chin@idt.com>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 30ea098f
Loading
Loading
Loading
Loading
+29 −11
Original line number Original line Diff line number Diff line
@@ -263,6 +263,7 @@ struct sigmatel_spec {


	struct sigmatel_mic_route ext_mic;
	struct sigmatel_mic_route ext_mic;
	struct sigmatel_mic_route int_mic;
	struct sigmatel_mic_route int_mic;
	struct sigmatel_mic_route dock_mic;


	const char **spdif_labels;
	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,
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;
	unsigned int cfg;


@@ -3496,15 +3497,22 @@ static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid,
		return 0;
		return 0;
	cfg = snd_hda_codec_get_pincfg(codec, nid);
	cfg = snd_hda_codec_get_pincfg(codec, nid);
	switch (get_defcfg_connect(cfg)) {
	switch (get_defcfg_connect(cfg)) {
	case AC_JACK_PORT_BOTH:
	case AC_JACK_PORT_FIXED:
	case AC_JACK_PORT_FIXED:
		if (*fixed)
		if (*fixed)
			return 1; /* already occupied */
			return 1; /* already occupied */
		*fixed = nid;
		*fixed = nid;
		break;
		break;
	case AC_JACK_PORT_COMPLEX:
	case AC_JACK_PORT_COMPLEX:
		if ((get_defcfg_location(cfg) & 0xF0) == AC_JACK_LOC_SEPARATE) {
			if (*dock)
				return 1; /* already occupied */
			*dock = nid;
		} else {
			if (*ext)
			if (*ext)
				return 1; /* already occupied */
				return 1; /* already occupied */
			*ext = nid;
			*ext = nid;
		}
		break;
		break;
	}
	}
	return 0;
	return 0;
@@ -3519,6 +3527,8 @@ static int set_mic_route(struct hda_codec *codec,
	int i;
	int i;


	mic->pin = pin;
	mic->pin = pin;
	if (pin == 0)
		return 0;
	for (i = 0; i < cfg->num_inputs; i++) {
	for (i = 0; i < cfg->num_inputs; i++) {
		if (pin == cfg->inputs[i].pin)
		if (pin == cfg->inputs[i].pin)
			break;
			break;
@@ -3554,26 +3564,29 @@ static int stac_check_auto_mic(struct hda_codec *codec)
{
{
	struct sigmatel_spec *spec = codec->spec;
	struct sigmatel_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	hda_nid_t fixed, ext;
	hda_nid_t fixed, ext, dock;
	int i;
	int i;


	for (i = 0; i < cfg->num_inputs; i++) {
	for (i = 0; i < cfg->num_inputs; i++) {
		if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
		if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN)
			return 0; /* must be exclusively mics */
			return 0; /* must be exclusively mics */
	}
	}
	fixed = ext = 0;
	fixed = ext = dock = 0;
	for (i = 0; i < cfg->num_inputs; i++)
	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;
			return 0;
	for (i = 0; i < spec->num_dmics; i++)
	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],
			return 0;
		    &fixed, &ext, &dock))
	if (!fixed || !ext)
			return 0;
			return 0;
	if (!fixed && !ext && !dock)
		return 0; /* no input to switch */
	if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
	if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP))
		return 0; /* no unsol support */
		return 0; /* no unsol support */
	if (set_mic_route(codec, &spec->ext_mic, ext) ||
	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 0; /* something is wrong */
	return 1;
	return 1;
}
}
@@ -4281,6 +4294,9 @@ static int stac92xx_init(struct hda_codec *codec)
					  AC_VERB_SET_CONNECT_SEL, 0);
					  AC_VERB_SET_CONNECT_SEL, 0);
		if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
		if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT))
			stac_issue_unsol_event(codec, spec->ext_mic.pin);
			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++) {
	for (i = 0; i < cfg->num_inputs; i++) {
		hda_nid_t nid = cfg->inputs[i].pin;
		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))
	if (get_pin_presence(codec, spec->ext_mic.pin))
		mic = &spec->ext_mic;
		mic = &spec->ext_mic;
	else if (get_pin_presence(codec, spec->dock_mic.pin))
		mic = &spec->dock_mic;
	else
	else
		mic = &spec->int_mic;
		mic = &spec->int_mic;
	if (mic->dmux_idx >= 0)
	if (mic->dmux_idx >= 0)