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

Commit d69607b3 authored by Lydia Wang's avatar Lydia Wang Committed by Takashi Iwai
Browse files

ALSA: hda - Fix VIA output-path init for VT2002P/1802/1812



For VT2002P, VT1802 and VT1812 codecs, the original activate_output_path()
function can't initialize output and hp path correctly, since mixers connected to
output pin widgets are not considered. So modify the activate_output_path()
function to satisify this kind of codec.

Signed-off-by: default avatarLydia Wang <lydiawang@viatech.com.cn>
Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 1d045db9
Loading
Loading
Loading
Loading
+67 −37
Original line number Diff line number Diff line
@@ -438,11 +438,62 @@ static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
#define have_mute(codec, nid, dir) \
	check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE)

static bool is_node_in_path(struct nid_path *path, hda_nid_t nid)
{
	int i;
	if (!nid)
		return false;
	for (i = 0; i < path->depth; i++) {
		if (path->path[i] == nid)
			return true;
	}
	return false;
}

/* enable/disable the output-route mixers */
static void activate_output_mix(struct hda_codec *codec, struct nid_path *path,
				 hda_nid_t mix_nid, int aa_mix_idx, bool enable)
{
	int i, num, val;
	bool hp_path, front_path;
	struct via_spec *spec = codec->spec;

	if (!path)
		return;
	num = snd_hda_get_conn_list(codec, mix_nid, NULL);
	hp_path = is_node_in_path(path, spec->hp_dac_nid);
	front_path = is_node_in_path(path, spec->multiout.dac_nids[0]);

	for (i = 0; i < num; i++) {
		if (i == aa_mix_idx) {
			if (hp_path)
				val = enable ? AMP_IN_MUTE(i) :
				AMP_IN_UNMUTE(i);
			else if (front_path)
				val = AMP_IN_UNMUTE(i);
			else
				val = AMP_IN_MUTE(i);
		} else {
			if (hp_path)
				val = enable ? AMP_IN_UNMUTE(i) :
				AMP_IN_MUTE(i);
			else if (front_path)
				val = AMP_IN_MUTE(i);
			else
				val = AMP_IN_UNMUTE(i);
		}
		snd_hda_codec_write(codec, mix_nid, 0,
				    AC_VERB_SET_AMP_GAIN_MUTE, val);
	}
}

/* enable/disable the output-route */
static void activate_output_path(struct hda_codec *codec, struct nid_path *path,
				 bool enable, bool force)
{
	int i;
	int i, val;
	struct via_spec *spec = codec->spec;
	hda_nid_t aa_mix_nid = spec->aa_mix_nid;
	for (i = 0; i < path->depth; i++) {
		hda_nid_t src, dst;
		int idx = path->idx[i];
@@ -459,10 +510,19 @@ static void activate_output_path(struct hda_codec *codec, struct nid_path *path,
		    && get_wcaps_type(get_wcaps(codec, dst)) == AC_WID_AUD_MIX)
			continue;
		if (have_mute(codec, dst, HDA_INPUT)) {
			int val = enable ? AMP_IN_UNMUTE(idx) :
			if (dst == aa_mix_nid) {
				val = enable ? AMP_IN_UNMUTE(idx) :
					AMP_IN_MUTE(idx);
				snd_hda_codec_write(codec, dst, 0,
					AC_VERB_SET_AMP_GAIN_MUTE, val);
			} else {
				idx = get_connection_index(codec, dst,
							   aa_mix_nid);
				if (idx >= 0) {
					activate_output_mix(codec, path,
							    dst, idx, enable);
				}
			}
		}
		if (!force && (src == path->vol_ctl || src == path->mute_ctl))
			continue;
@@ -493,8 +553,7 @@ static void via_auto_init_output(struct hda_codec *codec,
{
	struct via_spec *spec = codec->spec;
	unsigned int caps;
	hda_nid_t pin, nid, pre_nid;
	int i, idx, j, num;
	hda_nid_t pin;

	if (!path->depth)
		return;
@@ -509,39 +568,10 @@ static void via_auto_init_output(struct hda_codec *codec,
				    AMP_OUT_MUTE | val);
	}

	activate_output_path(codec, path, true, force);

	/* initialize the AA-path */
	if (!spec->aa_mix_nid)
		return;
	for (i = path->depth - 1; i > 0; i--) {
		nid = path->path[i];
		pre_nid = path->path[i - 1];
		idx = get_connection_index(codec, nid, spec->aa_mix_nid);
		if (idx >= 0) {
			if (have_mute(codec, nid, HDA_INPUT)) {
				unsigned int mute = with_aa_mix ?
					AMP_IN_UNMUTE(idx) : AMP_IN_MUTE(idx);
				snd_hda_codec_write(codec, nid, 0,
						    AC_VERB_SET_AMP_GAIN_MUTE,
						    mute);
				/* exclusively via aa-mix for front */
				if (pre_nid == spec->multiout.dac_nids[0]) {
					num = snd_hda_get_conn_list(codec, nid,
								    NULL);
					for (j = 0; j < num; j++) {
						if (j == idx)
							continue;
						snd_hda_codec_write(codec,
						    nid, 0,
						    AC_VERB_SET_AMP_GAIN_MUTE,
						    AMP_IN_MUTE(j));
					}
				}
			}
			break;
		}
	}
	activate_output_path(codec, path, true, force);
}

static void via_auto_init_multi_out(struct hda_codec *codec)