Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Jack-detection handling for HD-audio
4 : : *
5 : : * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
6 : : */
7 : :
8 : : #include <linux/init.h>
9 : : #include <linux/slab.h>
10 : : #include <linux/export.h>
11 : : #include <sound/core.h>
12 : : #include <sound/control.h>
13 : : #include <sound/jack.h>
14 : : #include <sound/hda_codec.h>
15 : : #include "hda_local.h"
16 : : #include "hda_auto_parser.h"
17 : : #include "hda_jack.h"
18 : :
19 : : /**
20 : : * is_jack_detectable - Check whether the given pin is jack-detectable
21 : : * @codec: the HDA codec
22 : : * @nid: pin NID
23 : : *
24 : : * Check whether the given pin is capable to report the jack detection.
25 : : * The jack detection might not work by various reasons, e.g. the jack
26 : : * detection is prohibited in the codec level, the pin config has
27 : : * AC_DEFCFG_MISC_NO_PRESENCE bit, no unsol support, etc.
28 : : */
29 : 0 : bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
30 : : {
31 [ # # ]: 0 : if (codec->no_jack_detect)
32 : : return false;
33 [ # # ]: 0 : if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
34 : : return false;
35 [ # # ]: 0 : if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
36 : : AC_DEFCFG_MISC_NO_PRESENCE)
37 : : return false;
38 [ # # # # ]: 0 : if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) &&
39 [ # # ]: 0 : !codec->jackpoll_interval)
40 : 0 : return false;
41 : : return true;
42 : : }
43 : : EXPORT_SYMBOL_GPL(is_jack_detectable);
44 : :
45 : : /* execute pin sense measurement */
46 : 0 : static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
47 : : {
48 : 0 : u32 pincap;
49 : 0 : u32 val;
50 : :
51 [ # # ]: 0 : if (!codec->no_trigger_sense) {
52 : 0 : pincap = snd_hda_query_pin_caps(codec, nid);
53 [ # # ]: 0 : if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
54 : 0 : snd_hda_codec_read(codec, nid, 0,
55 : : AC_VERB_SET_PIN_SENSE, 0);
56 : : }
57 : 0 : val = snd_hda_codec_read(codec, nid, 0,
58 : : AC_VERB_GET_PIN_SENSE, dev_id);
59 [ # # ]: 0 : if (codec->inv_jack_detect)
60 : 0 : val ^= AC_PINSENSE_PRESENCE;
61 : 0 : return val;
62 : : }
63 : :
64 : : /**
65 : : * snd_hda_jack_tbl_get_mst - query the jack-table entry for the given NID
66 : : * @codec: the HDA codec
67 : : * @nid: pin NID to refer to
68 : : * @dev_id: pin device entry id
69 : : */
70 : : struct hda_jack_tbl *
71 : 0 : snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
72 : : {
73 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
74 : 0 : int i;
75 : :
76 [ # # ]: 0 : if (!nid || !jack)
77 : : return NULL;
78 [ # # # # : 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
# # # # #
# # # ]
79 [ # # # # : 0 : if (jack->nid == nid && jack->dev_id == dev_id)
# # # # #
# # # # #
# # # # #
# # # #
# ]
80 : 0 : return jack;
81 : : return NULL;
82 : : }
83 : : EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_mst);
84 : :
85 : : /**
86 : : * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
87 : : * @codec: the HDA codec
88 : : * @tag: tag value to refer to
89 : : * @dev_id: pin device entry id
90 : : */
91 : : struct hda_jack_tbl *
92 : 0 : snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
93 : : unsigned char tag, int dev_id)
94 : : {
95 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
96 : 0 : int i;
97 : :
98 [ # # ]: 0 : if (!tag || !jack)
99 : : return NULL;
100 [ # # # # : 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
# # ]
101 [ # # # # : 0 : if (jack->tag == tag && jack->dev_id == dev_id)
# # # # #
# # # ]
102 : 0 : return jack;
103 : : return NULL;
104 : : }
105 : : EXPORT_SYMBOL_GPL(snd_hda_jack_tbl_get_from_tag);
106 : :
107 : : static struct hda_jack_tbl *
108 : 0 : any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid)
109 : : {
110 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
111 : 0 : int i;
112 : :
113 : 0 : if (!nid || !jack)
114 : : return NULL;
115 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
116 [ # # ]: 0 : if (jack->nid == nid)
117 : : return jack;
118 : : return NULL;
119 : : }
120 : :
121 : : /**
122 : : * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
123 : : * @codec: the HDA codec
124 : : * @nid: pin NID to assign
125 : : * @dev_id: pin device entry id
126 : : */
127 : : static struct hda_jack_tbl *
128 : 0 : snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id)
129 : : {
130 [ # # ]: 0 : struct hda_jack_tbl *jack =
131 : : snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
132 [ # # ]: 0 : struct hda_jack_tbl *existing_nid_jack =
133 : : any_jack_tbl_get_from_nid(codec, nid);
134 : :
135 [ # # # # : 0 : WARN_ON(dev_id != 0 && !codec->dp_mst);
# # ]
136 : :
137 [ # # ]: 0 : if (jack)
138 : : return jack;
139 : 0 : jack = snd_array_new(&codec->jacktbl);
140 [ # # ]: 0 : if (!jack)
141 : : return NULL;
142 : 0 : jack->nid = nid;
143 : 0 : jack->dev_id = dev_id;
144 : 0 : jack->jack_dirty = 1;
145 [ # # ]: 0 : if (existing_nid_jack) {
146 : 0 : jack->tag = existing_nid_jack->tag;
147 : :
148 : : /*
149 : : * Copy jack_detect from existing_nid_jack to avoid
150 : : * snd_hda_jack_detect_enable_callback_mst() making multiple
151 : : * SET_UNSOLICITED_ENABLE calls on the same pin.
152 : : */
153 : 0 : jack->jack_detect = existing_nid_jack->jack_detect;
154 : : } else {
155 : 0 : jack->tag = codec->jacktbl.used;
156 : : }
157 : :
158 : : return jack;
159 : : }
160 : :
161 : 0 : void snd_hda_jack_tbl_clear(struct hda_codec *codec)
162 : : {
163 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
164 : 0 : int i;
165 : :
166 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++) {
167 : 0 : struct hda_jack_callback *cb, *next;
168 : :
169 : : /* free jack instances manually when clearing/reconfiguring */
170 [ # # # # ]: 0 : if (!codec->bus->shutdown && jack->jack)
171 : 0 : snd_device_free(codec->card, jack->jack);
172 : :
173 [ # # ]: 0 : for (cb = jack->callback; cb; cb = next) {
174 : 0 : next = cb->next;
175 : 0 : kfree(cb);
176 : : }
177 : : }
178 : 0 : snd_array_free(&codec->jacktbl);
179 : 0 : }
180 : :
181 : : #define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
182 : :
183 : : /* update the cached value and notification flag if needed */
184 : 0 : static void jack_detect_update(struct hda_codec *codec,
185 : : struct hda_jack_tbl *jack)
186 : : {
187 [ # # ]: 0 : if (!jack->jack_dirty)
188 : : return;
189 : :
190 [ # # ]: 0 : if (jack->phantom_jack)
191 : 0 : jack->pin_sense = AC_PINSENSE_PRESENCE;
192 : : else
193 : 0 : jack->pin_sense = read_pin_sense(codec, jack->nid,
194 : : jack->dev_id);
195 : :
196 : : /* A gating jack indicates the jack is invalid if gating is unplugged */
197 [ # # # # ]: 0 : if (jack->gating_jack &&
198 : 0 : !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id))
199 : 0 : jack->pin_sense &= ~AC_PINSENSE_PRESENCE;
200 : :
201 : 0 : jack->jack_dirty = 0;
202 : :
203 : : /* If a jack is gated by this one update it. */
204 [ # # ]: 0 : if (jack->gated_jack) {
205 : 0 : struct hda_jack_tbl *gated =
206 [ # # ]: 0 : snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
207 : : jack->dev_id);
208 [ # # ]: 0 : if (gated) {
209 : 0 : gated->jack_dirty = 1;
210 : 0 : jack_detect_update(codec, gated);
211 : : }
212 : : }
213 : : }
214 : :
215 : : /**
216 : : * snd_hda_set_dirty_all - Mark all the cached as dirty
217 : : * @codec: the HDA codec
218 : : *
219 : : * This function sets the dirty flag to all entries of jack table.
220 : : * It's called from the resume path in hda_codec.c.
221 : : */
222 : 0 : void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
223 : : {
224 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
225 : 0 : int i;
226 : :
227 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
228 [ # # ]: 0 : if (jack->nid)
229 : 0 : jack->jack_dirty = 1;
230 : 0 : }
231 : : EXPORT_SYMBOL_GPL(snd_hda_jack_set_dirty_all);
232 : :
233 : : /**
234 : : * snd_hda_jack_pin_sense - execute pin sense measurement
235 : : * @codec: the CODEC to sense
236 : : * @nid: the pin NID to sense
237 : : * @dev_id: pin device entry id
238 : : *
239 : : * Execute necessary pin sense measurement and return its Presence Detect,
240 : : * Impedance, ELD Valid etc. status bits.
241 : : */
242 : 0 : u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
243 : : {
244 : 0 : struct hda_jack_tbl *jack =
245 [ # # ]: 0 : snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
246 [ # # ]: 0 : if (jack) {
247 : 0 : jack_detect_update(codec, jack);
248 : 0 : return jack->pin_sense;
249 : : }
250 : 0 : return read_pin_sense(codec, nid, dev_id);
251 : : }
252 : : EXPORT_SYMBOL_GPL(snd_hda_jack_pin_sense);
253 : :
254 : : /**
255 : : * snd_hda_jack_detect_state_mst - query pin Presence Detect status
256 : : * @codec: the CODEC to sense
257 : : * @nid: the pin NID to sense
258 : : * @dev_id: pin device entry id
259 : : *
260 : : * Query and return the pin's Presence Detect status, as either
261 : : * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
262 : : */
263 : 0 : int snd_hda_jack_detect_state_mst(struct hda_codec *codec,
264 : : hda_nid_t nid, int dev_id)
265 : : {
266 : 0 : struct hda_jack_tbl *jack =
267 [ # # ]: 0 : snd_hda_jack_tbl_get_mst(codec, nid, dev_id);
268 [ # # # # ]: 0 : if (jack && jack->phantom_jack)
269 : : return HDA_JACK_PHANTOM;
270 [ # # ]: 0 : else if (snd_hda_jack_pin_sense(codec, nid, dev_id) &
271 : : AC_PINSENSE_PRESENCE)
272 : : return HDA_JACK_PRESENT;
273 : : else
274 : 0 : return HDA_JACK_NOT_PRESENT;
275 : : }
276 : : EXPORT_SYMBOL_GPL(snd_hda_jack_detect_state_mst);
277 : :
278 : : /**
279 : : * snd_hda_jack_detect_enable_mst - enable the jack-detection
280 : : * @codec: the HDA codec
281 : : * @nid: pin NID to enable
282 : : * @func: callback function to register
283 : : * @dev_id: pin device entry id
284 : : *
285 : : * In the case of error, the return value will be a pointer embedded with
286 : : * errno. Check and handle the return value appropriately with standard
287 : : * macros such as @IS_ERR() and @PTR_ERR().
288 : : */
289 : : struct hda_jack_callback *
290 : 0 : snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
291 : : int dev_id, hda_jack_callback_fn func)
292 : : {
293 : 0 : struct hda_jack_tbl *jack;
294 : 0 : struct hda_jack_callback *callback = NULL;
295 : 0 : int err;
296 : :
297 : 0 : jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
298 [ # # ]: 0 : if (!jack)
299 : : return ERR_PTR(-ENOMEM);
300 [ # # ]: 0 : if (func) {
301 : 0 : callback = kzalloc(sizeof(*callback), GFP_KERNEL);
302 [ # # ]: 0 : if (!callback)
303 : : return ERR_PTR(-ENOMEM);
304 : 0 : callback->func = func;
305 : 0 : callback->nid = jack->nid;
306 : 0 : callback->dev_id = jack->dev_id;
307 : 0 : callback->next = jack->callback;
308 : 0 : jack->callback = callback;
309 : : }
310 : :
311 [ # # ]: 0 : if (jack->jack_detect)
312 : : return callback; /* already registered */
313 : 0 : jack->jack_detect = 1;
314 [ # # ]: 0 : if (codec->jackpoll_interval > 0)
315 : : return callback; /* No unsol if we're polling instead */
316 : 0 : err = snd_hda_codec_write_cache(codec, nid, 0,
317 : : AC_VERB_SET_UNSOLICITED_ENABLE,
318 : 0 : AC_USRSP_EN | jack->tag);
319 [ # # ]: 0 : if (err < 0)
320 : 0 : return ERR_PTR(err);
321 : : return callback;
322 : : }
323 : : EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable_callback_mst);
324 : :
325 : : /**
326 : : * snd_hda_jack_detect_enable - Enable the jack detection on the given pin
327 : : * @codec: the HDA codec
328 : : * @nid: pin NID to enable jack detection
329 : : * @dev_id: pin device entry id
330 : : *
331 : : * Enable the jack detection with the default callback. Returns zero if
332 : : * successful or a negative error code.
333 : : */
334 : 0 : int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
335 : : int dev_id)
336 : : {
337 : 0 : return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback_mst(codec,
338 : : nid,
339 : : dev_id,
340 : : NULL));
341 : : }
342 : : EXPORT_SYMBOL_GPL(snd_hda_jack_detect_enable);
343 : :
344 : : /**
345 : : * snd_hda_jack_set_gating_jack - Set gating jack.
346 : : * @codec: the HDA codec
347 : : * @gated_nid: gated pin NID
348 : : * @gating_nid: gating pin NID
349 : : *
350 : : * Indicates the gated jack is only valid when the gating jack is plugged.
351 : : */
352 : 0 : int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
353 : : hda_nid_t gating_nid)
354 : : {
355 : 0 : struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid, 0);
356 : 0 : struct hda_jack_tbl *gating =
357 : 0 : snd_hda_jack_tbl_new(codec, gating_nid, 0);
358 : :
359 [ # # ]: 0 : WARN_ON(codec->dp_mst);
360 : :
361 [ # # ]: 0 : if (!gated || !gating)
362 : : return -EINVAL;
363 : :
364 : 0 : gated->gating_jack = gating_nid;
365 : 0 : gating->gated_jack = gated_nid;
366 : :
367 : 0 : return 0;
368 : : }
369 : : EXPORT_SYMBOL_GPL(snd_hda_jack_set_gating_jack);
370 : :
371 : : /**
372 : : * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
373 : : * @codec: the HDA codec
374 : : */
375 : 0 : void snd_hda_jack_report_sync(struct hda_codec *codec)
376 : : {
377 : 0 : struct hda_jack_tbl *jack;
378 : 0 : int i, state;
379 : :
380 : : /* update all jacks at first */
381 : 0 : jack = codec->jacktbl.list;
382 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
383 [ # # ]: 0 : if (jack->nid)
384 : 0 : jack_detect_update(codec, jack);
385 : :
386 : : /* report the updated jacks; it's done after updating all jacks
387 : : * to make sure that all gating jacks properly have been set
388 : : */
389 : 0 : jack = codec->jacktbl.list;
390 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++)
391 [ # # ]: 0 : if (jack->nid) {
392 [ # # # # ]: 0 : if (!jack->jack || jack->block_report)
393 : 0 : continue;
394 : 0 : state = jack->button_state;
395 [ # # ]: 0 : if (get_jack_plug_state(jack->pin_sense))
396 : 0 : state |= jack->type;
397 : 0 : snd_jack_report(jack->jack, state);
398 [ # # ]: 0 : if (jack->button_state) {
399 : 0 : snd_jack_report(jack->jack,
400 : 0 : state & ~jack->button_state);
401 : 0 : jack->button_state = 0; /* button released */
402 : : }
403 : : }
404 : 0 : }
405 : : EXPORT_SYMBOL_GPL(snd_hda_jack_report_sync);
406 : :
407 : : /* guess the jack type from the pin-config */
408 : 0 : static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
409 : : {
410 : 0 : unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
411 [ # # ]: 0 : switch (get_defcfg_device(def_conf)) {
412 : : case AC_JACK_LINE_OUT:
413 : : case AC_JACK_SPEAKER:
414 : : return SND_JACK_LINEOUT;
415 : : case AC_JACK_HP_OUT:
416 : : return SND_JACK_HEADPHONE;
417 : : case AC_JACK_SPDIF_OUT:
418 : : case AC_JACK_DIG_OTHER_OUT:
419 : : return SND_JACK_AVOUT;
420 : : case AC_JACK_MIC_IN:
421 : : return SND_JACK_MICROPHONE;
422 : : default:
423 : : return SND_JACK_LINEIN;
424 : : }
425 : : }
426 : :
427 : 0 : static void hda_free_jack_priv(struct snd_jack *jack)
428 : : {
429 : 0 : struct hda_jack_tbl *jacks = jack->private_data;
430 : 0 : jacks->nid = 0;
431 : 0 : jacks->jack = NULL;
432 : 0 : }
433 : :
434 : : /**
435 : : * snd_hda_jack_add_kctl_mst - Add a kctl for the given pin
436 : : * @codec: the HDA codec
437 : : * @nid: pin NID to assign
438 : : * @dev_id : pin device entry id
439 : : * @name: string name for the jack
440 : : * @phantom_jack: flag to deal as a phantom jack
441 : : * @type: jack type bits to be reported, 0 for guessing from pincfg
442 : : * @keymap: optional jack / key mapping
443 : : *
444 : : * This assigns a jack-detection kctl to the given pin. The kcontrol
445 : : * will have the given name and index.
446 : : */
447 : 0 : int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
448 : : int dev_id, const char *name, bool phantom_jack,
449 : : int type, const struct hda_jack_keymap *keymap)
450 : : {
451 : 0 : struct hda_jack_tbl *jack;
452 : 0 : const struct hda_jack_keymap *map;
453 : 0 : int err, state, buttons;
454 : :
455 : 0 : jack = snd_hda_jack_tbl_new(codec, nid, dev_id);
456 [ # # ]: 0 : if (!jack)
457 : : return 0;
458 [ # # ]: 0 : if (jack->jack)
459 : : return 0; /* already created */
460 : :
461 [ # # ]: 0 : if (!type)
462 : 0 : type = get_input_jack_type(codec, nid);
463 : :
464 : 0 : buttons = 0;
465 [ # # ]: 0 : if (keymap) {
466 [ # # ]: 0 : for (map = keymap; map->type; map++)
467 : 0 : buttons |= map->type;
468 : : }
469 : :
470 : 0 : err = snd_jack_new(codec->card, name, type | buttons,
471 : : &jack->jack, true, phantom_jack);
472 [ # # ]: 0 : if (err < 0)
473 : : return err;
474 : :
475 : 0 : jack->phantom_jack = !!phantom_jack;
476 : 0 : jack->type = type;
477 : 0 : jack->button_state = 0;
478 : 0 : jack->jack->private_data = jack;
479 : 0 : jack->jack->private_free = hda_free_jack_priv;
480 [ # # ]: 0 : if (keymap) {
481 [ # # ]: 0 : for (map = keymap; map->type; map++)
482 : 0 : snd_jack_set_key(jack->jack, map->type, map->key);
483 : : }
484 : :
485 : 0 : state = snd_hda_jack_detect_mst(codec, nid, dev_id);
486 [ # # ]: 0 : snd_jack_report(jack->jack, state ? jack->type : 0);
487 : :
488 : 0 : return 0;
489 : : }
490 : : EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctl_mst);
491 : :
492 : 0 : static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
493 : : const struct auto_pin_cfg *cfg,
494 : : const char *base_name)
495 : : {
496 : 0 : unsigned int def_conf, conn;
497 : 0 : char name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
498 : 0 : int err;
499 : 0 : bool phantom_jack;
500 : :
501 [ # # ]: 0 : WARN_ON(codec->dp_mst);
502 : :
503 [ # # ]: 0 : if (!nid)
504 : : return 0;
505 : 0 : def_conf = snd_hda_codec_get_pincfg(codec, nid);
506 : 0 : conn = get_defcfg_connect(def_conf);
507 [ # # ]: 0 : if (conn == AC_JACK_PORT_NONE)
508 : : return 0;
509 [ # # # # ]: 0 : phantom_jack = (conn != AC_JACK_PORT_COMPLEX) ||
510 : 0 : !is_jack_detectable(codec, nid);
511 : :
512 [ # # ]: 0 : if (base_name)
513 : 0 : strlcpy(name, base_name, sizeof(name));
514 : : else
515 : 0 : snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL);
516 [ # # ]: 0 : if (phantom_jack)
517 : : /* Example final name: "Internal Mic Phantom Jack" */
518 : 0 : strncat(name, " Phantom", sizeof(name) - strlen(name) - 1);
519 : 0 : err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL);
520 [ # # ]: 0 : if (err < 0)
521 : : return err;
522 : :
523 [ # # ]: 0 : if (!phantom_jack)
524 : 0 : return snd_hda_jack_detect_enable(codec, nid, 0);
525 : : return 0;
526 : : }
527 : :
528 : : /**
529 : : * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
530 : : * @codec: the HDA codec
531 : : * @cfg: pin config table to parse
532 : : */
533 : 0 : int snd_hda_jack_add_kctls(struct hda_codec *codec,
534 : : const struct auto_pin_cfg *cfg)
535 : : {
536 : 0 : const hda_nid_t *p;
537 : 0 : int i, err;
538 : :
539 [ # # ]: 0 : for (i = 0; i < cfg->num_inputs; i++) {
540 : : /* If we have headphone mics; make sure they get the right name
541 : : before grabbed by output pins */
542 [ # # ]: 0 : if (cfg->inputs[i].is_headphone_mic) {
543 [ # # # # ]: 0 : if (auto_cfg_hp_outs(cfg) == 1)
544 [ # # ]: 0 : err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0],
545 : : cfg, "Headphone Mic");
546 : : else
547 : 0 : err = add_jack_kctl(codec, cfg->inputs[i].pin,
548 : : cfg, "Headphone Mic");
549 : : } else
550 : 0 : err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg,
551 : : NULL);
552 [ # # ]: 0 : if (err < 0)
553 : 0 : return err;
554 : : }
555 : :
556 [ # # ]: 0 : for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
557 : 0 : err = add_jack_kctl(codec, *p, cfg, NULL);
558 [ # # ]: 0 : if (err < 0)
559 : 0 : return err;
560 : : }
561 [ # # ]: 0 : for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
562 [ # # ]: 0 : if (*p == *cfg->line_out_pins) /* might be duplicated */
563 : : break;
564 : 0 : err = add_jack_kctl(codec, *p, cfg, NULL);
565 [ # # ]: 0 : if (err < 0)
566 : 0 : return err;
567 : : }
568 [ # # ]: 0 : for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
569 [ # # ]: 0 : if (*p == *cfg->line_out_pins) /* might be duplicated */
570 : : break;
571 : 0 : err = add_jack_kctl(codec, *p, cfg, NULL);
572 [ # # ]: 0 : if (err < 0)
573 : 0 : return err;
574 : : }
575 [ # # ]: 0 : for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
576 : 0 : err = add_jack_kctl(codec, *p, cfg, NULL);
577 [ # # ]: 0 : if (err < 0)
578 : 0 : return err;
579 : : }
580 : 0 : err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL);
581 [ # # ]: 0 : if (err < 0)
582 : : return err;
583 : 0 : err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL);
584 : 0 : if (err < 0)
585 : : return err;
586 : : return 0;
587 : : }
588 : : EXPORT_SYMBOL_GPL(snd_hda_jack_add_kctls);
589 : :
590 : 0 : static void call_jack_callback(struct hda_codec *codec, unsigned int res,
591 : : struct hda_jack_tbl *jack)
592 : : {
593 : 0 : struct hda_jack_callback *cb;
594 : :
595 [ # # ]: 0 : for (cb = jack->callback; cb; cb = cb->next) {
596 : 0 : cb->jack = jack;
597 : 0 : cb->unsol_res = res;
598 : 0 : cb->func(codec, cb);
599 : : }
600 [ # # ]: 0 : if (jack->gated_jack) {
601 : 0 : struct hda_jack_tbl *gated =
602 [ # # ]: 0 : snd_hda_jack_tbl_get_mst(codec, jack->gated_jack,
603 : : jack->dev_id);
604 [ # # ]: 0 : if (gated) {
605 [ # # ]: 0 : for (cb = gated->callback; cb; cb = cb->next) {
606 : 0 : cb->jack = gated;
607 : 0 : cb->unsol_res = res;
608 : 0 : cb->func(codec, cb);
609 : : }
610 : : }
611 : : }
612 : 0 : }
613 : :
614 : : /**
615 : : * snd_hda_jack_unsol_event - Handle an unsolicited event
616 : : * @codec: the HDA codec
617 : : * @res: the unsolicited event data
618 : : */
619 : 0 : void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res)
620 : : {
621 : 0 : struct hda_jack_tbl *event;
622 : 0 : int tag = (res & AC_UNSOL_RES_TAG) >> AC_UNSOL_RES_TAG_SHIFT;
623 : :
624 [ # # ]: 0 : if (codec->dp_mst) {
625 : 0 : int dev_entry =
626 : 0 : (res & AC_UNSOL_RES_DE) >> AC_UNSOL_RES_DE_SHIFT;
627 : :
628 [ # # ]: 0 : event = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry);
629 : : } else {
630 [ # # ]: 0 : event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0);
631 : : }
632 [ # # ]: 0 : if (!event)
633 : : return;
634 : 0 : event->jack_dirty = 1;
635 : :
636 : 0 : call_jack_callback(codec, res, event);
637 : 0 : snd_hda_jack_report_sync(codec);
638 : : }
639 : : EXPORT_SYMBOL_GPL(snd_hda_jack_unsol_event);
640 : :
641 : : /**
642 : : * snd_hda_jack_poll_all - Poll all jacks
643 : : * @codec: the HDA codec
644 : : *
645 : : * Poll all detectable jacks with dirty flag, update the status, call
646 : : * callbacks and call snd_hda_jack_report_sync() if any changes are found.
647 : : */
648 : 0 : void snd_hda_jack_poll_all(struct hda_codec *codec)
649 : : {
650 : 0 : struct hda_jack_tbl *jack = codec->jacktbl.list;
651 : 0 : int i, changes = 0;
652 : :
653 [ # # ]: 0 : for (i = 0; i < codec->jacktbl.used; i++, jack++) {
654 : 0 : unsigned int old_sense;
655 [ # # # # ]: 0 : if (!jack->nid || !jack->jack_dirty || jack->phantom_jack)
656 : 0 : continue;
657 : 0 : old_sense = get_jack_plug_state(jack->pin_sense);
658 : 0 : jack_detect_update(codec, jack);
659 [ # # ]: 0 : if (old_sense == get_jack_plug_state(jack->pin_sense))
660 : 0 : continue;
661 : 0 : changes = 1;
662 : 0 : call_jack_callback(codec, 0, jack);
663 : : }
664 [ # # ]: 0 : if (changes)
665 : 0 : snd_hda_jack_report_sync(codec);
666 : 0 : }
667 : : EXPORT_SYMBOL_GPL(snd_hda_jack_poll_all);
668 : :
|