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

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
...@@ -438,11 +438,62 @@ static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, ...@@ -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) \ #define have_mute(codec, nid, dir) \
check_amp_caps(codec, nid, dir, AC_AMPCAP_MUTE) 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 */ /* enable/disable the output-route */
static void activate_output_path(struct hda_codec *codec, struct nid_path *path, static void activate_output_path(struct hda_codec *codec, struct nid_path *path,
bool enable, bool force) 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++) { for (i = 0; i < path->depth; i++) {
hda_nid_t src, dst; hda_nid_t src, dst;
int idx = path->idx[i]; int idx = path->idx[i];
...@@ -459,10 +510,19 @@ static void activate_output_path(struct hda_codec *codec, struct nid_path *path, ...@@ -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) && get_wcaps_type(get_wcaps(codec, dst)) == AC_WID_AUD_MIX)
continue; continue;
if (have_mute(codec, dst, HDA_INPUT)) { 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); AMP_IN_MUTE(idx);
snd_hda_codec_write(codec, dst, 0, snd_hda_codec_write(codec, dst, 0,
AC_VERB_SET_AMP_GAIN_MUTE, val); 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)) if (!force && (src == path->vol_ctl || src == path->mute_ctl))
continue; continue;
...@@ -493,8 +553,7 @@ static void via_auto_init_output(struct hda_codec *codec, ...@@ -493,8 +553,7 @@ static void via_auto_init_output(struct hda_codec *codec,
{ {
struct via_spec *spec = codec->spec; struct via_spec *spec = codec->spec;
unsigned int caps; unsigned int caps;
hda_nid_t pin, nid, pre_nid; hda_nid_t pin;
int i, idx, j, num;
if (!path->depth) if (!path->depth)
return; return;
...@@ -509,39 +568,10 @@ static void via_auto_init_output(struct hda_codec *codec, ...@@ -509,39 +568,10 @@ static void via_auto_init_output(struct hda_codec *codec,
AMP_OUT_MUTE | val); AMP_OUT_MUTE | val);
} }
activate_output_path(codec, path, true, force);
/* initialize the AA-path */ /* initialize the AA-path */
if (!spec->aa_mix_nid) if (!spec->aa_mix_nid)
return; return;
for (i = path->depth - 1; i > 0; i--) { activate_output_path(codec, path, true, force);
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;
}
}
} }
static void via_auto_init_multi_out(struct hda_codec *codec) static void via_auto_init_multi_out(struct hda_codec *codec)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment