diff options
Diffstat (limited to 'sound/pci/hda')
-rw-r--r-- | sound/pci/hda/Makefile | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 40 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 3 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.c | 148 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 63 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 15 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 1 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 18 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 20 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 46 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 19 |
13 files changed, 284 insertions, 117 deletions
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index f928d6634723..ace157cc3d15 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
@@ -1,6 +1,6 @@ | |||
1 | snd-hda-intel-objs := hda_intel.o | 1 | snd-hda-intel-objs := hda_intel.o |
2 | 2 | ||
3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o hda_jack.o |
4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
6 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index c6ff9b9de553..8217ff7ff7b5 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <sound/jack.h> | 33 | #include <sound/jack.h> |
34 | #include "hda_local.h" | 34 | #include "hda_local.h" |
35 | #include "hda_beep.h" | 35 | #include "hda_beep.h" |
36 | #include "hda_jack.h" | ||
36 | #include <sound/hda_hwdep.h> | 37 | #include <sound/hda_hwdep.h> |
37 | 38 | ||
38 | #define CREATE_TRACE_POINTS | 39 | #define CREATE_TRACE_POINTS |
@@ -1723,43 +1724,6 @@ int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | |||
1723 | } | 1724 | } |
1724 | EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps); | 1725 | EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps); |
1725 | 1726 | ||
1726 | /** | ||
1727 | * snd_hda_pin_sense - execute pin sense measurement | ||
1728 | * @codec: the CODEC to sense | ||
1729 | * @nid: the pin NID to sense | ||
1730 | * | ||
1731 | * Execute necessary pin sense measurement and return its Presence Detect, | ||
1732 | * Impedance, ELD Valid etc. status bits. | ||
1733 | */ | ||
1734 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) | ||
1735 | { | ||
1736 | u32 pincap; | ||
1737 | |||
1738 | if (!codec->no_trigger_sense) { | ||
1739 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
1740 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ | ||
1741 | snd_hda_codec_read(codec, nid, 0, | ||
1742 | AC_VERB_SET_PIN_SENSE, 0); | ||
1743 | } | ||
1744 | return snd_hda_codec_read(codec, nid, 0, | ||
1745 | AC_VERB_GET_PIN_SENSE, 0); | ||
1746 | } | ||
1747 | EXPORT_SYMBOL_HDA(snd_hda_pin_sense); | ||
1748 | |||
1749 | /** | ||
1750 | * snd_hda_jack_detect - query pin Presence Detect status | ||
1751 | * @codec: the CODEC to sense | ||
1752 | * @nid: the pin NID to sense | ||
1753 | * | ||
1754 | * Query and return the pin's Presence Detect status. | ||
1755 | */ | ||
1756 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | ||
1757 | { | ||
1758 | u32 sense = snd_hda_pin_sense(codec, nid); | ||
1759 | return !!(sense & AC_PINSENSE_PRESENCE); | ||
1760 | } | ||
1761 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | ||
1762 | |||
1763 | /* | 1727 | /* |
1764 | * read the current volume to info | 1728 | * read the current volume to info |
1765 | * if the cache exists, read the cache value. | 1729 | * if the cache exists, read the cache value. |
@@ -2308,6 +2272,7 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2308 | } | 2272 | } |
2309 | if (codec->patch_ops.free) | 2273 | if (codec->patch_ops.free) |
2310 | codec->patch_ops.free(codec); | 2274 | codec->patch_ops.free(codec); |
2275 | snd_hda_jack_tbl_clear(codec); | ||
2311 | codec->proc_widget_hook = NULL; | 2276 | codec->proc_widget_hook = NULL; |
2312 | codec->spec = NULL; | 2277 | codec->spec = NULL; |
2313 | free_hda_cache(&codec->amp_cache); | 2278 | free_hda_cache(&codec->amp_cache); |
@@ -3364,6 +3329,7 @@ static void hda_call_codec_resume(struct hda_codec *codec) | |||
3364 | restore_pincfgs(codec); /* restore all current pin configs */ | 3329 | restore_pincfgs(codec); /* restore all current pin configs */ |
3365 | restore_shutup_pins(codec); | 3330 | restore_shutup_pins(codec); |
3366 | hda_exec_init_verbs(codec); | 3331 | hda_exec_init_verbs(codec); |
3332 | snd_hda_jack_set_dirty_all(codec); | ||
3367 | if (codec->patch_ops.resume) | 3333 | if (codec->patch_ops.resume) |
3368 | codec->patch_ops.resume(codec); | 3334 | codec->patch_ops.resume(codec); |
3369 | else { | 3335 | else { |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 564471169cae..97aa65d1f1d1 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -869,6 +869,9 @@ struct hda_codec { | |||
869 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, | 869 | void (*proc_widget_hook)(struct snd_info_buffer *buffer, |
870 | struct hda_codec *codec, hda_nid_t nid); | 870 | struct hda_codec *codec, hda_nid_t nid); |
871 | 871 | ||
872 | /* jack detection */ | ||
873 | struct snd_array jacktbl; | ||
874 | |||
872 | #ifdef CONFIG_SND_HDA_INPUT_JACK | 875 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
873 | /* jack detection */ | 876 | /* jack detection */ |
874 | struct snd_array jacks; | 877 | struct snd_array jacks; |
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c new file mode 100644 index 000000000000..64b78a2e20e0 --- /dev/null +++ b/sound/pci/hda/hda_jack.c | |||
@@ -0,0 +1,148 @@ | |||
1 | /* | ||
2 | * Jack-detection handling for HD-audio | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
6 | * This driver is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <sound/core.h> | ||
15 | #include "hda_codec.h" | ||
16 | #include "hda_local.h" | ||
17 | #include "hda_jack.h" | ||
18 | |||
19 | /* execute pin sense measurement */ | ||
20 | static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid) | ||
21 | { | ||
22 | u32 pincap; | ||
23 | |||
24 | if (!codec->no_trigger_sense) { | ||
25 | pincap = snd_hda_query_pin_caps(codec, nid); | ||
26 | if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */ | ||
27 | snd_hda_codec_read(codec, nid, 0, | ||
28 | AC_VERB_SET_PIN_SENSE, 0); | ||
29 | } | ||
30 | return snd_hda_codec_read(codec, nid, 0, | ||
31 | AC_VERB_GET_PIN_SENSE, 0); | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * snd_hda_jack_tbl_get - query the jack-table entry for the given NID | ||
36 | */ | ||
37 | struct hda_jack_tbl * | ||
38 | snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) | ||
39 | { | ||
40 | struct hda_jack_tbl *jack = codec->jacktbl.list; | ||
41 | int i; | ||
42 | |||
43 | if (!nid || !jack) | ||
44 | return NULL; | ||
45 | for (i = 0; i < codec->jacktbl.used; i++, jack++) | ||
46 | if (jack->nid == nid) | ||
47 | return jack; | ||
48 | return NULL; | ||
49 | } | ||
50 | EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); | ||
51 | |||
52 | /** | ||
53 | * snd_hda_jack_tbl_new - create a jack-table entry for the given NID | ||
54 | */ | ||
55 | struct hda_jack_tbl * | ||
56 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid) | ||
57 | { | ||
58 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); | ||
59 | if (jack) | ||
60 | return jack; | ||
61 | snd_array_init(&codec->jacktbl, sizeof(*jack), 16); | ||
62 | jack = snd_array_new(&codec->jacktbl); | ||
63 | if (!jack) | ||
64 | return NULL; | ||
65 | jack->nid = nid; | ||
66 | jack->jack_dirty = 1; | ||
67 | return jack; | ||
68 | } | ||
69 | |||
70 | void snd_hda_jack_tbl_clear(struct hda_codec *codec) | ||
71 | { | ||
72 | snd_array_free(&codec->jacktbl); | ||
73 | } | ||
74 | |||
75 | /* update the cached value and notification flag if needed */ | ||
76 | static void jack_detect_update(struct hda_codec *codec, | ||
77 | struct hda_jack_tbl *jack) | ||
78 | { | ||
79 | if (jack->jack_dirty) { | ||
80 | jack->pin_sense = read_pin_sense(codec, jack->nid); | ||
81 | jack->jack_dirty = 0; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | /** | ||
86 | * snd_hda_set_dirty_all - Mark all the cached as dirty | ||
87 | * | ||
88 | * This function sets the dirty flag to all entries of jack table. | ||
89 | * It's called from the resume path in hda_codec.c. | ||
90 | */ | ||
91 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec) | ||
92 | { | ||
93 | struct hda_jack_tbl *jack = codec->jacktbl.list; | ||
94 | int i; | ||
95 | |||
96 | for (i = 0; i < codec->jacktbl.used; i++, jack++) | ||
97 | if (jack->nid) | ||
98 | jack->jack_dirty = 1; | ||
99 | } | ||
100 | EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all); | ||
101 | |||
102 | /** | ||
103 | * snd_hda_pin_sense - execute pin sense measurement | ||
104 | * @codec: the CODEC to sense | ||
105 | * @nid: the pin NID to sense | ||
106 | * | ||
107 | * Execute necessary pin sense measurement and return its Presence Detect, | ||
108 | * Impedance, ELD Valid etc. status bits. | ||
109 | */ | ||
110 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid) | ||
111 | { | ||
112 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); | ||
113 | if (jack) { | ||
114 | jack_detect_update(codec, jack); | ||
115 | return jack->pin_sense; | ||
116 | } | ||
117 | return read_pin_sense(codec, nid); | ||
118 | } | ||
119 | EXPORT_SYMBOL_HDA(snd_hda_pin_sense); | ||
120 | |||
121 | /** | ||
122 | * snd_hda_jack_detect - query pin Presence Detect status | ||
123 | * @codec: the CODEC to sense | ||
124 | * @nid: the pin NID to sense | ||
125 | * | ||
126 | * Query and return the pin's Presence Detect status. | ||
127 | */ | ||
128 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) | ||
129 | { | ||
130 | u32 sense = snd_hda_pin_sense(codec, nid); | ||
131 | return !!(sense & AC_PINSENSE_PRESENCE); | ||
132 | } | ||
133 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect); | ||
134 | |||
135 | /** | ||
136 | * snd_hda_jack_detect_enable - enable the jack-detection | ||
137 | */ | ||
138 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | ||
139 | unsigned int tag) | ||
140 | { | ||
141 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); | ||
142 | if (!jack) | ||
143 | return -ENOMEM; | ||
144 | return snd_hda_codec_write_cache(codec, nid, 0, | ||
145 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
146 | AC_USRSP_EN | tag); | ||
147 | } | ||
148 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); | ||
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h new file mode 100644 index 000000000000..5c1bcb8cf565 --- /dev/null +++ b/sound/pci/hda/hda_jack.h | |||
@@ -0,0 +1,63 @@ | |||
1 | /* | ||
2 | * Jack-detection handling for HD-audio | ||
3 | * | ||
4 | * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> | ||
5 | * | ||
6 | * This driver is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef __SOUND_HDA_JACK_H | ||
13 | #define __SOUND_HDA_JACK_H | ||
14 | |||
15 | struct hda_jack_tbl { | ||
16 | hda_nid_t nid; | ||
17 | unsigned int pin_sense; /* cached pin-sense value */ | ||
18 | unsigned int jack_dirty:1; /* needs to update? */ | ||
19 | }; | ||
20 | |||
21 | struct hda_jack_tbl * | ||
22 | snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); | ||
23 | |||
24 | struct hda_jack_tbl * | ||
25 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); | ||
26 | void snd_hda_jack_tbl_clear(struct hda_codec *codec); | ||
27 | |||
28 | /** | ||
29 | * snd_hda_jack_set_dirty - set the dirty flag for the given jack-entry | ||
30 | * | ||
31 | * Call this function when a pin-state may change, e.g. when the hardware | ||
32 | * notifies via an unsolicited event. | ||
33 | */ | ||
34 | static inline void snd_hda_jack_set_dirty(struct hda_codec *codec, | ||
35 | hda_nid_t nid) | ||
36 | { | ||
37 | struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); | ||
38 | if (jack) | ||
39 | jack->jack_dirty = 1; | ||
40 | } | ||
41 | |||
42 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec); | ||
43 | |||
44 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | ||
45 | unsigned int tag); | ||
46 | |||
47 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | ||
48 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | ||
49 | |||
50 | static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | ||
51 | { | ||
52 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
53 | return false; | ||
54 | if (!codec->ignore_misc_bit && | ||
55 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
56 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
57 | return false; | ||
58 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
59 | return false; | ||
60 | return true; | ||
61 | } | ||
62 | |||
63 | #endif /* __SOUND_HDA_JACK_H */ | ||
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 7a10fe95211e..08e88b826d27 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -505,21 +505,6 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir, | |||
505 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); | 505 | u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); |
506 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, | 506 | int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, |
507 | unsigned int caps); | 507 | unsigned int caps); |
508 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | ||
509 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | ||
510 | |||
511 | static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) | ||
512 | { | ||
513 | if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) | ||
514 | return false; | ||
515 | if (!codec->ignore_misc_bit && | ||
516 | (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & | ||
517 | AC_DEFCFG_MISC_NO_PRESENCE)) | ||
518 | return false; | ||
519 | if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)) | ||
520 | return false; | ||
521 | return true; | ||
522 | } | ||
523 | 508 | ||
524 | /* flags for hda_nid_item */ | 509 | /* flags for hda_nid_item */ |
525 | #define HDA_NID_ITEM_AMP (1<<0) | 510 | #define HDA_NID_ITEM_AMP (1<<0) |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index bcb3310c394f..9cb14b42dfff 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include "hda_codec.h" | 29 | #include "hda_codec.h" |
30 | #include "hda_local.h" | 30 | #include "hda_local.h" |
31 | #include "hda_beep.h" | 31 | #include "hda_beep.h" |
32 | #include "hda_jack.h" | ||
32 | 33 | ||
33 | struct ad198x_spec { | 34 | struct ad198x_spec { |
34 | const struct snd_kcontrol_new *mixers[6]; | 35 | const struct snd_kcontrol_new *mixers[6]; |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 34a460bd27bb..6f158777f71a 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <sound/core.h> | 26 | #include <sound/core.h> |
27 | #include "hda_codec.h" | 27 | #include "hda_codec.h" |
28 | #include "hda_local.h" | 28 | #include "hda_local.h" |
29 | #include "hda_jack.h" | ||
29 | #include <sound/tlv.h> | 30 | #include <sound/tlv.h> |
30 | 31 | ||
31 | /* | 32 | /* |
@@ -1020,9 +1021,7 @@ static void init_output(struct hda_codec *codec) | |||
1020 | if (!cfg->speaker_outs) | 1021 | if (!cfg->speaker_outs) |
1021 | continue; | 1022 | continue; |
1022 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { | 1023 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
1023 | snd_hda_codec_write(codec, nid, 0, | 1024 | snd_hda_jack_detect_enable(codec, nid, HP_EVENT); |
1024 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1025 | AC_USRSP_EN | HP_EVENT); | ||
1026 | spec->hp_detect = 1; | 1025 | spec->hp_detect = 1; |
1027 | } | 1026 | } |
1028 | } | 1027 | } |
@@ -1063,9 +1062,7 @@ static void init_input(struct hda_codec *codec) | |||
1063 | AC_VERB_SET_AMP_GAIN_MUTE, | 1062 | AC_VERB_SET_AMP_GAIN_MUTE, |
1064 | AMP_IN_MUTE(spec->adc_idx[i])); | 1063 | AMP_IN_MUTE(spec->adc_idx[i])); |
1065 | if (spec->mic_detect && spec->automic_idx == i) | 1064 | if (spec->mic_detect && spec->automic_idx == i) |
1066 | snd_hda_codec_write(codec, pin, 0, | 1065 | snd_hda_jack_detect_enable(codec, pin, MIC_EVENT); |
1067 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1068 | AC_USRSP_EN | MIC_EVENT); | ||
1069 | } | 1066 | } |
1070 | /* specific to CS421x */ | 1067 | /* specific to CS421x */ |
1071 | if (spec->vendor_nid == CS421X_VENDOR_NID) { | 1068 | if (spec->vendor_nid == CS421X_VENDOR_NID) { |
@@ -1227,6 +1224,8 @@ static void cs_free(struct hda_codec *codec) | |||
1227 | 1224 | ||
1228 | static void cs_unsol_event(struct hda_codec *codec, unsigned int res) | 1225 | static void cs_unsol_event(struct hda_codec *codec, unsigned int res) |
1229 | { | 1226 | { |
1227 | snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ | ||
1228 | |||
1230 | switch ((res >> 26) & 0x7f) { | 1229 | switch ((res >> 26) & 0x7f) { |
1231 | case HP_EVENT: | 1230 | case HP_EVENT: |
1232 | cs_automute(codec); | 1231 | cs_automute(codec); |
@@ -1585,10 +1584,7 @@ static void init_cs421x_digital(struct hda_codec *codec) | |||
1585 | if (!cfg->speaker_outs) | 1584 | if (!cfg->speaker_outs) |
1586 | continue; | 1585 | continue; |
1587 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { | 1586 | if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) { |
1588 | 1587 | snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT); | |
1589 | snd_hda_codec_write(codec, nid, 0, | ||
1590 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1591 | AC_USRSP_EN | SPDIF_EVENT); | ||
1592 | spec->spdif_detect = 1; | 1588 | spec->spdif_detect = 1; |
1593 | } | 1589 | } |
1594 | } | 1590 | } |
@@ -1806,6 +1802,8 @@ static int cs421x_build_controls(struct hda_codec *codec) | |||
1806 | 1802 | ||
1807 | static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) | 1803 | static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) |
1808 | { | 1804 | { |
1805 | snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ | ||
1806 | |||
1809 | switch ((res >> 26) & 0x3f) { | 1807 | switch ((res >> 26) & 0x3f) { |
1810 | case HP_EVENT: | 1808 | case HP_EVENT: |
1811 | case SPDIF_EVENT: | 1809 | case SPDIF_EVENT: |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 0de21193a2b0..220e567ccfff 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include "hda_codec.h" | 31 | #include "hda_codec.h" |
32 | #include "hda_local.h" | 32 | #include "hda_local.h" |
33 | #include "hda_beep.h" | 33 | #include "hda_beep.h" |
34 | #include "hda_jack.h" | ||
34 | 35 | ||
35 | #define CXT_PIN_DIR_IN 0x00 | 36 | #define CXT_PIN_DIR_IN 0x00 |
36 | #define CXT_PIN_DIR_OUT 0x01 | 37 | #define CXT_PIN_DIR_OUT 0x01 |
@@ -3756,6 +3757,7 @@ static void cx_auto_automic(struct hda_codec *codec) | |||
3756 | static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | 3757 | static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) |
3757 | { | 3758 | { |
3758 | int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; | 3759 | int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; |
3760 | snd_hda_jack_set_dirty(codec, nid); | ||
3759 | switch (res >> 26) { | 3761 | switch (res >> 26) { |
3760 | case CONEXANT_HP_EVENT: | 3762 | case CONEXANT_HP_EVENT: |
3761 | cx_auto_hp_automute(codec); | 3763 | cx_auto_hp_automute(codec); |
@@ -3983,9 +3985,7 @@ static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | |||
3983 | { | 3985 | { |
3984 | int i; | 3986 | int i; |
3985 | for (i = 0; i < num_pins; i++) | 3987 | for (i = 0; i < num_pins; i++) |
3986 | snd_hda_codec_write(codec, pins[i], 0, | 3988 | snd_hda_jack_detect_enable(codec, pins[i], tag); |
3987 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
3988 | AC_USRSP_EN | tag); | ||
3989 | } | 3989 | } |
3990 | 3990 | ||
3991 | static void cx_auto_init_output(struct hda_codec *codec) | 3991 | static void cx_auto_init_output(struct hda_codec *codec) |
@@ -4060,16 +4060,14 @@ static void cx_auto_init_input(struct hda_codec *codec) | |||
4060 | 4060 | ||
4061 | if (spec->auto_mic) { | 4061 | if (spec->auto_mic) { |
4062 | if (spec->auto_mic_ext >= 0) { | 4062 | if (spec->auto_mic_ext >= 0) { |
4063 | snd_hda_codec_write(codec, | 4063 | snd_hda_jack_detect_enable(codec, |
4064 | cfg->inputs[spec->auto_mic_ext].pin, 0, | 4064 | cfg->inputs[spec->auto_mic_ext].pin, |
4065 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4065 | CONEXANT_MIC_EVENT); |
4066 | AC_USRSP_EN | CONEXANT_MIC_EVENT); | ||
4067 | } | 4066 | } |
4068 | if (spec->auto_mic_dock >= 0) { | 4067 | if (spec->auto_mic_dock >= 0) { |
4069 | snd_hda_codec_write(codec, | 4068 | snd_hda_jack_detect_enable(codec, |
4070 | cfg->inputs[spec->auto_mic_dock].pin, 0, | 4069 | cfg->inputs[spec->auto_mic_dock].pin, |
4071 | AC_VERB_SET_UNSOLICITED_ENABLE, | 4070 | CONEXANT_MIC_EVENT); |
4072 | AC_USRSP_EN | CONEXANT_MIC_EVENT); | ||
4073 | } | 4071 | } |
4074 | cx_auto_automic(codec); | 4072 | cx_auto_automic(codec); |
4075 | } else { | 4073 | } else { |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 9850c5b481ea..ea6d85d48444 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <sound/jack.h> | 36 | #include <sound/jack.h> |
37 | #include "hda_codec.h" | 37 | #include "hda_codec.h" |
38 | #include "hda_local.h" | 38 | #include "hda_local.h" |
39 | #include "hda_jack.h" | ||
39 | 40 | ||
40 | static bool static_hdmi_pcm; | 41 | static bool static_hdmi_pcm; |
41 | module_param(static_hdmi_pcm, bool, 0644); | 42 | module_param(static_hdmi_pcm, bool, 0644); |
@@ -766,6 +767,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | |||
766 | if (pin_idx < 0) | 767 | if (pin_idx < 0) |
767 | return; | 768 | return; |
768 | 769 | ||
770 | snd_hda_jack_set_dirty(codec, pin_nid); | ||
769 | hdmi_present_sense(&spec->pins[pin_idx], true); | 771 | hdmi_present_sense(&spec->pins[pin_idx], true); |
770 | } | 772 | } |
771 | 773 | ||
@@ -1282,9 +1284,7 @@ static int generic_hdmi_init(struct hda_codec *codec) | |||
1282 | struct hdmi_eld *eld = &per_pin->sink_eld; | 1284 | struct hdmi_eld *eld = &per_pin->sink_eld; |
1283 | 1285 | ||
1284 | hdmi_init_pin(codec, pin_nid); | 1286 | hdmi_init_pin(codec, pin_nid); |
1285 | snd_hda_codec_write(codec, pin_nid, 0, | 1287 | snd_hda_jack_detect_enable(codec, pin_nid, pin_nid); |
1286 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1287 | AC_USRSP_EN | pin_nid); | ||
1288 | 1288 | ||
1289 | per_pin->codec = codec; | 1289 | per_pin->codec = codec; |
1290 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); | 1290 | INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); |
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 14feecf2d802..da9d2276e68b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include "hda_codec.h" | 33 | #include "hda_codec.h" |
34 | #include "hda_local.h" | 34 | #include "hda_local.h" |
35 | #include "hda_beep.h" | 35 | #include "hda_beep.h" |
36 | #include "hda_jack.h" | ||
36 | 37 | ||
37 | /* unsol event tags */ | 38 | /* unsol event tags */ |
38 | #define ALC_FRONT_EVENT 0x01 | 39 | #define ALC_FRONT_EVENT 0x01 |
@@ -664,6 +665,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | |||
664 | res >>= 28; | 665 | res >>= 28; |
665 | else | 666 | else |
666 | res >>= 26; | 667 | res >>= 26; |
668 | snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ | ||
667 | switch (res) { | 669 | switch (res) { |
668 | case ALC_HP_EVENT: | 670 | case ALC_HP_EVENT: |
669 | alc_hp_automute(codec); | 671 | alc_hp_automute(codec); |
@@ -964,9 +966,7 @@ static void alc_init_automute(struct hda_codec *codec) | |||
964 | continue; | 966 | continue; |
965 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 967 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", |
966 | nid); | 968 | nid); |
967 | snd_hda_codec_write_cache(codec, nid, 0, | 969 | snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT); |
968 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
969 | AC_USRSP_EN | ALC_HP_EVENT); | ||
970 | spec->detect_hp = 1; | 970 | spec->detect_hp = 1; |
971 | } | 971 | } |
972 | 972 | ||
@@ -978,9 +978,8 @@ static void alc_init_automute(struct hda_codec *codec) | |||
978 | continue; | 978 | continue; |
979 | snd_printdd("realtek: Enable Line-Out " | 979 | snd_printdd("realtek: Enable Line-Out " |
980 | "auto-muting on NID 0x%x\n", nid); | 980 | "auto-muting on NID 0x%x\n", nid); |
981 | snd_hda_codec_write_cache(codec, nid, 0, | 981 | snd_hda_jack_detect_enable(codec, nid, |
982 | AC_VERB_SET_UNSOLICITED_ENABLE, | 982 | ALC_FRONT_EVENT); |
983 | AC_USRSP_EN | ALC_FRONT_EVENT); | ||
984 | spec->detect_lo = 1; | 983 | spec->detect_lo = 1; |
985 | } | 984 | } |
986 | spec->automute_lo_possible = spec->detect_hp; | 985 | spec->automute_lo_possible = spec->detect_hp; |
@@ -1108,13 +1107,10 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec) | |||
1108 | return false; /* no corresponding imux */ | 1107 | return false; /* no corresponding imux */ |
1109 | } | 1108 | } |
1110 | 1109 | ||
1111 | snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0, | 1110 | snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT); |
1112 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
1113 | AC_USRSP_EN | ALC_MIC_EVENT); | ||
1114 | if (spec->dock_mic_pin) | 1111 | if (spec->dock_mic_pin) |
1115 | snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0, | 1112 | snd_hda_jack_detect_enable(codec, spec->dock_mic_pin, |
1116 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1113 | ALC_MIC_EVENT); |
1117 | AC_USRSP_EN | ALC_MIC_EVENT); | ||
1118 | 1114 | ||
1119 | spec->auto_mic_valid_imux = 1; | 1115 | spec->auto_mic_valid_imux = 1; |
1120 | spec->auto_mic = 1; | 1116 | spec->auto_mic = 1; |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index 3b4ef0cba0e7..97c6df9db5e9 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include "hda_codec.h" | 37 | #include "hda_codec.h" |
38 | #include "hda_local.h" | 38 | #include "hda_local.h" |
39 | #include "hda_beep.h" | 39 | #include "hda_beep.h" |
40 | #include "hda_jack.h" | ||
40 | 41 | ||
41 | enum { | 42 | enum { |
42 | STAC_VREF_EVENT = 1, | 43 | STAC_VREF_EVENT = 1, |
@@ -4244,9 +4245,7 @@ static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | |||
4244 | if (tag < 0) | 4245 | if (tag < 0) |
4245 | return 0; | 4246 | return 0; |
4246 | } | 4247 | } |
4247 | snd_hda_codec_write_cache(codec, nid, 0, | 4248 | snd_hda_jack_detect_enable(codec, nid, tag); |
4248 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
4249 | AC_USRSP_EN | tag); | ||
4250 | return 1; | 4249 | return 1; |
4251 | } | 4250 | } |
4252 | 4251 | ||
@@ -4795,24 +4794,11 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
4795 | mic->mux_idx); | 4794 | mic->mux_idx); |
4796 | } | 4795 | } |
4797 | 4796 | ||
4798 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | 4797 | static void handle_unsol_event(struct hda_codec *codec, |
4799 | { | 4798 | struct sigmatel_event *event) |
4800 | struct sigmatel_event *event = stac_get_event(codec, nid); | ||
4801 | if (!event) | ||
4802 | return; | ||
4803 | codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26); | ||
4804 | } | ||
4805 | |||
4806 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
4807 | { | 4799 | { |
4808 | struct sigmatel_spec *spec = codec->spec; | 4800 | struct sigmatel_spec *spec = codec->spec; |
4809 | struct sigmatel_event *event; | 4801 | int data; |
4810 | int tag, data; | ||
4811 | |||
4812 | tag = (res >> 26) & 0x7f; | ||
4813 | event = stac_get_event_from_tag(codec, tag); | ||
4814 | if (!event) | ||
4815 | return; | ||
4816 | 4802 | ||
4817 | switch (event->type) { | 4803 | switch (event->type) { |
4818 | case STAC_HP_EVENT: | 4804 | case STAC_HP_EVENT: |
@@ -4862,6 +4848,28 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | |||
4862 | } | 4848 | } |
4863 | } | 4849 | } |
4864 | 4850 | ||
4851 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | ||
4852 | { | ||
4853 | struct sigmatel_event *event = stac_get_event(codec, nid); | ||
4854 | if (!event) | ||
4855 | return; | ||
4856 | handle_unsol_event(codec, event); | ||
4857 | } | ||
4858 | |||
4859 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | ||
4860 | { | ||
4861 | struct sigmatel_spec *spec = codec->spec; | ||
4862 | struct sigmatel_event *event; | ||
4863 | int tag; | ||
4864 | |||
4865 | tag = (res >> 26) & 0x7f; | ||
4866 | event = stac_get_event_from_tag(codec, tag); | ||
4867 | if (!event) | ||
4868 | return; | ||
4869 | snd_hda_jack_set_dirty(codec, event->nid); | ||
4870 | handle_unsol_event(codec, event); | ||
4871 | } | ||
4872 | |||
4865 | static int hp_blike_system(u32 subsystem_id); | 4873 | static int hp_blike_system(u32 subsystem_id); |
4866 | 4874 | ||
4867 | static void set_hp_led_gpio(struct hda_codec *codec) | 4875 | static void set_hp_led_gpio(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index 431c0d417eeb..3467d0c23fe9 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <sound/asoundef.h> | 54 | #include <sound/asoundef.h> |
55 | #include "hda_codec.h" | 55 | #include "hda_codec.h" |
56 | #include "hda_local.h" | 56 | #include "hda_local.h" |
57 | #include "hda_jack.h" | ||
57 | 58 | ||
58 | /* Pin Widget NID */ | 59 | /* Pin Widget NID */ |
59 | #define VT1708_HP_PIN_NID 0x20 | 60 | #define VT1708_HP_PIN_NID 0x20 |
@@ -1708,6 +1709,8 @@ static void via_gpio_control(struct hda_codec *codec) | |||
1708 | static void via_unsol_event(struct hda_codec *codec, | 1709 | static void via_unsol_event(struct hda_codec *codec, |
1709 | unsigned int res) | 1710 | unsigned int res) |
1710 | { | 1711 | { |
1712 | snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ | ||
1713 | |||
1711 | res >>= 26; | 1714 | res >>= 26; |
1712 | 1715 | ||
1713 | if (res & VIA_JACK_EVENT) | 1716 | if (res & VIA_JACK_EVENT) |
@@ -2729,9 +2732,8 @@ static void via_auto_init_unsol_event(struct hda_codec *codec) | |||
2729 | int i; | 2732 | int i; |
2730 | 2733 | ||
2731 | if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0])) | 2734 | if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0])) |
2732 | snd_hda_codec_write(codec, cfg->hp_pins[0], 0, | 2735 | snd_hda_jack_detect_enable(codec, cfg->hp_pins[0], |
2733 | AC_VERB_SET_UNSOLICITED_ENABLE, | 2736 | VIA_HP_EVENT | VIA_JACK_EVENT); |
2734 | AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT); | ||
2735 | 2737 | ||
2736 | if (cfg->speaker_pins[0]) | 2738 | if (cfg->speaker_pins[0]) |
2737 | ev = VIA_LINE_EVENT; | 2739 | ev = VIA_LINE_EVENT; |
@@ -2740,16 +2742,14 @@ static void via_auto_init_unsol_event(struct hda_codec *codec) | |||
2740 | for (i = 0; i < cfg->line_outs; i++) { | 2742 | for (i = 0; i < cfg->line_outs; i++) { |
2741 | if (cfg->line_out_pins[i] && | 2743 | if (cfg->line_out_pins[i] && |
2742 | is_jack_detectable(codec, cfg->line_out_pins[i])) | 2744 | is_jack_detectable(codec, cfg->line_out_pins[i])) |
2743 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | 2745 | snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i], |
2744 | AC_VERB_SET_UNSOLICITED_ENABLE, | 2746 | ev | VIA_JACK_EVENT); |
2745 | AC_USRSP_EN | ev | VIA_JACK_EVENT); | ||
2746 | } | 2747 | } |
2747 | 2748 | ||
2748 | for (i = 0; i < cfg->num_inputs; i++) { | 2749 | for (i = 0; i < cfg->num_inputs; i++) { |
2749 | if (is_jack_detectable(codec, cfg->inputs[i].pin)) | 2750 | if (is_jack_detectable(codec, cfg->inputs[i].pin)) |
2750 | snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, | 2751 | snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin, |
2751 | AC_VERB_SET_UNSOLICITED_ENABLE, | 2752 | VIA_JACK_EVENT); |
2752 | AC_USRSP_EN | VIA_JACK_EVENT); | ||
2753 | } | 2753 | } |
2754 | } | 2754 | } |
2755 | 2755 | ||
@@ -2781,6 +2781,7 @@ static void vt1708_update_hp_jack_state(struct work_struct *work) | |||
2781 | vt1708_hp_work.work); | 2781 | vt1708_hp_work.work); |
2782 | if (spec->codec_type != VT1708) | 2782 | if (spec->codec_type != VT1708) |
2783 | return; | 2783 | return; |
2784 | snd_hda_jack_set_dirty_all(spec->codec); | ||
2784 | /* if jack state toggled */ | 2785 | /* if jack state toggled */ |
2785 | if (spec->vt1708_hp_present | 2786 | if (spec->vt1708_hp_present |
2786 | != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) { | 2787 | != snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) { |