diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-10-27 19:16:55 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-11-16 05:14:03 -0500 |
commit | 3a93897ea37cbb8277f8a4232c12c0c18168a7db (patch) | |
tree | 1c79df3bb270e86c61bdb13fab0bf66cbd3682ac | |
parent | 01a61e12b4602c82bde9797d0e153f3e53c95b04 (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>
-rw-r--r-- | sound/pci/hda/hda_jack.c | 61 | ||||
-rw-r--r-- | sound/pci/hda/hda_jack.h | 28 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 13 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 6 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 104 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 3 |
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) | |||
51 | EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get); | 51 | EXPORT_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 | */ | ||
56 | struct hda_jack_tbl * | ||
57 | snd_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 | } | ||
69 | EXPORT_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 | */ |
56 | struct hda_jack_tbl * | 74 | struct 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) | |||
77 | static void jack_detect_update(struct hda_codec *codec, | 96 | static 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 | */ |
143 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 162 | int 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 | } |
156 | EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); | 177 | EXPORT_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 | */ | ||
173 | void 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 | } | ||
180 | EXPORT_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 | */ |
185 | void snd_hda_jack_report_sync(struct hda_codec *codec) | 194 | void 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, | |||
251 | static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx, | 260 | static 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 | */ |
269 | int snd_hda_jack_add_kctls(struct hda_codec *codec, | 286 | int 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 | ||
15 | struct hda_jack_tbl { | 15 | struct 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 | ||
24 | struct hda_jack_tbl * | 28 | struct hda_jack_tbl * |
25 | snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); | 29 | snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid); |
30 | struct hda_jack_tbl * | ||
31 | snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag); | ||
26 | 32 | ||
27 | struct hda_jack_tbl * | 33 | struct hda_jack_tbl * |
28 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); | 34 | snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid); |
29 | void snd_hda_jack_tbl_clear(struct hda_codec *codec); | 35 | void 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 | */ |
37 | static inline void snd_hda_jack_set_dirty(struct hda_codec *codec, | 43 | static inline unsigned char |
38 | hda_nid_t nid) | 44 | snd_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 | ||
45 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec); | 54 | void snd_hda_jack_set_dirty_all(struct hda_codec *codec); |
46 | 55 | ||
47 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, | 56 | int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, |
48 | unsigned int tag); | 57 | unsigned char action); |
49 | 58 | ||
50 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); | 59 | u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid); |
51 | int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid); | 60 | int 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, | |||
68 | int snd_hda_jack_add_kctls(struct hda_codec *codec, | 77 | int 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 | ||
71 | void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid); | ||
72 | void snd_hda_jack_report_sync(struct hda_codec *codec); | 80 | void 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 | ||
1236 | static void cs_unsol_event(struct hda_codec *codec, unsigned int res) | 1236 | static 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 | ||
1825 | static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) | 1823 | static 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) | |||
3757 | 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) |
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 | ||
3984 | static void enable_unsol_pins(struct hda_codec *codec, int num_pins, | 3984 | static 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 | ||
3992 | static void cx_auto_init_output(struct hda_codec *codec) | 3992 | static 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); | |||
754 | static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res) | 754 | static 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 */ |
662 | static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res) | 663 | static 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) | |||
3896 | static void alc_auto_init_std(struct hda_codec *codec) | 3899 | static 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 | ||
180 | struct sigmatel_event { | ||
181 | hda_nid_t nid; | ||
182 | unsigned char type; | ||
183 | unsigned char tag; | ||
184 | int data; | ||
185 | }; | ||
186 | |||
187 | struct sigmatel_mic_route { | 180 | struct 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 | ||
4185 | static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid, | 4175 | static 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 | |||
4202 | static 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 | ||
4216 | static 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, | |||
4234 | static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid, | 4193 | static 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 | ||
4803 | static void handle_unsol_event(struct hda_codec *codec, | 4756 | static 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 | ||
4857 | static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid) | 4810 | static 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 | ||
4865 | static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res) | 4818 | static 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) | |||
1714 | static void via_unsol_event(struct hda_codec *codec, | 1714 | static 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); |