summaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/hda_generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda/hda_generic.c')
-rw-r--r--sound/pci/hda/hda_generic.c59
1 files changed, 51 insertions, 8 deletions
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;
}