diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index e26e8d3430f2..6d1e843c6e8d 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c @@ -1845,6 +1845,10 @@ static int indep_hp_get(struct snd_kcontrol *kcontrol, return 0; } +static void update_aamix_paths(struct hda_codec *codec, bool do_mix, + int nomix_path_idx, int mix_path_idx, + int out_type); + static int indep_hp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { @@ -1860,11 +1864,31 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol, } if (spec->indep_hp_enabled != select) { + hda_nid_t *dacp; + if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT) + dacp = &spec->private_dac_nids[0]; + else + dacp = &spec->multiout.hp_out_nid[0]; + + /* update HP aamix paths in case it conflicts with indep HP */ + if (spec->have_aamix_ctl) { + if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT) + update_aamix_paths(codec, spec->aamix_mode, + spec->out_paths[0], + spec->aamix_out_paths[0], + spec->autocfg.line_out_type); + else + update_aamix_paths(codec, spec->aamix_mode, + spec->hp_paths[0], + spec->aamix_out_paths[1], + AUTO_PIN_HP_OUT); + } + spec->indep_hp_enabled = select; if (spec->indep_hp_enabled) - spec->multiout.hp_out_nid[0] = 0; + *dacp = 0; else - spec->multiout.hp_out_nid[0] = spec->alt_dac_nid; + *dacp = spec->alt_dac_nid; ret = 1; } unlock: @@ -1884,16 +1908,21 @@ static const struct snd_kcontrol_new indep_hp_ctl = { static int create_indep_hp_ctls(struct hda_codec *codec) { struct hda_gen_spec *spec = codec->spec; + hda_nid_t dac; if (!spec->indep_hp) return 0; - if (!spec->multiout.hp_out_nid[0]) { + if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT) + dac = spec->multiout.dac_nids[0]; + else + dac = spec->multiout.hp_out_nid[0]; + if (!dac) { spec->indep_hp = 0; return 0; } spec->indep_hp_enabled = false; - spec->alt_dac_nid = spec->multiout.hp_out_nid[0]; + spec->alt_dac_nid = dac; if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl)) return -ENOMEM; return 0; @@ -2026,14 +2055,24 @@ static int loopback_mixing_get(struct snd_kcontrol *kcontrol, } static void update_aamix_paths(struct hda_codec *codec, bool do_mix, - int nomix_path_idx, int mix_path_idx) + int nomix_path_idx, int mix_path_idx, + int out_type) { + struct hda_gen_spec *spec = codec->spec; struct nid_path *nomix_path, *mix_path; nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx); mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx); if (!nomix_path || !mix_path) return; + + /* if HP aamix path is driven from a different DAC and the + * independent HP mode is ON, can't turn on aamix path + */ + if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled && + mix_path->path[0] != spec->alt_dac_nid) + do_mix = false; + if (do_mix) { snd_hda_activate_path(codec, nomix_path, false, true); snd_hda_activate_path(codec, mix_path, true, true); @@ -2054,11 +2093,14 @@ static int loopback_mixing_put(struct snd_kcontrol *kcontrol, return 0; spec->aamix_mode = val; update_aamix_paths(codec, val, spec->out_paths[0], - spec->aamix_out_paths[0]); + spec->aamix_out_paths[0], + spec->autocfg.line_out_type); update_aamix_paths(codec, val, spec->hp_paths[0], - spec->aamix_out_paths[1]); + spec->aamix_out_paths[1], + AUTO_PIN_HP_OUT); update_aamix_paths(codec, val, spec->speaker_paths[0], - spec->aamix_out_paths[2]); + spec->aamix_out_paths[2], + AUTO_PIN_SPEAKER_OUT); return 1; } @@ -2081,6 +2123,7 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec) return 0; if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum)) return -ENOMEM; + spec->have_aamix_ctl = 1; return 0; } diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 696b6068a889..9c63555b971c 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h @@ -212,6 +212,7 @@ struct hda_gen_spec { unsigned int no_analog:1; /* digital I/O only */ unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ unsigned int indep_hp_enabled:1; /* independent HP enabled */ + unsigned int have_aamix_ctl:1; /* loopback mixing mode */ bool aamix_mode;