aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-10-27 19:16:55 -0400
committerTakashi Iwai <tiwai@suse.de>2011-11-16 05:14:03 -0500
commit3a93897ea37cbb8277f8a4232c12c0c18168a7db (patch)
tree1c79df3bb270e86c61bdb13fab0bf66cbd3682ac /sound
parent01a61e12b4602c82bde9797d0e153f3e53c95b04 (diff)
ALSA: hda - Manage unsol tags in hda_jack.c
Manage the tags assigned for unsolicited events dynamically together with the jack-detection routines. Basically this is almost same as what we've done in patch_sigmatel.c. Assign the new tag number for each new unsol event, associate with the given NID and the action type, etc. With this change, now all pins looked over in snd_hda_jack_add_kctls() are actually enabled for detection now even if the pins aren't used for jack-retasking by the driver. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/hda_jack.c61
-rw-r--r--sound/pci/hda/hda_jack.h28
-rw-r--r--sound/pci/hda/patch_cirrus.c8
-rw-r--r--sound/pci/hda/patch_conexant.c8
-rw-r--r--sound/pci/hda/patch_hdmi.c13
-rw-r--r--sound/pci/hda/patch_realtek.c6
-rw-r--r--sound/pci/hda/patch_sigmatel.c104
-rw-r--r--sound/pci/hda/patch_via.c3
8 files changed, 105 insertions, 126 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index cee6a00bd85a..8829d5c83fec 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -51,6 +51,24 @@ snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
51EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); 51EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
52 52
53/** 53/**
54 * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
55 */
56struct hda_jack_tbl *
57snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
58{
59 struct hda_jack_tbl *jack = codec->jacktbl.list;
60 int i;
61
62 if (!tag || !jack)
63 return NULL;
64 for (i = 0; i < codec->jacktbl.used; i++, jack++)
65 if (jack->tag == tag)
66 return jack;
67 return NULL;
68}
69EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
70
71/**
54 * snd_hda_jack_tbl_new - create a jack-table entry for the given NID 72 * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
55 */ 73 */
56struct hda_jack_tbl * 74struct hda_jack_tbl *
@@ -65,6 +83,7 @@ snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
65 return NULL; 83 return NULL;
66 jack->nid = nid; 84 jack->nid = nid;
67 jack->jack_dirty = 1; 85 jack->jack_dirty = 1;
86 jack->tag = codec->jacktbl.used;
68 return jack; 87 return jack;
69} 88}
70 89
@@ -77,7 +96,7 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
77static void jack_detect_update(struct hda_codec *codec, 96static void jack_detect_update(struct hda_codec *codec,
78 struct hda_jack_tbl *jack) 97 struct hda_jack_tbl *jack)
79{ 98{
80 if (jack->jack_dirty || !jack->jack_cachable) { 99 if (jack->jack_dirty || !jack->jack_detect) {
81 unsigned int val = read_pin_sense(codec, jack->nid); 100 unsigned int val = read_pin_sense(codec, jack->nid);
82 jack->jack_dirty = 0; 101 jack->jack_dirty = 0;
83 if (val != jack->pin_sense) { 102 if (val != jack->pin_sense) {
@@ -141,17 +160,19 @@ EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
141 * snd_hda_jack_detect_enable - enable the jack-detection 160 * snd_hda_jack_detect_enable - enable the jack-detection
142 */ 161 */
143int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, 162int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
144 unsigned int tag) 163 unsigned char action)
145{ 164{
146 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 165 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
147 if (!jack) 166 if (!jack)
148 return -ENOMEM; 167 return -ENOMEM;
149 if (jack->jack_cachable) 168 if (jack->jack_detect)
150 return 0; /* already registered */ 169 return 0; /* already registered */
151 jack->jack_cachable = 1; 170 jack->jack_detect = 1;
171 if (action)
172 jack->action = action;
152 return snd_hda_codec_write_cache(codec, nid, 0, 173 return snd_hda_codec_write_cache(codec, nid, 0,
153 AC_VERB_SET_UNSOLICITED_ENABLE, 174 AC_VERB_SET_UNSOLICITED_ENABLE,
154 AC_USRSP_EN | tag); 175 AC_USRSP_EN | jack->tag);
155} 176}
156EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); 177EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
157 178
@@ -168,18 +189,6 @@ static void jack_detect_report(struct hda_codec *codec,
168} 189}
169 190
170/** 191/**
171 * snd_hda_jack_report - notify kctl when the jack state was changed
172 */
173void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid)
174{
175 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
176
177 if (jack)
178 jack_detect_report(codec, jack);
179}
180EXPORT_SYMBOL_HDA(snd_hda_jack_report);
181
182/**
183 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed 192 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
184 */ 193 */
185void snd_hda_jack_report_sync(struct hda_codec *codec) 194void snd_hda_jack_report_sync(struct hda_codec *codec)
@@ -231,7 +240,7 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
231 struct hda_jack_tbl *jack; 240 struct hda_jack_tbl *jack;
232 struct snd_kcontrol *kctl; 241 struct snd_kcontrol *kctl;
233 242
234 jack = snd_hda_jack_tbl_get(codec, nid); 243 jack = snd_hda_jack_tbl_new(codec, nid);
235 if (!jack) 244 if (!jack)
236 return 0; 245 return 0;
237 if (jack->kctl) 246 if (jack->kctl)
@@ -251,20 +260,28 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
251static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, 260static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
252 const struct auto_pin_cfg *cfg) 261 const struct auto_pin_cfg *cfg)
253{ 262{
263 unsigned int def_conf, conn;
264 int err;
265
254 if (!nid) 266 if (!nid)
255 return 0; 267 return 0;
256 if (!is_jack_detectable(codec, nid)) 268 if (!is_jack_detectable(codec, nid))
257 return 0; 269 return 0;
258 return snd_hda_jack_add_kctl(codec, nid, 270 def_conf = snd_hda_codec_get_pincfg(codec, nid);
271 conn = get_defcfg_connect(def_conf);
272 if (conn != AC_JACK_PORT_COMPLEX)
273 return 0;
274
275 err = snd_hda_jack_add_kctl(codec, nid,
259 snd_hda_get_pin_label(codec, nid, cfg), 276 snd_hda_get_pin_label(codec, nid, cfg),
260 idx); 277 idx);
278 if (err < 0)
279 return err;
280 return snd_hda_jack_detect_enable(codec, nid, 0);
261} 281}
262 282
263/** 283/**
264 * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg 284 * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
265 *
266 * As of now, it assigns only to the pins that enabled the detection.
267 * Usually this is called at the end of build_controls callback.
268 */ 285 */
269int snd_hda_jack_add_kctls(struct hda_codec *codec, 286int snd_hda_jack_add_kctls(struct hda_codec *codec,
270 const struct auto_pin_cfg *cfg) 287 const struct auto_pin_cfg *cfg)
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index b5983eaea51e..69a67f8e4f45 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -14,8 +14,12 @@
14 14
15struct hda_jack_tbl { 15struct hda_jack_tbl {
16 hda_nid_t nid; 16 hda_nid_t nid;
17 unsigned char action; /* event action (0 = none) */
18 unsigned char tag; /* unsol event tag */
19 unsigned int private_data; /* arbitrary data */
20 /* jack-detection stuff */
17 unsigned int pin_sense; /* cached pin-sense value */ 21 unsigned int pin_sense; /* cached pin-sense value */
18 unsigned int jack_cachable:1; /* can be updated via unsol events */ 22 unsigned int jack_detect:1; /* capable of jack-detection? */
19 unsigned int jack_dirty:1; /* needs to update? */ 23 unsigned int jack_dirty:1; /* needs to update? */
20 unsigned int need_notify:1; /* to be notified? */ 24 unsigned int need_notify:1; /* to be notified? */
21 struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */ 25 struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
@@ -23,29 +27,34 @@ struct hda_jack_tbl {
23 27
24struct hda_jack_tbl * 28struct hda_jack_tbl *
25snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); 29snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
30struct hda_jack_tbl *
31snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);
26 32
27struct hda_jack_tbl * 33struct hda_jack_tbl *
28snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); 34snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
29void snd_hda_jack_tbl_clear(struct hda_codec *codec); 35void snd_hda_jack_tbl_clear(struct hda_codec *codec);
30 36
31/** 37/**
32 * snd_hda_jack_set_dirty - set the dirty flag for the given jack-entry 38 * snd_hda_jack_get_action - get jack-tbl entry for the tag
33 * 39 *
34 * Call this function when a pin-state may change, e.g. when the hardware 40 * Call this from the unsol event handler to get the assigned action for the
35 * notifies via an unsolicited event. 41 * event. This will mark the dirty flag for the later reporting, too.
36 */ 42 */
37static inline void snd_hda_jack_set_dirty(struct hda_codec *codec, 43static inline unsigned char
38 hda_nid_t nid) 44snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)
39{ 45{
40 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid); 46 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
41 if (jack) 47 if (jack) {
42 jack->jack_dirty = 1; 48 jack->jack_dirty = 1;
49 return jack->action;
50 }
51 return 0;
43} 52}
44 53
45void snd_hda_jack_set_dirty_all(struct hda_codec *codec); 54void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
46 55
47int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, 56int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
48 unsigned int tag); 57 unsigned char action);
49 58
50u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); 59u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
51int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); 60int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
@@ -68,7 +77,6 @@ int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
68int snd_hda_jack_add_kctls(struct hda_codec *codec, 77int snd_hda_jack_add_kctls(struct hda_codec *codec,
69 const struct auto_pin_cfg *cfg); 78 const struct auto_pin_cfg *cfg);
70 79
71void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid);
72void snd_hda_jack_report_sync(struct hda_codec *codec); 80void snd_hda_jack_report_sync(struct hda_codec *codec);
73 81
74 82
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 135fd49cd49d..0e34554bc45e 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -1235,9 +1235,7 @@ static void cs_free(struct hda_codec *codec)
1235 1235
1236static void cs_unsol_event(struct hda_codec *codec, unsigned int res) 1236static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
1237{ 1237{
1238 snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ 1238 switch (snd_hda_jack_get_action(codec, res >> 26)) {
1239
1240 switch ((res >> 26) & 0x7f) {
1241 case HP_EVENT: 1239 case HP_EVENT:
1242 cs_automute(codec); 1240 cs_automute(codec);
1243 break; 1241 break;
@@ -1824,9 +1822,7 @@ static int cs421x_build_controls(struct hda_codec *codec)
1824 1822
1825static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) 1823static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
1826{ 1824{
1827 snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ 1825 switch (snd_hda_jack_get_action(codec, res >> 26)) {
1828
1829 switch ((res >> 26) & 0x3f) {
1830 case HP_EVENT: 1826 case HP_EVENT:
1831 case SPDIF_EVENT: 1827 case SPDIF_EVENT:
1832 cs_automute(codec); 1828 cs_automute(codec);
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 25fdd1e9561f..40bd75b293ba 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3757,8 +3757,8 @@ static void cx_auto_automic(struct hda_codec *codec)
3757static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) 3757static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
3758{ 3758{
3759 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); 3760
3761 switch (res >> 26) { 3761 switch (snd_hda_jack_get_action(codec, res >> 26)) {
3762 case CONEXANT_HP_EVENT: 3762 case CONEXANT_HP_EVENT:
3763 cx_auto_hp_automute(codec); 3763 cx_auto_hp_automute(codec);
3764 break; 3764 break;
@@ -3982,11 +3982,11 @@ static void mute_outputs(struct hda_codec *codec, int num_nids,
3982} 3982}
3983 3983
3984static void enable_unsol_pins(struct hda_codec *codec, int num_pins, 3984static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
3985 hda_nid_t *pins, unsigned int tag) 3985 hda_nid_t *pins, unsigned int action)
3986{ 3986{
3987 int i; 3987 int i;
3988 for (i = 0; i < num_pins; i++) 3988 for (i = 0; i < num_pins; i++)
3989 snd_hda_jack_detect_enable(codec, pins[i], tag); 3989 snd_hda_jack_detect_enable(codec, pins[i], action);
3990} 3990}
3991 3991
3992static void cx_auto_init_output(struct hda_codec *codec) 3992static void cx_auto_init_output(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index f01c5efde8e1..ea30bf4a4f50 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -754,10 +754,18 @@ static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, bool retry);
754static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) 754static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
755{ 755{
756 struct hdmi_spec *spec = codec->spec; 756 struct hdmi_spec *spec = codec->spec;
757 int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT; 757 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
758 int pin_nid;
758 int pd = !!(res & AC_UNSOL_RES_PD); 759 int pd = !!(res & AC_UNSOL_RES_PD);
759 int eldv = !!(res & AC_UNSOL_RES_ELDV); 760 int eldv = !!(res & AC_UNSOL_RES_ELDV);
760 int pin_idx; 761 int pin_idx;
762 struct hda_jack_tbl *jack;
763
764 jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
765 if (!jack)
766 return;
767 pin_nid = jack->nid;
768 jack->jack_dirty = 1;
761 769
762 printk(KERN_INFO 770 printk(KERN_INFO
763 "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n", 771 "HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
@@ -767,7 +775,6 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
767 if (pin_idx < 0) 775 if (pin_idx < 0)
768 return; 776 return;
769 777
770 snd_hda_jack_set_dirty(codec, pin_nid);
771 hdmi_present_sense(&spec->pins[pin_idx], true); 778 hdmi_present_sense(&spec->pins[pin_idx], true);
772 snd_hda_jack_report_sync(codec); 779 snd_hda_jack_report_sync(codec);
773} 780}
@@ -801,7 +808,7 @@ static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
801 int tag = res >> AC_UNSOL_RES_TAG_SHIFT; 808 int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
802 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT; 809 int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
803 810
804 if (pin_nid_to_pin_index(spec, tag) < 0) { 811 if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) {
805 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag); 812 snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
806 return; 813 return;
807 } 814 }
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 04beae034fea..9a90cdac78f4 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -185,6 +185,7 @@ struct alc_spec {
185 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */ 185 unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
186 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */ 186 unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
187 unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */ 187 unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
188 unsigned int use_jack_tbl:1; /* 1 for model=auto */
188 189
189 /* auto-mute control */ 190 /* auto-mute control */
190 int automute_mode; 191 int automute_mode;
@@ -661,11 +662,13 @@ static void alc_mic_automute(struct hda_codec *codec)
661/* unsolicited event for HP jack sensing */ 662/* unsolicited event for HP jack sensing */
662static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) 663static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
663{ 664{
665 struct alc_spec *spec = codec->spec;
664 if (codec->vendor_id == 0x10ec0880) 666 if (codec->vendor_id == 0x10ec0880)
665 res >>= 28; 667 res >>= 28;
666 else 668 else
667 res >>= 26; 669 res >>= 26;
668 snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */ 670 if (spec->use_jack_tbl)
671 res = snd_hda_jack_get_action(codec, res);
669 switch (res) { 672 switch (res) {
670 case ALC_HP_EVENT: 673 case ALC_HP_EVENT:
671 alc_hp_automute(codec); 674 alc_hp_automute(codec);
@@ -3896,6 +3899,7 @@ static void set_capture_mixer(struct hda_codec *codec)
3896static void alc_auto_init_std(struct hda_codec *codec) 3899static void alc_auto_init_std(struct hda_codec *codec)
3897{ 3900{
3898 struct alc_spec *spec = codec->spec; 3901 struct alc_spec *spec = codec->spec;
3902 spec->use_jack_tbl = 1;
3899 alc_auto_init_multi_out(codec); 3903 alc_auto_init_multi_out(codec);
3900 alc_auto_init_extra_out(codec); 3904 alc_auto_init_extra_out(codec);
3901 alc_auto_init_analog_input(codec); 3905 alc_auto_init_analog_input(codec);
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 90954b8269c3..dd6569ffcff8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -177,13 +177,6 @@ enum {
177 STAC_9872_MODELS 177 STAC_9872_MODELS
178}; 178};
179 179
180struct sigmatel_event {
181 hda_nid_t nid;
182 unsigned char type;
183 unsigned char tag;
184 int data;
185};
186
187struct sigmatel_mic_route { 180struct sigmatel_mic_route {
188 hda_nid_t pin; 181 hda_nid_t pin;
189 signed char mux_idx; 182 signed char mux_idx;
@@ -231,9 +224,6 @@ struct sigmatel_spec {
231 const hda_nid_t *pwr_nids; 224 const hda_nid_t *pwr_nids;
232 const hda_nid_t *dac_list; 225 const hda_nid_t *dac_list;
233 226
234 /* events */
235 struct snd_array events;
236
237 /* playback */ 227 /* playback */
238 struct hda_input_mux *mono_mux; 228 struct hda_input_mux *mono_mux;
239 unsigned int cur_mmux; 229 unsigned int cur_mmux;
@@ -4182,49 +4172,18 @@ static int stac92xx_add_jack(struct hda_codec *codec,
4182#endif /* CONFIG_SND_HDA_INPUT_JACK */ 4172#endif /* CONFIG_SND_HDA_INPUT_JACK */
4183} 4173}
4184 4174
4185static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, 4175static int stac_add_event(struct hda_codec *codec, hda_nid_t nid,
4186 unsigned char type, int data) 4176 unsigned char type, int data)
4187{ 4177{
4188 struct sigmatel_event *event; 4178 struct hda_jack_tbl *event;
4189 4179
4190 snd_array_init(&spec->events, sizeof(*event), 32); 4180 event = snd_hda_jack_tbl_new(codec, nid);
4191 event = snd_array_new(&spec->events);
4192 if (!event) 4181 if (!event)
4193 return -ENOMEM; 4182 return -ENOMEM;
4194 event->nid = nid; 4183 event->action = type;
4195 event->type = type; 4184 event->private_data = data;
4196 event->tag = spec->events.used;
4197 event->data = data;
4198
4199 return event->tag;
4200}
4201
4202static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
4203 hda_nid_t nid)
4204{
4205 struct sigmatel_spec *spec = codec->spec;
4206 struct sigmatel_event *event = spec->events.list;
4207 int i;
4208
4209 for (i = 0; i < spec->events.used; i++, event++) {
4210 if (event->nid == nid)
4211 return event;
4212 }
4213 return NULL;
4214}
4215 4185
4216static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec, 4186 return 0;
4217 unsigned char tag)
4218{
4219 struct sigmatel_spec *spec = codec->spec;
4220 struct sigmatel_event *event = spec->events.list;
4221 int i;
4222
4223 for (i = 0; i < spec->events.used; i++, event++) {
4224 if (event->tag == tag)
4225 return event;
4226 }
4227 return NULL;
4228} 4187}
4229 4188
4230/* check if given nid is a valid pin and no other events are assigned 4189/* check if given nid is a valid pin and no other events are assigned
@@ -4234,22 +4193,17 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
4234static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, 4193static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
4235 unsigned int type) 4194 unsigned int type)
4236{ 4195{
4237 struct sigmatel_event *event; 4196 struct hda_jack_tbl *event;
4238 int tag;
4239 4197
4240 if (!is_jack_detectable(codec, nid)) 4198 if (!is_jack_detectable(codec, nid))
4241 return 0; 4199 return 0;
4242 event = stac_get_event(codec, nid); 4200 event = snd_hda_jack_tbl_new(codec, nid);
4243 if (event) { 4201 if (!event)
4244 if (event->type != type) 4202 return -ENOMEM;
4245 return 0; 4203 if (event->action && event->action != type)
4246 tag = event->tag; 4204 return 0;
4247 } else { 4205 event->action = type;
4248 tag = stac_add_event(codec->spec, nid, type, 0); 4206 snd_hda_jack_detect_enable(codec, nid, 0);
4249 if (tag < 0)
4250 return 0;
4251 }
4252 snd_hda_jack_detect_enable(codec, nid, tag);
4253 return 1; 4207 return 1;
4254} 4208}
4255 4209
@@ -4536,7 +4490,6 @@ static void stac92xx_free(struct hda_codec *codec)
4536 4490
4537 stac92xx_shutup(codec); 4491 stac92xx_shutup(codec);
4538 snd_hda_input_jack_free(codec); 4492 snd_hda_input_jack_free(codec);
4539 snd_array_free(&spec->events);
4540 4493
4541 kfree(spec); 4494 kfree(spec);
4542 snd_hda_detach_beep_device(codec); 4495 snd_hda_detach_beep_device(codec);
@@ -4801,12 +4754,12 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
4801} 4754}
4802 4755
4803static void handle_unsol_event(struct hda_codec *codec, 4756static void handle_unsol_event(struct hda_codec *codec,
4804 struct sigmatel_event *event) 4757 struct hda_jack_tbl *event)
4805{ 4758{
4806 struct sigmatel_spec *spec = codec->spec; 4759 struct sigmatel_spec *spec = codec->spec;
4807 int data; 4760 int data;
4808 4761
4809 switch (event->type) { 4762 switch (event->action) {
4810 case STAC_HP_EVENT: 4763 case STAC_HP_EVENT:
4811 case STAC_LO_EVENT: 4764 case STAC_LO_EVENT:
4812 stac92xx_hp_detect(codec); 4765 stac92xx_hp_detect(codec);
@@ -4816,7 +4769,7 @@ static void handle_unsol_event(struct hda_codec *codec,
4816 break; 4769 break;
4817 } 4770 }
4818 4771
4819 switch (event->type) { 4772 switch (event->action) {
4820 case STAC_HP_EVENT: 4773 case STAC_HP_EVENT:
4821 case STAC_LO_EVENT: 4774 case STAC_LO_EVENT:
4822 case STAC_MIC_EVENT: 4775 case STAC_MIC_EVENT:
@@ -4849,14 +4802,14 @@ static void handle_unsol_event(struct hda_codec *codec,
4849 AC_VERB_GET_GPIO_DATA, 0); 4802 AC_VERB_GET_GPIO_DATA, 0);
4850 /* toggle VREF state based on GPIOx status */ 4803 /* toggle VREF state based on GPIOx status */
4851 snd_hda_codec_write(codec, codec->afg, 0, 0x7e0, 4804 snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
4852 !!(data & (1 << event->data))); 4805 !!(data & (1 << event->private_data)));
4853 break; 4806 break;
4854 } 4807 }
4855} 4808}
4856 4809
4857static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) 4810static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
4858{ 4811{
4859 struct sigmatel_event *event = stac_get_event(codec, nid); 4812 struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid);
4860 if (!event) 4813 if (!event)
4861 return; 4814 return;
4862 handle_unsol_event(codec, event); 4815 handle_unsol_event(codec, event);
@@ -4864,15 +4817,14 @@ static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
4864 4817
4865static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) 4818static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
4866{ 4819{
4867 struct sigmatel_spec *spec = codec->spec; 4820 struct hda_jack_tbl *event;
4868 struct sigmatel_event *event;
4869 int tag; 4821 int tag;
4870 4822
4871 tag = (res >> 26) & 0x7f; 4823 tag = (res >> 26) & 0x7f;
4872 event = stac_get_event_from_tag(codec, tag); 4824 event = snd_hda_jack_tbl_get_from_tag(codec, tag);
4873 if (!event) 4825 if (!event)
4874 return; 4826 return;
4875 snd_hda_jack_set_dirty(codec, event->nid); 4827 event->jack_dirty = 1;
4876 handle_unsol_event(codec, event); 4828 handle_unsol_event(codec, event);
4877 snd_hda_jack_report_sync(codec); 4829 snd_hda_jack_report_sync(codec);
4878} 4830}
@@ -5857,15 +5809,13 @@ again:
5857 switch (spec->board_config) { 5809 switch (spec->board_config) {
5858 case STAC_HP_M4: 5810 case STAC_HP_M4:
5859 /* Enable VREF power saving on GPIO1 detect */ 5811 /* Enable VREF power saving on GPIO1 detect */
5860 err = stac_add_event(spec, codec->afg, 5812 err = stac_add_event(codec, codec->afg,
5861 STAC_VREF_EVENT, 0x02); 5813 STAC_VREF_EVENT, 0x02);
5862 if (err < 0) 5814 if (err < 0)
5863 return err; 5815 return err;
5864 snd_hda_codec_write_cache(codec, codec->afg, 0, 5816 snd_hda_codec_write_cache(codec, codec->afg, 0,
5865 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02); 5817 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
5866 snd_hda_codec_write_cache(codec, codec->afg, 0, 5818 snd_hda_jack_detect_enable(codec, codec->afg, 0);
5867 AC_VERB_SET_UNSOLICITED_ENABLE,
5868 AC_USRSP_EN | err);
5869 spec->gpio_mask |= 0x02; 5819 spec->gpio_mask |= 0x02;
5870 break; 5820 break;
5871 } 5821 }
@@ -6338,14 +6288,12 @@ static int patch_stac9205(struct hda_codec *codec)
6338 snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030); 6288 snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
6339 6289
6340 /* Enable unsol response for GPIO4/Dock HP connection */ 6290 /* Enable unsol response for GPIO4/Dock HP connection */
6341 err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01); 6291 err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01);
6342 if (err < 0) 6292 if (err < 0)
6343 return err; 6293 return err;
6344 snd_hda_codec_write_cache(codec, codec->afg, 0, 6294 snd_hda_codec_write_cache(codec, codec->afg, 0,
6345 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10); 6295 AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
6346 snd_hda_codec_write_cache(codec, codec->afg, 0, 6296 snd_hda_jack_detect_enable(codec, codec->afg, 0);
6347 AC_VERB_SET_UNSOLICITED_ENABLE,
6348 AC_USRSP_EN | err);
6349 6297
6350 spec->gpio_dir = 0x0b; 6298 spec->gpio_dir = 0x0b;
6351 spec->eapd_mask = 0x01; 6299 spec->eapd_mask = 0x01;
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 852939658ddb..f73c98638abd 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1714,9 +1714,8 @@ static void via_gpio_control(struct hda_codec *codec)
1714static void via_unsol_event(struct hda_codec *codec, 1714static void via_unsol_event(struct hda_codec *codec,
1715 unsigned int res) 1715 unsigned int res)
1716{ 1716{
1717 snd_hda_jack_set_dirty_all(codec); /* FIXME: to be more fine-grained */
1718
1719 res >>= 26; 1717 res >>= 26;
1718 res = snd_hda_jack_get_action(codec, res);
1720 1719
1721 if (res & VIA_JACK_EVENT) 1720 if (res & VIA_JACK_EVENT)
1722 set_widgets_power_state(codec); 1721 set_widgets_power_state(codec);