diff options
Diffstat (limited to 'sound/pci/hda/patch_via.c')
-rw-r--r-- | sound/pci/hda/patch_via.c | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 42d5a91781fc..8f59e0b5d477 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c @@ -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) |