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>
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 42d5a91..8f59e0b 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -438,11 +438,62 @@
#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 @@
&& 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 @@
{
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 @@
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)