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: Lydia Wang <lydiawang@viatech.com.cn>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Lydia Wang 2011-07-08 14:02:52 +08:00 committed by Takashi Iwai
parent 1d045db96a
commit d69607b3c3

View File

@ -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) :
AMP_IN_MUTE(idx);
snd_hda_codec_write(codec, dst, 0,
AC_VERB_SET_AMP_GAIN_MUTE, val);
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)