aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda
diff options
context:
space:
mode:
Diffstat (limited to 'sound/pci/hda')
-rw-r--r--sound/pci/hda/hda_jack.c168
-rw-r--r--sound/pci/hda/hda_jack.h12
-rw-r--r--sound/pci/hda/patch_cirrus.c27
-rw-r--r--sound/pci/hda/patch_conexant.c2
-rw-r--r--sound/pci/hda/patch_hdmi.c6
-rw-r--r--sound/pci/hda/patch_realtek.c7
-rw-r--r--sound/pci/hda/patch_sigmatel.c7
-rw-r--r--sound/pci/hda/patch_via.c7
8 files changed, 232 insertions, 4 deletions
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index 64b78a2e20e0..cee6a00bd85a 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -12,6 +12,7 @@
12#include <linux/init.h> 12#include <linux/init.h>
13#include <linux/slab.h> 13#include <linux/slab.h>
14#include <sound/core.h> 14#include <sound/core.h>
15#include <sound/control.h>
15#include "hda_codec.h" 16#include "hda_codec.h"
16#include "hda_local.h" 17#include "hda_local.h"
17#include "hda_jack.h" 18#include "hda_jack.h"
@@ -76,9 +77,13 @@ void snd_hda_jack_tbl_clear(struct hda_codec *codec)
76static void jack_detect_update(struct hda_codec *codec, 77static void jack_detect_update(struct hda_codec *codec,
77 struct hda_jack_tbl *jack) 78 struct hda_jack_tbl *jack)
78{ 79{
79 if (jack->jack_dirty) { 80 if (jack->jack_dirty || !jack->jack_cachable) {
80 jack->pin_sense = read_pin_sense(codec, jack->nid); 81 unsigned int val = read_pin_sense(codec, jack->nid);
81 jack->jack_dirty = 0; 82 jack->jack_dirty = 0;
83 if (val != jack->pin_sense) {
84 jack->need_notify = 1;
85 jack->pin_sense = val;
86 }
82 } 87 }
83} 88}
84 89
@@ -141,8 +146,167 @@ int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
141 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid); 146 struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
142 if (!jack) 147 if (!jack)
143 return -ENOMEM; 148 return -ENOMEM;
149 if (jack->jack_cachable)
150 return 0; /* already registered */
151 jack->jack_cachable = 1;
144 return snd_hda_codec_write_cache(codec, nid, 0, 152 return snd_hda_codec_write_cache(codec, nid, 0,
145 AC_VERB_SET_UNSOLICITED_ENABLE, 153 AC_VERB_SET_UNSOLICITED_ENABLE,
146 AC_USRSP_EN | tag); 154 AC_USRSP_EN | tag);
147} 155}
148EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable); 156EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
157
158/* queue the notification when needed */
159static void jack_detect_report(struct hda_codec *codec,
160 struct hda_jack_tbl *jack)
161{
162 jack_detect_update(codec, jack);
163 if (jack->need_notify) {
164 snd_ctl_notify(codec->bus->card, SNDRV_CTL_EVENT_MASK_VALUE,
165 &jack->kctl->id);
166 jack->need_notify = 0;
167 }
168}
169
170/**
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
184 */
185void snd_hda_jack_report_sync(struct hda_codec *codec)
186{
187 struct hda_jack_tbl *jack = codec->jacktbl.list;
188 int i;
189
190 for (i = 0; i < codec->jacktbl.used; i++, jack++)
191 if (jack->nid) {
192 jack_detect_update(codec, jack);
193 jack_detect_report(codec, jack);
194 }
195}
196EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
197
198/*
199 * jack-detection kcontrols
200 */
201
202#define jack_detect_kctl_info snd_ctl_boolean_mono_info
203
204static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
205 struct snd_ctl_elem_value *ucontrol)
206{
207 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
208 hda_nid_t nid = kcontrol->private_value;
209
210 ucontrol->value.integer.value[0] = snd_hda_jack_detect(codec, nid);
211 return 0;
212}
213
214static struct snd_kcontrol_new jack_detect_kctl = {
215 /* name is filled later */
216 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
217 .access = SNDRV_CTL_ELEM_ACCESS_READ,
218 .info = jack_detect_kctl_info,
219 .get = jack_detect_kctl_get,
220};
221
222/**
223 * snd_hda_jack_add_kctl - Add a kctl for the given pin
224 *
225 * This assigns a jack-detection kctl to the given pin. The kcontrol
226 * will have the given name and index.
227 */
228int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
229 const char *name, int idx)
230{
231 struct hda_jack_tbl *jack;
232 struct snd_kcontrol *kctl;
233
234 jack = snd_hda_jack_tbl_get(codec, nid);
235 if (!jack)
236 return 0;
237 if (jack->kctl)
238 return 0; /* already created */
239 kctl = snd_ctl_new1(&jack_detect_kctl, codec);
240 if (!kctl)
241 return -ENOMEM;
242 snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
243 kctl->id.index = idx;
244 kctl->private_value = nid;
245 if (snd_hda_ctl_add(codec, nid, kctl) < 0)
246 return -ENOMEM;
247 jack->kctl = kctl;
248 return 0;
249}
250
251static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, int idx,
252 const struct auto_pin_cfg *cfg)
253{
254 if (!nid)
255 return 0;
256 if (!is_jack_detectable(codec, nid))
257 return 0;
258 return snd_hda_jack_add_kctl(codec, nid,
259 snd_hda_get_pin_label(codec, nid, cfg),
260 idx);
261}
262
263/**
264 * 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 */
269int snd_hda_jack_add_kctls(struct hda_codec *codec,
270 const struct auto_pin_cfg *cfg)
271{
272 const hda_nid_t *p;
273 int i, err;
274
275 for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
276 err = add_jack_kctl(codec, *p, i, cfg);
277 if (err < 0)
278 return err;
279 }
280 for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
281 if (*p == *cfg->line_out_pins) /* might be duplicated */
282 break;
283 err = add_jack_kctl(codec, *p, i, cfg);
284 if (err < 0)
285 return err;
286 }
287 for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
288 if (*p == *cfg->line_out_pins) /* might be duplicated */
289 break;
290 err = add_jack_kctl(codec, *p, i, cfg);
291 if (err < 0)
292 return err;
293 }
294 for (i = 0; i < cfg->num_inputs; i++) {
295 err = add_jack_kctl(codec, cfg->inputs[i].pin, 0, cfg);
296 if (err < 0)
297 return err;
298 }
299 for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
300 err = add_jack_kctl(codec, *p, i, cfg);
301 if (err < 0)
302 return err;
303 }
304 err = add_jack_kctl(codec, cfg->dig_in_pin, 0, cfg);
305 if (err < 0)
306 return err;
307 err = add_jack_kctl(codec, cfg->mono_out_pin, 0, cfg);
308 if (err < 0)
309 return err;
310 return 0;
311}
312EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 5c1bcb8cf565..b5983eaea51e 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -15,7 +15,10 @@
15struct hda_jack_tbl { 15struct hda_jack_tbl {
16 hda_nid_t nid; 16 hda_nid_t nid;
17 unsigned int pin_sense; /* cached pin-sense value */ 17 unsigned int pin_sense; /* cached pin-sense value */
18 unsigned int jack_cachable:1; /* can be updated via unsol events */
18 unsigned int jack_dirty:1; /* needs to update? */ 19 unsigned int jack_dirty:1; /* needs to update? */
20 unsigned int need_notify:1; /* to be notified? */
21 struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
19}; 22};
20 23
21struct hda_jack_tbl * 24struct hda_jack_tbl *
@@ -60,4 +63,13 @@ static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
60 return true; 63 return true;
61} 64}
62 65
66int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
67 const char *name, int idx);
68int snd_hda_jack_add_kctls(struct hda_codec *codec,
69 const struct auto_pin_cfg *cfg);
70
71void snd_hda_jack_report(struct hda_codec *codec, hda_nid_t nid);
72void snd_hda_jack_report_sync(struct hda_codec *codec);
73
74
63#endif /* __SOUND_HDA_JACK_H */ 75#endif /* __SOUND_HDA_JACK_H */
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index 6f158777f71a..135fd49cd49d 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -1192,11 +1192,14 @@ static int cs_init(struct hda_codec *codec)
1192 init_output(codec); 1192 init_output(codec);
1193 init_input(codec); 1193 init_input(codec);
1194 init_digital(codec); 1194 init_digital(codec);
1195 snd_hda_jack_report_sync(codec);
1196
1195 return 0; 1197 return 0;
1196} 1198}
1197 1199
1198static int cs_build_controls(struct hda_codec *codec) 1200static int cs_build_controls(struct hda_codec *codec)
1199{ 1201{
1202 struct cs_spec *spec = codec->spec;
1200 int err; 1203 int err;
1201 1204
1202 err = build_output(codec); 1205 err = build_output(codec);
@@ -1211,7 +1214,15 @@ static int cs_build_controls(struct hda_codec *codec)
1211 err = build_digital_input(codec); 1214 err = build_digital_input(codec);
1212 if (err < 0) 1215 if (err < 0)
1213 return err; 1216 return err;
1214 return cs_init(codec); 1217 err = cs_init(codec);
1218 if (err < 0)
1219 return err;
1220
1221 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1222 if (err < 0)
1223 return err;
1224
1225 return 0;
1215} 1226}
1216 1227
1217static void cs_free(struct hda_codec *codec) 1228static void cs_free(struct hda_codec *codec)
@@ -1234,6 +1245,7 @@ static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
1234 cs_automic(codec); 1245 cs_automic(codec);
1235 break; 1246 break;
1236 } 1247 }
1248 snd_hda_jack_report_sync(codec);
1237} 1249}
1238 1250
1239static const struct hda_codec_ops cs_patch_ops = { 1251static const struct hda_codec_ops cs_patch_ops = {
@@ -1611,6 +1623,7 @@ static int cs421x_init(struct hda_codec *codec)
1611 init_output(codec); 1623 init_output(codec);
1612 init_input(codec); 1624 init_input(codec);
1613 init_cs421x_digital(codec); 1625 init_cs421x_digital(codec);
1626 snd_hda_jack_report_sync(codec);
1614 1627
1615 return 0; 1628 return 0;
1616} 1629}
@@ -1786,6 +1799,7 @@ static int build_cs421x_output(struct hda_codec *codec)
1786 1799
1787static int cs421x_build_controls(struct hda_codec *codec) 1800static int cs421x_build_controls(struct hda_codec *codec)
1788{ 1801{
1802 struct cs_spec *spec = codec->spec;
1789 int err; 1803 int err;
1790 1804
1791 err = build_cs421x_output(codec); 1805 err = build_cs421x_output(codec);
@@ -1797,7 +1811,15 @@ static int cs421x_build_controls(struct hda_codec *codec)
1797 err = build_digital_output(codec); 1811 err = build_digital_output(codec);
1798 if (err < 0) 1812 if (err < 0)
1799 return err; 1813 return err;
1800 return cs421x_init(codec); 1814 err = cs421x_init(codec);
1815 if (err < 0)
1816 return err;
1817
1818 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1819 if (err < 0)
1820 return err;
1821
1822 return 0;
1801} 1823}
1802 1824
1803static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res) 1825static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
@@ -1814,6 +1836,7 @@ static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
1814 cs_automic(codec); 1836 cs_automic(codec);
1815 break; 1837 break;
1816 } 1838 }
1839 snd_hda_jack_report_sync(codec);
1817} 1840}
1818 1841
1819static int parse_cs421x_input(struct hda_codec *codec) 1842static int parse_cs421x_input(struct hda_codec *codec)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 220e567ccfff..25fdd1e9561f 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -3770,6 +3770,7 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
3770 snd_hda_input_jack_report(codec, nid); 3770 snd_hda_input_jack_report(codec, nid);
3771 break; 3771 break;
3772 } 3772 }
3773 snd_hda_jack_report_sync(codec);
3773} 3774}
3774 3775
3775/* check whether the pin config is suitable for auto-mic switching; 3776/* check whether the pin config is suitable for auto-mic switching;
@@ -4095,6 +4096,7 @@ static int cx_auto_init(struct hda_codec *codec)
4095 cx_auto_init_output(codec); 4096 cx_auto_init_output(codec);
4096 cx_auto_init_input(codec); 4097 cx_auto_init_input(codec);
4097 cx_auto_init_digital(codec); 4098 cx_auto_init_digital(codec);
4099 snd_hda_jack_report_sync(codec);
4098 return 0; 4100 return 0;
4099} 4101}
4100 4102
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index ea6d85d48444..f01c5efde8e1 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -769,6 +769,7 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
769 769
770 snd_hda_jack_set_dirty(codec, pin_nid); 770 snd_hda_jack_set_dirty(codec, pin_nid);
771 hdmi_present_sense(&spec->pins[pin_idx], true); 771 hdmi_present_sense(&spec->pins[pin_idx], true);
772 snd_hda_jack_report_sync(codec);
772} 773}
773 774
774static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res) 775static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -1268,6 +1269,10 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
1268 1269
1269 if (err < 0) 1270 if (err < 0)
1270 return err; 1271 return err;
1272 err = snd_hda_jack_add_kctl(codec, per_pin->pin_nid,
1273 "HDMI", pin_idx);
1274 if (err < 0)
1275 return err;
1271 } 1276 }
1272 1277
1273 return 0; 1278 return 0;
@@ -1290,6 +1295,7 @@ static int generic_hdmi_init(struct hda_codec *codec)
1290 INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld); 1295 INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
1291 snd_hda_eld_proc_new(codec, eld, pin_idx); 1296 snd_hda_eld_proc_new(codec, eld, pin_idx);
1292 } 1297 }
1298 snd_hda_jack_report_sync(codec);
1293 return 0; 1299 return 0;
1294} 1300}
1295 1301
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index da9d2276e68b..04beae034fea 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -677,6 +677,7 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
677 alc_mic_automute(codec); 677 alc_mic_automute(codec);
678 break; 678 break;
679 } 679 }
680 snd_hda_jack_report_sync(codec);
680} 681}
681 682
682/* call init functions of standard auto-mute helpers */ 683/* call init functions of standard auto-mute helpers */
@@ -2054,6 +2055,10 @@ static int alc_build_controls(struct hda_codec *codec)
2054 2055
2055 alc_free_kctls(codec); /* no longer needed */ 2056 alc_free_kctls(codec); /* no longer needed */
2056 2057
2058 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
2059 if (err < 0)
2060 return err;
2061
2057 return 0; 2062 return 0;
2058} 2063}
2059 2064
@@ -2081,6 +2086,8 @@ static int alc_init(struct hda_codec *codec)
2081 2086
2082 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT); 2087 alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
2083 2088
2089 snd_hda_jack_report_sync(codec);
2090
2084 hda_call_check_power_status(codec, 0x01); 2091 hda_call_check_power_status(codec, 0x01);
2085 return 0; 2092 return 0;
2086} 2093}
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 97c6df9db5e9..90954b8269c3 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -1212,6 +1212,10 @@ static int stac92xx_build_controls(struct hda_codec *codec)
1212 return err; 1212 return err;
1213 } 1213 }
1214 1214
1215 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1216 if (err < 0)
1217 return err;
1218
1215 return 0; 1219 return 0;
1216} 1220}
1217 1221
@@ -4473,6 +4477,8 @@ static int stac92xx_init(struct hda_codec *codec)
4473 stac_toggle_power_map(codec, nid, 0); 4477 stac_toggle_power_map(codec, nid, 0);
4474 } 4478 }
4475 4479
4480 snd_hda_jack_report_sync(codec);
4481
4476 /* sync mute LED */ 4482 /* sync mute LED */
4477 if (spec->gpio_led) 4483 if (spec->gpio_led)
4478 hda_call_check_power_status(codec, 0x01); 4484 hda_call_check_power_status(codec, 0x01);
@@ -4868,6 +4874,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
4868 return; 4874 return;
4869 snd_hda_jack_set_dirty(codec, event->nid); 4875 snd_hda_jack_set_dirty(codec, event->nid);
4870 handle_unsol_event(codec, event); 4876 handle_unsol_event(codec, event);
4877 snd_hda_jack_report_sync(codec);
4871} 4878}
4872 4879
4873static int hp_blike_system(u32 subsystem_id); 4880static int hp_blike_system(u32 subsystem_id);
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 3467d0c23fe9..852939658ddb 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -1500,6 +1500,11 @@ static int via_build_controls(struct hda_codec *codec)
1500 analog_low_current_mode(codec); 1500 analog_low_current_mode(codec);
1501 1501
1502 via_free_kctls(codec); /* no longer needed */ 1502 via_free_kctls(codec); /* no longer needed */
1503
1504 err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
1505 if (err < 0)
1506 return err;
1507
1503 return 0; 1508 return 0;
1504} 1509}
1505 1510
@@ -1722,6 +1727,7 @@ static void via_unsol_event(struct hda_codec *codec,
1722 via_hp_automute(codec); 1727 via_hp_automute(codec);
1723 else if (res == VIA_GPIO_EVENT) 1728 else if (res == VIA_GPIO_EVENT)
1724 via_gpio_control(codec); 1729 via_gpio_control(codec);
1730 snd_hda_jack_report_sync(codec);
1725} 1731}
1726 1732
1727#ifdef CONFIG_PM 1733#ifdef CONFIG_PM
@@ -2771,6 +2777,7 @@ static int via_init(struct hda_codec *codec)
2771 via_auto_init_unsol_event(codec); 2777 via_auto_init_unsol_event(codec);
2772 2778
2773 via_hp_automute(codec); 2779 via_hp_automute(codec);
2780 snd_hda_jack_report_sync(codec);
2774 2781
2775 return 0; 2782 return 0;
2776} 2783}