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

Commit 7e35dd3d authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/realtek - Fix split stereo dmic code



The previous commit passed an utterly wrong value for checking the
split inv dmic pin.  This patch fixes it and also tries to remove
inv_dmic_split_idx field.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent c9ce6b26
Loading
Loading
Loading
Loading
+36 −22
Original line number Diff line number Diff line
@@ -182,7 +182,6 @@ struct alc_spec {
	int int_mic_idx, ext_mic_idx, dock_mic_idx; /* for auto-mic */
	hda_nid_t inv_dmic_pin;
	hda_nid_t shared_mic_vref_pin;
	int inv_dmic_split_idx;	/* used internally for inv_dmic_split */

	/* DAC list */
	int num_all_dacs;
@@ -2552,23 +2551,19 @@ static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
static unsigned int amp_val_replace_channels(unsigned int val, unsigned int chs);

static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
			      int idx, bool is_switch, unsigned int ctl)
			      int idx, bool is_switch, unsigned int ctl,
			      bool inv_dmic)
{
	struct alc_spec *spec = codec->spec;
	char tmpname[44];
	int type = is_switch ? ALC_CTL_WIDGET_MUTE : ALC_CTL_WIDGET_VOL;
	const char *sfx = is_switch ? "Switch" : "Volume";
	unsigned int chs;
	unsigned int chs = inv_dmic ? 1 : 3;
	int err;

	if (!ctl)
		return 0;

	if (idx == spec->inv_dmic_split_idx)
		chs = 1;
	else
		chs = 3;

	if (label)
		snprintf(tmpname, sizeof(tmpname),
			 "%s Capture %s", label, sfx);
@@ -2591,15 +2586,36 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
			   amp_val_replace_channels(ctl, 2));
}

static bool is_inv_dmic_pin(struct hda_codec *codec, hda_nid_t nid)
{
	struct alc_spec *spec = codec->spec;
	struct auto_pin_cfg *cfg = &spec->autocfg;
	unsigned int val;
	int i;

	if (!spec->inv_dmic_split)
		return false;
	for (i = 0; i < cfg->num_inputs; i++) {
		if (cfg->inputs[i].pin != nid)
			continue;
		if (cfg->inputs[i].type != AUTO_PIN_MIC)
			return false;
		val = snd_hda_codec_get_pincfg(codec, nid);
		return snd_hda_get_input_pin_attr(val) == INPUT_PIN_ATTR_INT;
	}
	return false;
}

/* create single (and simple) capture volume and switch controls */
static int create_single_cap_vol_ctl(struct hda_codec *codec, int idx,
				     unsigned int vol_ctl, unsigned int sw_ctl)
				     unsigned int vol_ctl, unsigned int sw_ctl,
				     bool inv_dmic)
{
	int err;
	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl);
	err = add_single_cap_ctl(codec, NULL, idx, false, vol_ctl, inv_dmic);
	if (err < 0)
		return err;
	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl);
	err = add_single_cap_ctl(codec, NULL, idx, true, sw_ctl, inv_dmic);
	if (err < 0)
		return err;
	return 0;
@@ -2665,16 +2681,19 @@ static int create_multi_cap_vol_ctl(struct hda_codec *codec)

	for (i = 0; i < imux->num_items; i++) {
		const char *label;
		bool inv_dmic;
		label = hda_get_autocfg_input_label(codec, &spec->autocfg, i);
		if (prev_label && !strcmp(label, prev_label))
			type_idx++;
		else
			type_idx = 0;
		prev_label = label;
		inv_dmic = is_inv_dmic_pin(codec, spec->imux_pins[i]);

		for (type = 0; type < 2; type++) {
			err = add_single_cap_ctl(codec, label, type_idx, type,
						 get_first_cap_ctl(codec, i, type));
						 get_first_cap_ctl(codec, i, type),
						 inv_dmic);
			if (err < 0)
				return err;
		}
@@ -2703,6 +2722,7 @@ static int create_capture_mixers(struct hda_codec *codec)

	for (n = 0; n < nums; n++) {
		bool multi = false;
		bool inv_dmic = false;
		int vol, sw;

		vol = sw = 0;
@@ -2721,10 +2741,13 @@ static int create_capture_mixers(struct hda_codec *codec)
				sw = path->ctls[NID_PATH_MUTE_CTL];
			else if (sw != path->ctls[NID_PATH_MUTE_CTL])
				multi = true;
			if (is_inv_dmic_pin(codec, spec->imux_pins[i]))
				inv_dmic = true;
		}

		if (!multi)
			err = create_single_cap_vol_ctl(codec, n, vol, sw);
			err = create_single_cap_vol_ctl(codec, n, vol, sw,
							inv_dmic);
		else if (!spec->multi_cap_vol)
			err = create_bind_cap_vol_ctl(codec, n, vol, sw);
		else
@@ -2751,7 +2774,6 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
	if (num_adcs < 0)
		return 0;

	spec->inv_dmic_split_idx = -1;
	for (i = 0; i < cfg->num_inputs; i++) {
		hda_nid_t pin;
		const char *label;
@@ -2805,14 +2827,6 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
				imux_added = true;
			}
		}

		if (spec->inv_dmic_split) {
			if (cfg->inputs[i].type == AUTO_PIN_MIC) {
				unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin);
				if (snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT)
					spec->inv_dmic_split_idx = i;
			}
		}
	}

	return 0;