aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2013-01-21 09:11:25 -0500
committerTakashi Iwai <tiwai@suse.de>2013-01-21 09:11:25 -0500
commita1e908edccd1b6928cda78371026b458e2c1973a (patch)
treea6db12980efa5d13dee688dabeb51b1a4f2f44b8
parentf87498b65197f951899d8bbd99e5553227c41ec9 (diff)
ALSA: hda - Fix conflicts between Loopback Mixing and Independent HP
This patch eventually fixes two issues: - Handle the case where the primary output is a headphone and can have independent HP mode; so far we checked only the case where the headphone is the secondary output. - Fix the conflict of HP independent mode and aamix mode; when switched to aamix mode, the DAC might be also switched to another widget shared with other outputs. Then even if we disable the DAC for the original output, it doesn't change -- because the active route is from another (shared) DAC to HP pin through aamix. So, in such a case, we have to prohibit the switch to aamix for HP routes. This fixes issues appearing on VT codecs. Signed-off-by: Takashi Iwai <tiwai@suse.de>
-rw-r--r--sound/pci/hda/hda_generic.c59
-rw-r--r--sound/pci/hda/hda_generic.h1
2 files changed, 52 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,
1845 return 0; 1845 return 0;
1846} 1846}
1847 1847
1848static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
1849 int nomix_path_idx, int mix_path_idx,
1850 int out_type);
1851
1848static int indep_hp_put(struct snd_kcontrol *kcontrol, 1852static int indep_hp_put(struct snd_kcontrol *kcontrol,
1849 struct snd_ctl_elem_value *ucontrol) 1853 struct snd_ctl_elem_value *ucontrol)
1850{ 1854{
@@ -1860,11 +1864,31 @@ static int indep_hp_put(struct snd_kcontrol *kcontrol,
1860 } 1864 }
1861 1865
1862 if (spec->indep_hp_enabled != select) { 1866 if (spec->indep_hp_enabled != select) {
1867 hda_nid_t *dacp;
1868 if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
1869 dacp = &spec->private_dac_nids[0];
1870 else
1871 dacp = &spec->multiout.hp_out_nid[0];
1872
1873 /* update HP aamix paths in case it conflicts with indep HP */
1874 if (spec->have_aamix_ctl) {
1875 if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
1876 update_aamix_paths(codec, spec->aamix_mode,
1877 spec->out_paths[0],
1878 spec->aamix_out_paths[0],
1879 spec->autocfg.line_out_type);
1880 else
1881 update_aamix_paths(codec, spec->aamix_mode,
1882 spec->hp_paths[0],
1883 spec->aamix_out_paths[1],
1884 AUTO_PIN_HP_OUT);
1885 }
1886
1863 spec->indep_hp_enabled = select; 1887 spec->indep_hp_enabled = select;
1864 if (spec->indep_hp_enabled) 1888 if (spec->indep_hp_enabled)
1865 spec->multiout.hp_out_nid[0] = 0; 1889 *dacp = 0;
1866 else 1890 else
1867 spec->multiout.hp_out_nid[0] = spec->alt_dac_nid; 1891 *dacp = spec->alt_dac_nid;
1868 ret = 1; 1892 ret = 1;
1869 } 1893 }
1870 unlock: 1894 unlock:
@@ -1884,16 +1908,21 @@ static const struct snd_kcontrol_new indep_hp_ctl = {
1884static int create_indep_hp_ctls(struct hda_codec *codec) 1908static int create_indep_hp_ctls(struct hda_codec *codec)
1885{ 1909{
1886 struct hda_gen_spec *spec = codec->spec; 1910 struct hda_gen_spec *spec = codec->spec;
1911 hda_nid_t dac;
1887 1912
1888 if (!spec->indep_hp) 1913 if (!spec->indep_hp)
1889 return 0; 1914 return 0;
1890 if (!spec->multiout.hp_out_nid[0]) { 1915 if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
1916 dac = spec->multiout.dac_nids[0];
1917 else
1918 dac = spec->multiout.hp_out_nid[0];
1919 if (!dac) {
1891 spec->indep_hp = 0; 1920 spec->indep_hp = 0;
1892 return 0; 1921 return 0;
1893 } 1922 }
1894 1923
1895 spec->indep_hp_enabled = false; 1924 spec->indep_hp_enabled = false;
1896 spec->alt_dac_nid = spec->multiout.hp_out_nid[0]; 1925 spec->alt_dac_nid = dac;
1897 if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl)) 1926 if (!snd_hda_gen_add_kctl(spec, NULL, &indep_hp_ctl))
1898 return -ENOMEM; 1927 return -ENOMEM;
1899 return 0; 1928 return 0;
@@ -2026,14 +2055,24 @@ static int loopback_mixing_get(struct snd_kcontrol *kcontrol,
2026} 2055}
2027 2056
2028static void update_aamix_paths(struct hda_codec *codec, bool do_mix, 2057static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
2029 int nomix_path_idx, int mix_path_idx) 2058 int nomix_path_idx, int mix_path_idx,
2059 int out_type)
2030{ 2060{
2061 struct hda_gen_spec *spec = codec->spec;
2031 struct nid_path *nomix_path, *mix_path; 2062 struct nid_path *nomix_path, *mix_path;
2032 2063
2033 nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx); 2064 nomix_path = snd_hda_get_path_from_idx(codec, nomix_path_idx);
2034 mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx); 2065 mix_path = snd_hda_get_path_from_idx(codec, mix_path_idx);
2035 if (!nomix_path || !mix_path) 2066 if (!nomix_path || !mix_path)
2036 return; 2067 return;
2068
2069 /* if HP aamix path is driven from a different DAC and the
2070 * independent HP mode is ON, can't turn on aamix path
2071 */
2072 if (out_type == AUTO_PIN_HP_OUT && spec->indep_hp_enabled &&
2073 mix_path->path[0] != spec->alt_dac_nid)
2074 do_mix = false;
2075
2037 if (do_mix) { 2076 if (do_mix) {
2038 snd_hda_activate_path(codec, nomix_path, false, true); 2077 snd_hda_activate_path(codec, nomix_path, false, true);
2039 snd_hda_activate_path(codec, mix_path, true, true); 2078 snd_hda_activate_path(codec, mix_path, true, true);
@@ -2054,11 +2093,14 @@ static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
2054 return 0; 2093 return 0;
2055 spec->aamix_mode = val; 2094 spec->aamix_mode = val;
2056 update_aamix_paths(codec, val, spec->out_paths[0], 2095 update_aamix_paths(codec, val, spec->out_paths[0],
2057 spec->aamix_out_paths[0]); 2096 spec->aamix_out_paths[0],
2097 spec->autocfg.line_out_type);
2058 update_aamix_paths(codec, val, spec->hp_paths[0], 2098 update_aamix_paths(codec, val, spec->hp_paths[0],
2059 spec->aamix_out_paths[1]); 2099 spec->aamix_out_paths[1],
2100 AUTO_PIN_HP_OUT);
2060 update_aamix_paths(codec, val, spec->speaker_paths[0], 2101 update_aamix_paths(codec, val, spec->speaker_paths[0],
2061 spec->aamix_out_paths[2]); 2102 spec->aamix_out_paths[2],
2103 AUTO_PIN_SPEAKER_OUT);
2062 return 1; 2104 return 1;
2063} 2105}
2064 2106
@@ -2081,6 +2123,7 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
2081 return 0; 2123 return 0;
2082 if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum)) 2124 if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
2083 return -ENOMEM; 2125 return -ENOMEM;
2126 spec->have_aamix_ctl = 1;
2084 return 0; 2127 return 0;
2085} 2128}
2086 2129
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 {
212 unsigned int no_analog:1; /* digital I/O only */ 212 unsigned int no_analog:1; /* digital I/O only */
213 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ 213 unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
214 unsigned int indep_hp_enabled:1; /* independent HP enabled */ 214 unsigned int indep_hp_enabled:1; /* independent HP enabled */
215 unsigned int have_aamix_ctl:1;
215 216
216 /* loopback mixing mode */ 217 /* loopback mixing mode */
217 bool aamix_mode; 218 bool aamix_mode;