diff options
author | Takashi Iwai <tiwai@suse.de> | 2013-01-17 10:20:14 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2013-01-17 10:20:14 -0500 |
commit | 8f0fdc09aacbf5df5ddeeb8768625ae9c52fab0f (patch) | |
tree | 0fb489be08327ecd27c9f124de9bb78775cd04fa /sound/pci/hda | |
parent | f6655d52a36ccb27e1cf918dfa7221923964ab21 (diff) | |
parent | 247d85ee068610c50d66ee0cd3130e02c69f5f2e (diff) |
Merge branch 'test/hda-gen-parser' into test/hda-migrate
* test/hda-gen-parser:
ALSA: hda - Improve naming rule for primary output
ALSA: hda - Add PCM capture hook to hda_gen_spec
ALSA: hda - Record all detected ADCs in hda_gen_spec
ALSA: hda - Move vmaster TLV parsing to snd_hda_gen_parse_auto_config()
ALSA: hda - Add input jack mode enum controls to generic parser
ALSA: hda - Give more comments to hda_gen_spec flags
ALSA: hda - Add suppress_auto_mute flag to hda_gen_spec
ALSA: hda - Record the current speaker / LO mute status in hda_gen_spec
ALSA: hda - Properly call automute/switch hooks at init
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/hda_generic.c | 312 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.h | 38 |
2 files changed, 315 insertions, 35 deletions
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 73900d935681..ef4c04adbc21 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/sort.h> | 26 | #include <linux/sort.h> |
27 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
28 | #include <linux/string.h> | 28 | #include <linux/string.h> |
29 | #include <linux/bitops.h> | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/jack.h> | 31 | #include <sound/jack.h> |
31 | #include "hda_codec.h" | 32 | #include "hda_codec.h" |
@@ -119,6 +120,9 @@ static void parse_user_hints(struct hda_codec *codec) | |||
119 | if (val >= 0) | 120 | if (val >= 0) |
120 | codec->single_adc_amp = !!val; | 121 | codec->single_adc_amp = !!val; |
121 | 122 | ||
123 | val = snd_hda_get_bool_hint(codec, "auto_mute"); | ||
124 | if (val >= 0) | ||
125 | spec->suppress_auto_mute = !val; | ||
122 | val = snd_hda_get_bool_hint(codec, "auto_mic"); | 126 | val = snd_hda_get_bool_hint(codec, "auto_mic"); |
123 | if (val >= 0) | 127 | if (val >= 0) |
124 | spec->suppress_auto_mic = !val; | 128 | spec->suppress_auto_mic = !val; |
@@ -146,6 +150,9 @@ static void parse_user_hints(struct hda_codec *codec) | |||
146 | val = snd_hda_get_bool_hint(codec, "add_out_jack_modes"); | 150 | val = snd_hda_get_bool_hint(codec, "add_out_jack_modes"); |
147 | if (val >= 0) | 151 | if (val >= 0) |
148 | spec->add_out_jack_modes = !!val; | 152 | spec->add_out_jack_modes = !!val; |
153 | val = snd_hda_get_bool_hint(codec, "add_in_jack_modes"); | ||
154 | if (val >= 0) | ||
155 | spec->add_in_jack_modes = !!val; | ||
149 | 156 | ||
150 | if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) | 157 | if (!snd_hda_get_int_hint(codec, "mixer_nid", &val)) |
151 | spec->mixer_nid = val; | 158 | spec->mixer_nid = val; |
@@ -818,19 +825,27 @@ static int add_stereo_sw(struct hda_codec *codec, const char *pfx, | |||
818 | return add_sw_ctl(codec, pfx, cidx, chs, path); | 825 | return add_sw_ctl(codec, pfx, cidx, chs, path); |
819 | } | 826 | } |
820 | 827 | ||
828 | /* any ctl assigned to the path with the given index? */ | ||
829 | static bool path_has_mixer(struct hda_codec *codec, int path_idx, int ctl_type) | ||
830 | { | ||
831 | struct nid_path *path = snd_hda_get_path_from_idx(codec, path_idx); | ||
832 | return path && path->ctls[ctl_type]; | ||
833 | } | ||
834 | |||
821 | static const char * const channel_name[4] = { | 835 | static const char * const channel_name[4] = { |
822 | "Front", "Surround", "CLFE", "Side" | 836 | "Front", "Surround", "CLFE", "Side" |
823 | }; | 837 | }; |
824 | 838 | ||
825 | /* give some appropriate ctl name prefix for the given line out channel */ | 839 | /* give some appropriate ctl name prefix for the given line out channel */ |
826 | static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch, | 840 | static const char *get_line_out_pfx(struct hda_codec *codec, int ch, |
827 | bool can_be_master, int *index) | 841 | int *index, int ctl_type) |
828 | { | 842 | { |
843 | struct hda_gen_spec *spec = codec->spec; | ||
829 | struct auto_pin_cfg *cfg = &spec->autocfg; | 844 | struct auto_pin_cfg *cfg = &spec->autocfg; |
830 | 845 | ||
831 | *index = 0; | 846 | *index = 0; |
832 | if (cfg->line_outs == 1 && !spec->multi_ios && | 847 | if (cfg->line_outs == 1 && !spec->multi_ios && |
833 | !cfg->hp_outs && !cfg->speaker_outs && can_be_master) | 848 | !cfg->hp_outs && !cfg->speaker_outs) |
834 | return spec->vmaster_mute.hook ? "PCM" : "Master"; | 849 | return spec->vmaster_mute.hook ? "PCM" : "Master"; |
835 | 850 | ||
836 | /* if there is really a single DAC used in the whole output paths, | 851 | /* if there is really a single DAC used in the whole output paths, |
@@ -840,24 +855,41 @@ static const char *get_line_out_pfx(struct hda_gen_spec *spec, int ch, | |||
840 | !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0]) | 855 | !spec->multiout.hp_out_nid[0] && !spec->multiout.extra_out_nid[0]) |
841 | return spec->vmaster_mute.hook ? "PCM" : "Master"; | 856 | return spec->vmaster_mute.hook ? "PCM" : "Master"; |
842 | 857 | ||
858 | /* multi-io channels */ | ||
859 | if (ch >= cfg->line_outs) | ||
860 | return channel_name[ch]; | ||
861 | |||
843 | switch (cfg->line_out_type) { | 862 | switch (cfg->line_out_type) { |
844 | case AUTO_PIN_SPEAKER_OUT: | 863 | case AUTO_PIN_SPEAKER_OUT: |
864 | /* if the primary channel vol/mute is shared with HP volume, | ||
865 | * don't name it as Speaker | ||
866 | */ | ||
867 | if (!ch && cfg->hp_outs && | ||
868 | !path_has_mixer(codec, spec->hp_paths[0], ctl_type)) | ||
869 | break; | ||
845 | if (cfg->line_outs == 1) | 870 | if (cfg->line_outs == 1) |
846 | return "Speaker"; | 871 | return "Speaker"; |
847 | if (cfg->line_outs == 2) | 872 | if (cfg->line_outs == 2) |
848 | return ch ? "Bass Speaker" : "Speaker"; | 873 | return ch ? "Bass Speaker" : "Speaker"; |
849 | break; | 874 | break; |
850 | case AUTO_PIN_HP_OUT: | 875 | case AUTO_PIN_HP_OUT: |
876 | /* if the primary channel vol/mute is shared with spk volume, | ||
877 | * don't name it as Headphone | ||
878 | */ | ||
879 | if (!ch && cfg->speaker_outs && | ||
880 | !path_has_mixer(codec, spec->speaker_paths[0], ctl_type)) | ||
881 | break; | ||
851 | /* for multi-io case, only the primary out */ | 882 | /* for multi-io case, only the primary out */ |
852 | if (ch && spec->multi_ios) | 883 | if (ch && spec->multi_ios) |
853 | break; | 884 | break; |
854 | *index = ch; | 885 | *index = ch; |
855 | return "Headphone"; | 886 | return "Headphone"; |
856 | default: | ||
857 | if (cfg->line_outs == 1 && !spec->multi_ios) | ||
858 | return "PCM"; | ||
859 | break; | ||
860 | } | 887 | } |
888 | |||
889 | /* for a single channel output, we don't have to name the channel */ | ||
890 | if (cfg->line_outs == 1 && !spec->multi_ios) | ||
891 | return "PCM"; | ||
892 | |||
861 | if (ch >= ARRAY_SIZE(channel_name)) { | 893 | if (ch >= ARRAY_SIZE(channel_name)) { |
862 | snd_BUG(); | 894 | snd_BUG(); |
863 | return "PCM"; | 895 | return "PCM"; |
@@ -1594,6 +1626,9 @@ static int parse_output_paths(struct hda_codec *codec) | |||
1594 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]); | 1626 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[0]); |
1595 | if (path) | 1627 | if (path) |
1596 | spec->vmaster_nid = look_for_out_vol_nid(codec, path); | 1628 | spec->vmaster_nid = look_for_out_vol_nid(codec, path); |
1629 | if (spec->vmaster_nid) | ||
1630 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
1631 | HDA_OUTPUT, spec->vmaster_tlv); | ||
1597 | } | 1632 | } |
1598 | 1633 | ||
1599 | kfree(best_cfg); | 1634 | kfree(best_cfg); |
@@ -1616,16 +1651,11 @@ static int create_multi_out_ctls(struct hda_codec *codec, | |||
1616 | int index; | 1651 | int index; |
1617 | struct nid_path *path; | 1652 | struct nid_path *path; |
1618 | 1653 | ||
1619 | if (i >= cfg->line_outs) { | ||
1620 | index = 0; | ||
1621 | name = channel_name[i]; | ||
1622 | } else { | ||
1623 | name = get_line_out_pfx(spec, i, true, &index); | ||
1624 | } | ||
1625 | |||
1626 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]); | 1654 | path = snd_hda_get_path_from_idx(codec, spec->out_paths[i]); |
1627 | if (!path) | 1655 | if (!path) |
1628 | continue; | 1656 | continue; |
1657 | |||
1658 | name = get_line_out_pfx(codec, i, &index, NID_PATH_VOL_CTL); | ||
1629 | if (!name || !strcmp(name, "CLFE")) { | 1659 | if (!name || !strcmp(name, "CLFE")) { |
1630 | /* Center/LFE */ | 1660 | /* Center/LFE */ |
1631 | err = add_vol_ctl(codec, "Center", 0, 1, path); | 1661 | err = add_vol_ctl(codec, "Center", 0, 1, path); |
@@ -1634,6 +1664,14 @@ static int create_multi_out_ctls(struct hda_codec *codec, | |||
1634 | err = add_vol_ctl(codec, "LFE", 0, 2, path); | 1664 | err = add_vol_ctl(codec, "LFE", 0, 2, path); |
1635 | if (err < 0) | 1665 | if (err < 0) |
1636 | return err; | 1666 | return err; |
1667 | } else { | ||
1668 | err = add_stereo_vol(codec, name, index, path); | ||
1669 | if (err < 0) | ||
1670 | return err; | ||
1671 | } | ||
1672 | |||
1673 | name = get_line_out_pfx(codec, i, &index, NID_PATH_MUTE_CTL); | ||
1674 | if (!name || !strcmp(name, "CLFE")) { | ||
1637 | err = add_sw_ctl(codec, "Center", 0, 1, path); | 1675 | err = add_sw_ctl(codec, "Center", 0, 1, path); |
1638 | if (err < 0) | 1676 | if (err < 0) |
1639 | return err; | 1677 | return err; |
@@ -1641,9 +1679,6 @@ static int create_multi_out_ctls(struct hda_codec *codec, | |||
1641 | if (err < 0) | 1679 | if (err < 0) |
1642 | return err; | 1680 | return err; |
1643 | } else { | 1681 | } else { |
1644 | err = add_stereo_vol(codec, name, index, path); | ||
1645 | if (err < 0) | ||
1646 | return err; | ||
1647 | err = add_stereo_sw(codec, name, index, path); | 1682 | err = add_stereo_sw(codec, name, index, path); |
1648 | if (err < 0) | 1683 | if (err < 0) |
1649 | return err; | 1684 | return err; |
@@ -1826,6 +1861,8 @@ get_multiio_path(struct hda_codec *codec, int idx) | |||
1826 | spec->out_paths[spec->autocfg.line_outs + idx]); | 1861 | spec->out_paths[spec->autocfg.line_outs + idx]); |
1827 | } | 1862 | } |
1828 | 1863 | ||
1864 | static void update_automute_all(struct hda_codec *codec); | ||
1865 | |||
1829 | static int set_multi_io(struct hda_codec *codec, int idx, bool output) | 1866 | static int set_multi_io(struct hda_codec *codec, int idx, bool output) |
1830 | { | 1867 | { |
1831 | struct hda_gen_spec *spec = codec->spec; | 1868 | struct hda_gen_spec *spec = codec->spec; |
@@ -1850,9 +1887,7 @@ static int set_multi_io(struct hda_codec *codec, int idx, bool output) | |||
1850 | } | 1887 | } |
1851 | 1888 | ||
1852 | /* update jack retasking in case it modifies any of them */ | 1889 | /* update jack retasking in case it modifies any of them */ |
1853 | snd_hda_gen_hp_automute(codec, NULL); | 1890 | update_automute_all(codec); |
1854 | snd_hda_gen_line_automute(codec, NULL); | ||
1855 | snd_hda_gen_mic_autoswitch(codec, NULL); | ||
1856 | 1891 | ||
1857 | return 0; | 1892 | return 0; |
1858 | } | 1893 | } |
@@ -2135,6 +2170,136 @@ static int create_out_jack_modes(struct hda_codec *codec, int num_pins, | |||
2135 | return 0; | 2170 | return 0; |
2136 | } | 2171 | } |
2137 | 2172 | ||
2173 | /* | ||
2174 | * input jack mode | ||
2175 | */ | ||
2176 | |||
2177 | /* from AC_PINCTL_VREF_HIZ to AC_PINCTL_VREF_100 */ | ||
2178 | #define NUM_VREFS 6 | ||
2179 | |||
2180 | static const char * const vref_texts[NUM_VREFS] = { | ||
2181 | "Line In", "Mic 50pc Bias", "Mic 0V Bias", | ||
2182 | "", "Mic 80pc Bias", "Mic 100pc Bias" | ||
2183 | }; | ||
2184 | |||
2185 | static unsigned int get_vref_caps(struct hda_codec *codec, hda_nid_t pin) | ||
2186 | { | ||
2187 | unsigned int pincap; | ||
2188 | |||
2189 | pincap = snd_hda_query_pin_caps(codec, pin); | ||
2190 | pincap = (pincap & AC_PINCAP_VREF) >> AC_PINCAP_VREF_SHIFT; | ||
2191 | /* filter out unusual vrefs */ | ||
2192 | pincap &= ~(AC_PINCAP_VREF_GRD | AC_PINCAP_VREF_100); | ||
2193 | return pincap; | ||
2194 | } | ||
2195 | |||
2196 | /* convert from the enum item index to the vref ctl index (0=HIZ, 1=50%...) */ | ||
2197 | static int get_vref_idx(unsigned int vref_caps, unsigned int item_idx) | ||
2198 | { | ||
2199 | unsigned int i, n = 0; | ||
2200 | |||
2201 | for (i = 0; i < NUM_VREFS; i++) { | ||
2202 | if (vref_caps & (1 << i)) { | ||
2203 | if (n == item_idx) | ||
2204 | return i; | ||
2205 | n++; | ||
2206 | } | ||
2207 | } | ||
2208 | return 0; | ||
2209 | } | ||
2210 | |||
2211 | /* convert back from the vref ctl index to the enum item index */ | ||
2212 | static int cvt_from_vref_idx(unsigned int vref_caps, unsigned int idx) | ||
2213 | { | ||
2214 | unsigned int i, n = 0; | ||
2215 | |||
2216 | for (i = 0; i < NUM_VREFS; i++) { | ||
2217 | if (i == idx) | ||
2218 | return n; | ||
2219 | if (vref_caps & (1 << i)) | ||
2220 | n++; | ||
2221 | } | ||
2222 | return 0; | ||
2223 | } | ||
2224 | |||
2225 | static int in_jack_mode_info(struct snd_kcontrol *kcontrol, | ||
2226 | struct snd_ctl_elem_info *uinfo) | ||
2227 | { | ||
2228 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2229 | hda_nid_t nid = kcontrol->private_value; | ||
2230 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2231 | |||
2232 | snd_hda_enum_helper_info(kcontrol, uinfo, hweight32(vref_caps), | ||
2233 | vref_texts); | ||
2234 | /* set the right text */ | ||
2235 | strcpy(uinfo->value.enumerated.name, | ||
2236 | vref_texts[get_vref_idx(vref_caps, uinfo->value.enumerated.item)]); | ||
2237 | return 0; | ||
2238 | } | ||
2239 | |||
2240 | static int in_jack_mode_get(struct snd_kcontrol *kcontrol, | ||
2241 | struct snd_ctl_elem_value *ucontrol) | ||
2242 | { | ||
2243 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2244 | hda_nid_t nid = kcontrol->private_value; | ||
2245 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2246 | unsigned int idx; | ||
2247 | |||
2248 | idx = snd_hda_codec_get_pin_target(codec, nid) & AC_PINCTL_VREFEN; | ||
2249 | ucontrol->value.enumerated.item[0] = cvt_from_vref_idx(vref_caps, idx); | ||
2250 | return 0; | ||
2251 | } | ||
2252 | |||
2253 | static int in_jack_mode_put(struct snd_kcontrol *kcontrol, | ||
2254 | struct snd_ctl_elem_value *ucontrol) | ||
2255 | { | ||
2256 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2257 | hda_nid_t nid = kcontrol->private_value; | ||
2258 | unsigned int vref_caps = get_vref_caps(codec, nid); | ||
2259 | unsigned int val, idx; | ||
2260 | |||
2261 | val = snd_hda_codec_get_pin_target(codec, nid); | ||
2262 | idx = cvt_from_vref_idx(vref_caps, val & AC_PINCTL_VREFEN); | ||
2263 | if (idx == ucontrol->value.enumerated.item[0]) | ||
2264 | return 0; | ||
2265 | |||
2266 | val &= ~AC_PINCTL_VREFEN; | ||
2267 | val |= get_vref_idx(vref_caps, ucontrol->value.enumerated.item[0]); | ||
2268 | snd_hda_set_pin_ctl_cache(codec, nid, val); | ||
2269 | return 1; | ||
2270 | } | ||
2271 | |||
2272 | static const struct snd_kcontrol_new in_jack_mode_enum = { | ||
2273 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | ||
2274 | .info = in_jack_mode_info, | ||
2275 | .get = in_jack_mode_get, | ||
2276 | .put = in_jack_mode_put, | ||
2277 | }; | ||
2278 | |||
2279 | static int create_in_jack_mode(struct hda_codec *codec, hda_nid_t pin) | ||
2280 | { | ||
2281 | struct hda_gen_spec *spec = codec->spec; | ||
2282 | unsigned int defcfg; | ||
2283 | struct snd_kcontrol_new *knew; | ||
2284 | char name[44]; | ||
2285 | |||
2286 | /* no jack mode for fixed pins */ | ||
2287 | defcfg = snd_hda_codec_get_pincfg(codec, pin); | ||
2288 | if (snd_hda_get_input_pin_attr(defcfg) == INPUT_PIN_ATTR_INT) | ||
2289 | return 0; | ||
2290 | |||
2291 | /* no multiple vref caps? */ | ||
2292 | if (hweight32(get_vref_caps(codec, pin)) <= 1) | ||
2293 | return 0; | ||
2294 | |||
2295 | get_jack_mode_name(codec, pin, name, sizeof(name)); | ||
2296 | knew = snd_hda_gen_add_kctl(spec, name, &in_jack_mode_enum); | ||
2297 | if (!knew) | ||
2298 | return -ENOMEM; | ||
2299 | knew->private_value = pin; | ||
2300 | return 0; | ||
2301 | } | ||
2302 | |||
2138 | 2303 | ||
2139 | /* | 2304 | /* |
2140 | * Parse input paths | 2305 | * Parse input paths |
@@ -2228,6 +2393,11 @@ static int fill_adc_nids(struct hda_codec *codec) | |||
2228 | break; | 2393 | break; |
2229 | } | 2394 | } |
2230 | spec->num_adc_nids = nums; | 2395 | spec->num_adc_nids = nums; |
2396 | |||
2397 | /* copy the detected ADCs to all_adcs[] */ | ||
2398 | spec->num_all_adcs = nums; | ||
2399 | memcpy(spec->all_adcs, spec->adc_nids, nums * sizeof(hda_nid_t)); | ||
2400 | |||
2231 | return nums; | 2401 | return nums; |
2232 | } | 2402 | } |
2233 | 2403 | ||
@@ -2389,6 +2559,12 @@ static int create_input_ctls(struct hda_codec *codec) | |||
2389 | err = parse_capture_source(codec, pin, num_adcs, label, -mixer); | 2559 | err = parse_capture_source(codec, pin, num_adcs, label, -mixer); |
2390 | if (err < 0) | 2560 | if (err < 0) |
2391 | return err; | 2561 | return err; |
2562 | |||
2563 | if (spec->add_in_jack_modes) { | ||
2564 | err = create_in_jack_mode(codec, pin); | ||
2565 | if (err < 0) | ||
2566 | return err; | ||
2567 | } | ||
2392 | } | 2568 | } |
2393 | 2569 | ||
2394 | if (mixer && spec->add_stereo_mix_input) { | 2570 | if (mixer && spec->add_stereo_mix_input) { |
@@ -3047,6 +3223,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec) | |||
3047 | else | 3223 | else |
3048 | on = spec->hp_jack_present | spec->line_jack_present; | 3224 | on = spec->hp_jack_present | spec->line_jack_present; |
3049 | on |= spec->master_mute; | 3225 | on |= spec->master_mute; |
3226 | spec->speaker_muted = on; | ||
3050 | do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins), | 3227 | do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins), |
3051 | spec->autocfg.speaker_pins, on); | 3228 | spec->autocfg.speaker_pins, on); |
3052 | 3229 | ||
@@ -3060,6 +3237,7 @@ void snd_hda_gen_update_outputs(struct hda_codec *codec) | |||
3060 | else | 3237 | else |
3061 | on = spec->hp_jack_present; | 3238 | on = spec->hp_jack_present; |
3062 | on |= spec->master_mute; | 3239 | on |= spec->master_mute; |
3240 | spec->line_out_muted = on; | ||
3063 | do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), | 3241 | do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins), |
3064 | spec->autocfg.line_out_pins, on); | 3242 | spec->autocfg.line_out_pins, on); |
3065 | } | 3243 | } |
@@ -3131,6 +3309,25 @@ void snd_hda_gen_mic_autoswitch(struct hda_codec *codec, struct hda_jack_tbl *ja | |||
3131 | } | 3309 | } |
3132 | EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch); | 3310 | EXPORT_SYMBOL_HDA(snd_hda_gen_mic_autoswitch); |
3133 | 3311 | ||
3312 | /* update jack retasking */ | ||
3313 | static void update_automute_all(struct hda_codec *codec) | ||
3314 | { | ||
3315 | struct hda_gen_spec *spec = codec->spec; | ||
3316 | |||
3317 | if (spec->hp_automute_hook) | ||
3318 | spec->hp_automute_hook(codec, NULL); | ||
3319 | else | ||
3320 | snd_hda_gen_hp_automute(codec, NULL); | ||
3321 | if (spec->line_automute_hook) | ||
3322 | spec->line_automute_hook(codec, NULL); | ||
3323 | else | ||
3324 | snd_hda_gen_line_automute(codec, NULL); | ||
3325 | if (spec->mic_autoswitch_hook) | ||
3326 | spec->mic_autoswitch_hook(codec, NULL); | ||
3327 | else | ||
3328 | snd_hda_gen_mic_autoswitch(codec, NULL); | ||
3329 | } | ||
3330 | |||
3134 | /* | 3331 | /* |
3135 | * Auto-Mute mode mixer enum support | 3332 | * Auto-Mute mode mixer enum support |
3136 | */ | 3333 | */ |
@@ -3232,6 +3429,9 @@ static int check_auto_mute_availability(struct hda_codec *codec) | |||
3232 | int present = 0; | 3429 | int present = 0; |
3233 | int i, err; | 3430 | int i, err; |
3234 | 3431 | ||
3432 | if (spec->suppress_auto_mute) | ||
3433 | return 0; | ||
3434 | |||
3235 | if (cfg->hp_pins[0]) | 3435 | if (cfg->hp_pins[0]) |
3236 | present++; | 3436 | present++; |
3237 | if (cfg->line_out_pins[0]) | 3437 | if (cfg->line_out_pins[0]) |
@@ -3585,11 +3785,8 @@ int snd_hda_gen_build_controls(struct hda_codec *codec) | |||
3585 | /* if we have no master control, let's create it */ | 3785 | /* if we have no master control, let's create it */ |
3586 | if (!spec->no_analog && | 3786 | if (!spec->no_analog && |
3587 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { | 3787 | !snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) { |
3588 | unsigned int vmaster_tlv[4]; | ||
3589 | snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid, | ||
3590 | HDA_OUTPUT, vmaster_tlv); | ||
3591 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 3788 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
3592 | vmaster_tlv, slave_pfxs, | 3789 | spec->vmaster_tlv, slave_pfxs, |
3593 | "Playback Volume"); | 3790 | "Playback Volume"); |
3594 | if (err < 0) | 3791 | if (err < 0) |
3595 | return err; | 3792 | return err; |
@@ -3643,6 +3840,16 @@ static void call_pcm_playback_hook(struct hda_pcm_stream *hinfo, | |||
3643 | spec->pcm_playback_hook(hinfo, codec, substream, action); | 3840 | spec->pcm_playback_hook(hinfo, codec, substream, action); |
3644 | } | 3841 | } |
3645 | 3842 | ||
3843 | static void call_pcm_capture_hook(struct hda_pcm_stream *hinfo, | ||
3844 | struct hda_codec *codec, | ||
3845 | struct snd_pcm_substream *substream, | ||
3846 | int action) | ||
3847 | { | ||
3848 | struct hda_gen_spec *spec = codec->spec; | ||
3849 | if (spec->pcm_capture_hook) | ||
3850 | spec->pcm_capture_hook(hinfo, codec, substream, action); | ||
3851 | } | ||
3852 | |||
3646 | /* | 3853 | /* |
3647 | * Analog playback callbacks | 3854 | * Analog playback callbacks |
3648 | */ | 3855 | */ |
@@ -3710,6 +3917,44 @@ static int playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
3710 | return 0; | 3917 | return 0; |
3711 | } | 3918 | } |
3712 | 3919 | ||
3920 | static int capture_pcm_open(struct hda_pcm_stream *hinfo, | ||
3921 | struct hda_codec *codec, | ||
3922 | struct snd_pcm_substream *substream) | ||
3923 | { | ||
3924 | call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_OPEN); | ||
3925 | return 0; | ||
3926 | } | ||
3927 | |||
3928 | static int capture_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
3929 | struct hda_codec *codec, | ||
3930 | unsigned int stream_tag, | ||
3931 | unsigned int format, | ||
3932 | struct snd_pcm_substream *substream) | ||
3933 | { | ||
3934 | snd_hda_codec_setup_stream(codec, hinfo->nid, stream_tag, 0, format); | ||
3935 | call_pcm_capture_hook(hinfo, codec, substream, | ||
3936 | HDA_GEN_PCM_ACT_PREPARE); | ||
3937 | return 0; | ||
3938 | } | ||
3939 | |||
3940 | static int capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | ||
3941 | struct hda_codec *codec, | ||
3942 | struct snd_pcm_substream *substream) | ||
3943 | { | ||
3944 | snd_hda_codec_cleanup_stream(codec, hinfo->nid); | ||
3945 | call_pcm_capture_hook(hinfo, codec, substream, | ||
3946 | HDA_GEN_PCM_ACT_CLEANUP); | ||
3947 | return 0; | ||
3948 | } | ||
3949 | |||
3950 | static int capture_pcm_close(struct hda_pcm_stream *hinfo, | ||
3951 | struct hda_codec *codec, | ||
3952 | struct snd_pcm_substream *substream) | ||
3953 | { | ||
3954 | call_pcm_capture_hook(hinfo, codec, substream, HDA_GEN_PCM_ACT_CLOSE); | ||
3955 | return 0; | ||
3956 | } | ||
3957 | |||
3713 | static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo, | 3958 | static int alt_playback_pcm_open(struct hda_pcm_stream *hinfo, |
3714 | struct hda_codec *codec, | 3959 | struct hda_codec *codec, |
3715 | struct snd_pcm_substream *substream) | 3960 | struct snd_pcm_substream *substream) |
@@ -3804,6 +4049,9 @@ static int dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | |||
3804 | /* | 4049 | /* |
3805 | * Analog capture | 4050 | * Analog capture |
3806 | */ | 4051 | */ |
4052 | #define alt_capture_pcm_open capture_pcm_open | ||
4053 | #define alt_capture_pcm_close capture_pcm_close | ||
4054 | |||
3807 | static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 4055 | static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo, |
3808 | struct hda_codec *codec, | 4056 | struct hda_codec *codec, |
3809 | unsigned int stream_tag, | 4057 | unsigned int stream_tag, |
@@ -3814,6 +4062,8 @@ static int alt_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
3814 | 4062 | ||
3815 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1], | 4063 | snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number + 1], |
3816 | stream_tag, 0, format); | 4064 | stream_tag, 0, format); |
4065 | call_pcm_capture_hook(hinfo, codec, substream, | ||
4066 | HDA_GEN_PCM_ACT_PREPARE); | ||
3817 | return 0; | 4067 | return 0; |
3818 | } | 4068 | } |
3819 | 4069 | ||
@@ -3825,6 +4075,8 @@ static int alt_capture_pcm_cleanup(struct hda_pcm_stream *hinfo, | |||
3825 | 4075 | ||
3826 | snd_hda_codec_cleanup_stream(codec, | 4076 | snd_hda_codec_cleanup_stream(codec, |
3827 | spec->adc_nids[substream->number + 1]); | 4077 | spec->adc_nids[substream->number + 1]); |
4078 | call_pcm_capture_hook(hinfo, codec, substream, | ||
4079 | HDA_GEN_PCM_ACT_CLEANUP); | ||
3828 | return 0; | 4080 | return 0; |
3829 | } | 4081 | } |
3830 | 4082 | ||
@@ -3848,6 +4100,12 @@ static const struct hda_pcm_stream pcm_analog_capture = { | |||
3848 | .channels_min = 2, | 4100 | .channels_min = 2, |
3849 | .channels_max = 2, | 4101 | .channels_max = 2, |
3850 | /* NID is set in build_pcms */ | 4102 | /* NID is set in build_pcms */ |
4103 | .ops = { | ||
4104 | .open = capture_pcm_open, | ||
4105 | .close = capture_pcm_close, | ||
4106 | .prepare = capture_pcm_prepare, | ||
4107 | .cleanup = capture_pcm_cleanup | ||
4108 | }, | ||
3851 | }; | 4109 | }; |
3852 | 4110 | ||
3853 | static const struct hda_pcm_stream pcm_analog_alt_playback = { | 4111 | static const struct hda_pcm_stream pcm_analog_alt_playback = { |
@@ -3869,6 +4127,8 @@ static const struct hda_pcm_stream pcm_analog_alt_capture = { | |||
3869 | .channels_max = 2, | 4127 | .channels_max = 2, |
3870 | /* NID is set in build_pcms */ | 4128 | /* NID is set in build_pcms */ |
3871 | .ops = { | 4129 | .ops = { |
4130 | .open = alt_capture_pcm_open, | ||
4131 | .close = alt_capture_pcm_close, | ||
3872 | .prepare = alt_capture_pcm_prepare, | 4132 | .prepare = alt_capture_pcm_prepare, |
3873 | .cleanup = alt_capture_pcm_cleanup | 4133 | .cleanup = alt_capture_pcm_cleanup |
3874 | }, | 4134 | }, |
@@ -4281,9 +4541,7 @@ int snd_hda_gen_init(struct hda_codec *codec) | |||
4281 | clear_unsol_on_unused_pins(codec); | 4541 | clear_unsol_on_unused_pins(codec); |
4282 | 4542 | ||
4283 | /* call init functions of standard auto-mute helpers */ | 4543 | /* call init functions of standard auto-mute helpers */ |
4284 | snd_hda_gen_hp_automute(codec, NULL); | 4544 | update_automute_all(codec); |
4285 | snd_hda_gen_line_automute(codec, NULL); | ||
4286 | snd_hda_gen_mic_autoswitch(codec, NULL); | ||
4287 | 4545 | ||
4288 | snd_hda_codec_flush_amp_cache(codec); | 4546 | snd_hda_codec_flush_amp_cache(codec); |
4289 | snd_hda_codec_flush_cmd_cache(codec); | 4547 | snd_hda_codec_flush_cmd_cache(codec); |
diff --git a/sound/pci/hda/hda_generic.h b/sound/pci/hda/hda_generic.h index 6ba580540081..7b14e9ce7486 100644 --- a/sound/pci/hda/hda_generic.h +++ b/sound/pci/hda/hda_generic.h | |||
@@ -142,9 +142,11 @@ struct hda_gen_spec { | |||
142 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; | 142 | unsigned int dyn_adc_idx[HDA_MAX_NUM_INPUTS]; |
143 | hda_nid_t shared_mic_vref_pin; | 143 | hda_nid_t shared_mic_vref_pin; |
144 | 144 | ||
145 | /* DAC list */ | 145 | /* DAC/ADC lists */ |
146 | int num_all_dacs; | 146 | int num_all_dacs; |
147 | hda_nid_t all_dacs[16]; | 147 | hda_nid_t all_dacs[16]; |
148 | int num_all_adcs; | ||
149 | hda_nid_t all_adcs[AUTO_CFG_MAX_OUTS]; | ||
148 | 150 | ||
149 | /* path list */ | 151 | /* path list */ |
150 | struct snd_array paths; | 152 | struct snd_array paths; |
@@ -164,24 +166,34 @@ struct hda_gen_spec { | |||
164 | struct automic_entry am_entry[MAX_AUTO_MIC_PINS]; | 166 | struct automic_entry am_entry[MAX_AUTO_MIC_PINS]; |
165 | 167 | ||
166 | /* for pin sensing */ | 168 | /* for pin sensing */ |
169 | /* current status; set in hda_geneic.c */ | ||
167 | unsigned int hp_jack_present:1; | 170 | unsigned int hp_jack_present:1; |
168 | unsigned int line_jack_present:1; | 171 | unsigned int line_jack_present:1; |
169 | unsigned int master_mute:1; | 172 | unsigned int speaker_muted:1; /* current status of speaker mute */ |
173 | unsigned int line_out_muted:1; /* current status of LO mute */ | ||
174 | |||
175 | /* internal states of automute / autoswitch behavior */ | ||
170 | unsigned int auto_mic:1; | 176 | unsigned int auto_mic:1; |
171 | unsigned int automute_speaker:1; /* automute speaker outputs */ | 177 | unsigned int automute_speaker:1; /* automute speaker outputs */ |
172 | unsigned int automute_lo:1; /* automute LO outputs */ | 178 | unsigned int automute_lo:1; /* automute LO outputs */ |
179 | |||
180 | /* capabilities detected by parser */ | ||
173 | unsigned int detect_hp:1; /* Headphone detection enabled */ | 181 | unsigned int detect_hp:1; /* Headphone detection enabled */ |
174 | unsigned int detect_lo:1; /* Line-out detection enabled */ | 182 | unsigned int detect_lo:1; /* Line-out detection enabled */ |
175 | unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ | 183 | unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */ |
176 | unsigned int automute_lo_possible:1; /* there are line outs and HP */ | 184 | unsigned int automute_lo_possible:1; /* there are line outs and HP */ |
185 | |||
186 | /* additional parameters set by codec drivers */ | ||
187 | unsigned int master_mute:1; /* master mute over all */ | ||
177 | unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ | 188 | unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */ |
178 | unsigned int suppress_auto_mic:1; /* suppress input jack auto switch */ | ||
179 | unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ | 189 | unsigned int line_in_auto_switch:1; /* allow line-in auto switch */ |
180 | 190 | ||
181 | /* other flags */ | 191 | /* parser behavior flags; set before snd_hda_gen_parse_auto_config() */ |
192 | unsigned int suppress_auto_mute:1; /* suppress input jack auto mute */ | ||
193 | unsigned int suppress_auto_mic:1; /* suppress input jack auto switch */ | ||
194 | |||
195 | /* other parse behavior flags */ | ||
182 | unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ | 196 | unsigned int need_dac_fix:1; /* need to limit DACs for multi channels */ |
183 | unsigned int no_analog:1; /* digital I/O only */ | ||
184 | unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ | ||
185 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ | 197 | unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ |
186 | unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ | 198 | unsigned int no_primary_hp:1; /* Don't prefer HP pins to speaker pins */ |
187 | unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ | 199 | unsigned int multi_cap_vol:1; /* allow multiple capture xxx volumes */ |
@@ -189,16 +201,22 @@ struct hda_gen_spec { | |||
189 | unsigned int own_eapd_ctl:1; /* set EAPD by own function */ | 201 | unsigned int own_eapd_ctl:1; /* set EAPD by own function */ |
190 | unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */ | 202 | unsigned int vmaster_mute_enum:1; /* add vmaster mute mode enum */ |
191 | unsigned int indep_hp:1; /* independent HP supported */ | 203 | unsigned int indep_hp:1; /* independent HP supported */ |
192 | unsigned int indep_hp_enabled:1; /* independent HP enabled */ | ||
193 | unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */ | 204 | unsigned int prefer_hp_amp:1; /* enable HP amp for speaker if any */ |
194 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ | 205 | unsigned int add_stereo_mix_input:1; /* add aamix as a capture src */ |
195 | unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */ | 206 | unsigned int add_out_jack_modes:1; /* add output jack mode enum ctls */ |
207 | unsigned int add_in_jack_modes:1; /* add input jack mode enum ctls */ | ||
208 | |||
209 | /* other internal flags */ | ||
210 | unsigned int no_analog:1; /* digital I/O only */ | ||
211 | unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */ | ||
212 | unsigned int indep_hp_enabled:1; /* independent HP enabled */ | ||
196 | 213 | ||
197 | /* loopback mixing mode */ | 214 | /* loopback mixing mode */ |
198 | bool aamix_mode; | 215 | bool aamix_mode; |
199 | 216 | ||
200 | /* for virtual master */ | 217 | /* for virtual master */ |
201 | hda_nid_t vmaster_nid; | 218 | hda_nid_t vmaster_nid; |
219 | unsigned int vmaster_tlv[4]; | ||
202 | struct hda_vmaster_mute_hook vmaster_mute; | 220 | struct hda_vmaster_mute_hook vmaster_mute; |
203 | #ifdef CONFIG_PM | 221 | #ifdef CONFIG_PM |
204 | struct hda_loopback_check loopback; | 222 | struct hda_loopback_check loopback; |
@@ -215,11 +233,15 @@ struct hda_gen_spec { | |||
215 | void (*automute_hook)(struct hda_codec *codec); | 233 | void (*automute_hook)(struct hda_codec *codec); |
216 | void (*cap_sync_hook)(struct hda_codec *codec); | 234 | void (*cap_sync_hook)(struct hda_codec *codec); |
217 | 235 | ||
218 | /* PCM playback hook */ | 236 | /* PCM hooks */ |
219 | void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo, | 237 | void (*pcm_playback_hook)(struct hda_pcm_stream *hinfo, |
220 | struct hda_codec *codec, | 238 | struct hda_codec *codec, |
221 | struct snd_pcm_substream *substream, | 239 | struct snd_pcm_substream *substream, |
222 | int action); | 240 | int action); |
241 | void (*pcm_capture_hook)(struct hda_pcm_stream *hinfo, | ||
242 | struct hda_codec *codec, | ||
243 | struct snd_pcm_substream *substream, | ||
244 | int action); | ||
223 | 245 | ||
224 | /* automute / autoswitch hooks */ | 246 | /* automute / autoswitch hooks */ |
225 | void (*hp_automute_hook)(struct hda_codec *codec, | 247 | void (*hp_automute_hook)(struct hda_codec *codec, |