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

Commit 81fede89 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: hda/realtek - Add conexant-style inverted dmic handling



To make the parser more generic, a few codes to handle the inverted
stereo dmic in a way Conexant parser does is added in this patch.

The caller should set spec->inv_dmic_split flag appropriately.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 9bf387b6
Loading
Loading
Loading
Loading
+34 −1
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@ 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;
@@ -222,6 +223,7 @@ struct alc_spec {
	unsigned int inv_dmic_muted:1; /* R-ch of inv d-mic is muted? */
	unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */
	unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */
	unsigned int inv_dmic_split:1; /* inverted dmic w/a for conexant */

	unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */

@@ -2550,6 +2552,8 @@ static int parse_capvol_in_path(struct hda_codec *codec, struct nid_path *path)
	return 0;
}

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)
{
@@ -2557,17 +2561,37 @@ static int add_single_cap_ctl(struct hda_codec *codec, const char *label,
	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;
	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);
	else
		snprintf(tmpname, sizeof(tmpname),
			 "Capture %s", sfx);
	return add_control(spec, type, tmpname, idx, ctl);
	err = add_control(spec, type, tmpname, idx,
			  amp_val_replace_channels(ctl, chs));
	if (err < 0 || chs == 3)
		return err;

	/* Make independent right kcontrol */
	if (label)
		snprintf(tmpname, sizeof(tmpname),
			 "Inverted %s Capture %s", label, sfx);
	else
		snprintf(tmpname, sizeof(tmpname),
			 "Inverted Capture %s", sfx);
	return add_control(spec, type, tmpname, idx,
			   amp_val_replace_channels(ctl, 2));
}

/* create single (and simple) capture volume and switch controls */
@@ -2730,6 +2754,7 @@ 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;
@@ -2783,6 +2808,14 @@ 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;