aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2011-10-27 16:12:46 -0400
committerTakashi Iwai <tiwai@suse.de>2011-11-16 05:11:15 -0500
commit1835a0f9a2121ce3198dab67507d4d3e960cc09e (patch)
tree5cbd9f34a3cb5d4906042c9fed5ab5fe2813123e /sound
parent04f5ade6afc4326dc6cd10d235500972fba548eb (diff)
ALSA: hda - Cache the jack-detection value
Introduce a table containing the pins and their jack-detection states for avoiding the unnecessary verbs to check the pin status at each time. When the unsol event is enabled via snd_hda_jack_detect_enable(), it automatically adds the given NID to the table. Then the driver supposes that the codec driver will set the dirty flag appropariately when an unsolicited event is invoked for that pin. The behavior for reading other pins that aren't registered in the table doesn't change. Only the pins assigned to the table are cached, so far. In near futre, this table can be extended to use the central place for the unsolicited events of all pins, etc, and eventually include the jack-detect kcontrols that replace the current input-jack stuff. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound')
-rw-r--r--sound/pci/hda/Makefile2
-rw-r--r--sound/pci/hda/hda_codec.c40
-rw-r--r--sound/pci/hda/hda_codec.h3
-rw-r--r--sound/pci/hda/hda_jack.c148
-rw-r--r--sound/pci/hda/hda_jack.h63
-rw-r--r--sound/pci/hda/hda_local.h15
-rw-r--r--sound/pci/hda/patch_analog.c1
-rw-r--r--sound/pci/hda/patch_cirrus.c18
-rw-r--r--sound/pci/hda/patch_conexant.c20
-rw-r--r--sound/pci/hda/patch_hdmi.c6
-rw-r--r--sound/pci/hda/patch_realtek.c20
-rw-r--r--sound/pci/hda/patch_sigmatel.c46
-rw-r--r--sound/pci/hda/patch_via.c19
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 @@
1snd-hda-intel-objs := hda_intel.o 1snd-hda-intel-objs := hda_intel.o
2 2
3snd-hda-codec-y := hda_codec.o 3snd-hda-codec-y := hda_codec.o hda_jack.o
4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o 4snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o 5snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
6snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o 6snd-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}
1724EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps); 1725EXPORT_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 */
1734u32 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}
1747EXPORT_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 */
1756int 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}
1761EXPORT_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 */
20static 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 */
37struct hda_jack_tbl *
38snd_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}
50EXPORT_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 */
55struct hda_jack_tbl *
56snd_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
70void 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 */
76static 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 */
91void 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}
100EXPORT_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 */
110u32 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}
119EXPORT_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 */
128int 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}
133EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
134
135/**
136 * snd_hda_jack_detect_enable - enable the jack-detection
137 */
138int 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}
148EXPORT_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
15struct 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
21struct hda_jack_tbl *
22snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
23
24struct hda_jack_tbl *
25snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
26void 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 */
34static 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
42void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
43
44int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
45 unsigned int tag);
46
47u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
48int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
49
50static 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,
505u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid); 505u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
506int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid, 506int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
507 unsigned int caps); 507 unsigned int caps);
508u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
509int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
510
511static 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
33struct ad198x_spec { 34struct 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
1228static void cs_unsol_event(struct hda_codec *codec, unsigned int res) 1225static 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
1807static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) 1803static 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)
3756static 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)
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
3991static void cx_auto_init_output(struct hda_codec *codec) 3991static 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
40static bool static_hdmi_pcm; 41static bool static_hdmi_pcm;
41module_param(static_hdmi_pcm, bool, 0644); 42module_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
41enum { 42enum {
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
4798static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) 4797static 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
4806static 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
4851static 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
4859static 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
4865static int hp_blike_system(u32 subsystem_id); 4873static int hp_blike_system(u32 subsystem_id);
4866 4874
4867static void set_hp_led_gpio(struct hda_codec *codec) 4875static 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)
1708static void via_unsol_event(struct hda_codec *codec, 1709static 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])) {