Lines Matching +full:codec +full:- +full:1

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Jack-detection handling for HD-audio
20 * is_jack_detectable - Check whether the given pin is jack-detectable
21 * @codec: the HDA codec
26 * detection is prohibited in the codec level, the pin config has
29 bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid) in is_jack_detectable() argument
31 if (codec->no_jack_detect) in is_jack_detectable()
33 if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT)) in is_jack_detectable()
35 if (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) & in is_jack_detectable()
38 if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) && in is_jack_detectable()
39 !codec->jackpoll_interval) in is_jack_detectable()
46 static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id) in read_pin_sense() argument
51 if (!codec->no_trigger_sense) { in read_pin_sense()
52 pincap = snd_hda_query_pin_caps(codec, nid); in read_pin_sense()
54 snd_hda_codec_read(codec, nid, 0, in read_pin_sense()
57 val = snd_hda_codec_read(codec, nid, 0, in read_pin_sense()
59 if (codec->inv_jack_detect) in read_pin_sense()
65 * snd_hda_jack_tbl_get_mst - query the jack-table entry for the given NID
66 * @codec: the HDA codec
71 snd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id) in snd_hda_jack_tbl_get_mst() argument
73 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_tbl_get_mst()
78 for (i = 0; i < codec->jacktbl.used; i++, jack++) in snd_hda_jack_tbl_get_mst()
79 if (jack->nid == nid && jack->dev_id == dev_id) in snd_hda_jack_tbl_get_mst()
86 * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
87 * @codec: the HDA codec
92 snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, in snd_hda_jack_tbl_get_from_tag() argument
95 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_tbl_get_from_tag()
100 for (i = 0; i < codec->jacktbl.used; i++, jack++) in snd_hda_jack_tbl_get_from_tag()
101 if (jack->tag == tag && jack->dev_id == dev_id) in snd_hda_jack_tbl_get_from_tag()
108 any_jack_tbl_get_from_nid(struct hda_codec *codec, hda_nid_t nid) in any_jack_tbl_get_from_nid() argument
110 struct hda_jack_tbl *jack = codec->jacktbl.list; in any_jack_tbl_get_from_nid()
115 for (i = 0; i < codec->jacktbl.used; i++, jack++) in any_jack_tbl_get_from_nid()
116 if (jack->nid == nid) in any_jack_tbl_get_from_nid()
122 * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
123 * @codec: the HDA codec
128 snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid, int dev_id) in snd_hda_jack_tbl_new() argument
131 snd_hda_jack_tbl_get_mst(codec, nid, dev_id); in snd_hda_jack_tbl_new()
133 any_jack_tbl_get_from_nid(codec, nid); in snd_hda_jack_tbl_new()
135 WARN_ON(dev_id != 0 && !codec->dp_mst); in snd_hda_jack_tbl_new()
139 jack = snd_array_new(&codec->jacktbl); in snd_hda_jack_tbl_new()
142 jack->nid = nid; in snd_hda_jack_tbl_new()
143 jack->dev_id = dev_id; in snd_hda_jack_tbl_new()
144 jack->jack_dirty = 1; in snd_hda_jack_tbl_new()
146 jack->tag = existing_nid_jack->tag; in snd_hda_jack_tbl_new()
153 jack->jack_detect = existing_nid_jack->jack_detect; in snd_hda_jack_tbl_new()
155 jack->tag = codec->jacktbl.used; in snd_hda_jack_tbl_new()
161 void snd_hda_jack_tbl_disconnect(struct hda_codec *codec) in snd_hda_jack_tbl_disconnect() argument
163 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_tbl_disconnect()
166 for (i = 0; i < codec->jacktbl.used; i++, jack++) { in snd_hda_jack_tbl_disconnect()
167 if (!codec->bus->shutdown && jack->jack) in snd_hda_jack_tbl_disconnect()
168 snd_device_disconnect(codec->card, jack->jack); in snd_hda_jack_tbl_disconnect()
172 void snd_hda_jack_tbl_clear(struct hda_codec *codec) in snd_hda_jack_tbl_clear() argument
174 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_tbl_clear()
177 for (i = 0; i < codec->jacktbl.used; i++, jack++) { in snd_hda_jack_tbl_clear()
181 if (!codec->bus->shutdown && jack->jack) in snd_hda_jack_tbl_clear()
182 snd_device_free(codec->card, jack->jack); in snd_hda_jack_tbl_clear()
184 for (cb = jack->callback; cb; cb = next) { in snd_hda_jack_tbl_clear()
185 next = cb->next; in snd_hda_jack_tbl_clear()
189 snd_array_free(&codec->jacktbl); in snd_hda_jack_tbl_clear()
195 static void jack_detect_update(struct hda_codec *codec, in jack_detect_update() argument
198 if (!jack->jack_dirty) in jack_detect_update()
201 if (jack->phantom_jack) in jack_detect_update()
202 jack->pin_sense = AC_PINSENSE_PRESENCE; in jack_detect_update()
204 jack->pin_sense = read_pin_sense(codec, jack->nid, in jack_detect_update()
205 jack->dev_id); in jack_detect_update()
208 if (jack->gating_jack && in jack_detect_update()
209 !snd_hda_jack_detect_mst(codec, jack->gating_jack, jack->dev_id)) in jack_detect_update()
210 jack->pin_sense &= ~AC_PINSENSE_PRESENCE; in jack_detect_update()
212 jack->jack_dirty = 0; in jack_detect_update()
215 if (jack->gated_jack) { in jack_detect_update()
217 snd_hda_jack_tbl_get_mst(codec, jack->gated_jack, in jack_detect_update()
218 jack->dev_id); in jack_detect_update()
220 gated->jack_dirty = 1; in jack_detect_update()
221 jack_detect_update(codec, gated); in jack_detect_update()
227 * snd_hda_jack_set_dirty_all - Mark all the cached as dirty
228 * @codec: the HDA codec
233 void snd_hda_jack_set_dirty_all(struct hda_codec *codec) in snd_hda_jack_set_dirty_all() argument
235 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_set_dirty_all()
238 for (i = 0; i < codec->jacktbl.used; i++, jack++) in snd_hda_jack_set_dirty_all()
239 if (jack->nid) in snd_hda_jack_set_dirty_all()
240 jack->jack_dirty = 1; in snd_hda_jack_set_dirty_all()
245 * snd_hda_jack_pin_sense - execute pin sense measurement
246 * @codec: the CODEC to sense
253 u32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id) in snd_hda_jack_pin_sense() argument
256 snd_hda_jack_tbl_get_mst(codec, nid, dev_id); in snd_hda_jack_pin_sense()
258 jack_detect_update(codec, jack); in snd_hda_jack_pin_sense()
259 return jack->pin_sense; in snd_hda_jack_pin_sense()
261 return read_pin_sense(codec, nid, dev_id); in snd_hda_jack_pin_sense()
266 * snd_hda_jack_detect_state_mst - query pin Presence Detect status
267 * @codec: the CODEC to sense
274 int snd_hda_jack_detect_state_mst(struct hda_codec *codec, in snd_hda_jack_detect_state_mst() argument
278 snd_hda_jack_tbl_get_mst(codec, nid, dev_id); in snd_hda_jack_detect_state_mst()
279 if (jack && jack->phantom_jack) in snd_hda_jack_detect_state_mst()
281 else if (snd_hda_jack_pin_sense(codec, nid, dev_id) & in snd_hda_jack_detect_state_mst()
298 for (cb = jack->callback; cb; cb = cb->next) { in find_callback_from_list()
299 if (cb->func == func) in find_callback_from_list()
307 * snd_hda_jack_detect_enable_callback_mst - enable the jack-detection
308 * @codec: the HDA codec
318 snd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid, in snd_hda_jack_detect_enable_callback_mst() argument
325 jack = snd_hda_jack_tbl_new(codec, nid, dev_id); in snd_hda_jack_detect_enable_callback_mst()
327 return ERR_PTR(-ENOMEM); in snd_hda_jack_detect_enable_callback_mst()
334 return ERR_PTR(-ENOMEM); in snd_hda_jack_detect_enable_callback_mst()
335 callback->func = func; in snd_hda_jack_detect_enable_callback_mst()
336 callback->nid = jack->nid; in snd_hda_jack_detect_enable_callback_mst()
337 callback->dev_id = jack->dev_id; in snd_hda_jack_detect_enable_callback_mst()
338 callback->next = jack->callback; in snd_hda_jack_detect_enable_callback_mst()
339 jack->callback = callback; in snd_hda_jack_detect_enable_callback_mst()
342 if (jack->jack_detect) in snd_hda_jack_detect_enable_callback_mst()
344 jack->jack_detect = 1; in snd_hda_jack_detect_enable_callback_mst()
345 if (codec->jackpoll_interval > 0) in snd_hda_jack_detect_enable_callback_mst()
347 err = snd_hda_codec_write_cache(codec, nid, 0, in snd_hda_jack_detect_enable_callback_mst()
349 AC_USRSP_EN | jack->tag); in snd_hda_jack_detect_enable_callback_mst()
357 * snd_hda_jack_detect_enable - Enable the jack detection on the given pin
358 * @codec: the HDA codec
365 int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, in snd_hda_jack_detect_enable() argument
368 return PTR_ERR_OR_ZERO(snd_hda_jack_detect_enable_callback_mst(codec, in snd_hda_jack_detect_enable()
376 * snd_hda_jack_set_gating_jack - Set gating jack.
377 * @codec: the HDA codec
383 int snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, in snd_hda_jack_set_gating_jack() argument
386 struct hda_jack_tbl *gated = snd_hda_jack_tbl_new(codec, gated_nid, 0); in snd_hda_jack_set_gating_jack()
388 snd_hda_jack_tbl_new(codec, gating_nid, 0); in snd_hda_jack_set_gating_jack()
390 WARN_ON(codec->dp_mst); in snd_hda_jack_set_gating_jack()
393 return -EINVAL; in snd_hda_jack_set_gating_jack()
395 gated->gating_jack = gating_nid; in snd_hda_jack_set_gating_jack()
396 gating->gated_jack = gated_nid; in snd_hda_jack_set_gating_jack()
403 * snd_hda_jack_bind_keymap - bind keys generated from one NID to another jack.
404 * @codec: the HDA codec
412 int snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid, in snd_hda_jack_bind_keymap() argument
417 struct hda_jack_tbl *key_gen = snd_hda_jack_tbl_get(codec, key_nid); in snd_hda_jack_bind_keymap()
418 struct hda_jack_tbl *report_to = snd_hda_jack_tbl_get(codec, jack_nid); in snd_hda_jack_bind_keymap()
420 WARN_ON(codec->dp_mst); in snd_hda_jack_bind_keymap()
422 if (!key_gen || !report_to || !report_to->jack) in snd_hda_jack_bind_keymap()
423 return -EINVAL; in snd_hda_jack_bind_keymap()
425 key_gen->key_report_jack = jack_nid; in snd_hda_jack_bind_keymap()
428 for (map = keymap; map->type; map++) in snd_hda_jack_bind_keymap()
429 snd_jack_set_key(report_to->jack, map->type, map->key); in snd_hda_jack_bind_keymap()
436 * snd_hda_jack_set_button_state - report button event to the hda_jack_tbl button_state.
437 * @codec: the HDA codec
439 * @button_state: the button event captured by codec
441 * Codec driver calls this function to report the button event.
443 void snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid, in snd_hda_jack_set_button_state() argument
446 struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, jack_nid); in snd_hda_jack_set_button_state()
451 if (jack->key_report_jack) { in snd_hda_jack_set_button_state()
453 snd_hda_jack_tbl_get(codec, jack->key_report_jack); in snd_hda_jack_set_button_state()
456 report_to->button_state = button_state; in snd_hda_jack_set_button_state()
461 jack->button_state = button_state; in snd_hda_jack_set_button_state()
466 * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
467 * @codec: the HDA codec
469 void snd_hda_jack_report_sync(struct hda_codec *codec) in snd_hda_jack_report_sync() argument
475 jack = codec->jacktbl.list; in snd_hda_jack_report_sync()
476 for (i = 0; i < codec->jacktbl.used; i++, jack++) in snd_hda_jack_report_sync()
477 if (jack->nid) in snd_hda_jack_report_sync()
478 jack_detect_update(codec, jack); in snd_hda_jack_report_sync()
483 jack = codec->jacktbl.list; in snd_hda_jack_report_sync()
484 for (i = 0; i < codec->jacktbl.used; i++, jack++) in snd_hda_jack_report_sync()
485 if (jack->nid) { in snd_hda_jack_report_sync()
486 if (!jack->jack || jack->block_report) in snd_hda_jack_report_sync()
488 state = jack->button_state; in snd_hda_jack_report_sync()
489 if (get_jack_plug_state(jack->pin_sense)) in snd_hda_jack_report_sync()
490 state |= jack->type; in snd_hda_jack_report_sync()
491 snd_jack_report(jack->jack, state); in snd_hda_jack_report_sync()
492 if (jack->button_state) { in snd_hda_jack_report_sync()
493 snd_jack_report(jack->jack, in snd_hda_jack_report_sync()
494 state & ~jack->button_state); in snd_hda_jack_report_sync()
495 jack->button_state = 0; /* button released */ in snd_hda_jack_report_sync()
501 /* guess the jack type from the pin-config */
502 static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid) in get_input_jack_type() argument
504 unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid); in get_input_jack_type()
523 struct hda_jack_tbl *jacks = jack->private_data; in hda_free_jack_priv()
524 jacks->nid = 0; in hda_free_jack_priv()
525 jacks->jack = NULL; in hda_free_jack_priv()
529 * snd_hda_jack_add_kctl_mst - Add a kctl for the given pin
530 * @codec: the HDA codec
538 * This assigns a jack-detection kctl to the given pin. The kcontrol
541 int snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid, in snd_hda_jack_add_kctl_mst() argument
549 jack = snd_hda_jack_tbl_new(codec, nid, dev_id); in snd_hda_jack_add_kctl_mst()
552 if (jack->jack) in snd_hda_jack_add_kctl_mst()
556 type = get_input_jack_type(codec, nid); in snd_hda_jack_add_kctl_mst()
560 for (map = keymap; map->type; map++) in snd_hda_jack_add_kctl_mst()
561 buttons |= map->type; in snd_hda_jack_add_kctl_mst()
564 err = snd_jack_new(codec->card, name, type | buttons, in snd_hda_jack_add_kctl_mst()
565 &jack->jack, true, phantom_jack); in snd_hda_jack_add_kctl_mst()
569 jack->phantom_jack = !!phantom_jack; in snd_hda_jack_add_kctl_mst()
570 jack->type = type; in snd_hda_jack_add_kctl_mst()
571 jack->button_state = 0; in snd_hda_jack_add_kctl_mst()
572 jack->jack->private_data = jack; in snd_hda_jack_add_kctl_mst()
573 jack->jack->private_free = hda_free_jack_priv; in snd_hda_jack_add_kctl_mst()
575 for (map = keymap; map->type; map++) in snd_hda_jack_add_kctl_mst()
576 snd_jack_set_key(jack->jack, map->type, map->key); in snd_hda_jack_add_kctl_mst()
579 state = snd_hda_jack_detect_mst(codec, nid, dev_id); in snd_hda_jack_add_kctl_mst()
580 snd_jack_report(jack->jack, state ? jack->type : 0); in snd_hda_jack_add_kctl_mst()
586 static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid, in add_jack_kctl() argument
595 WARN_ON(codec->dp_mst); in add_jack_kctl()
599 def_conf = snd_hda_codec_get_pincfg(codec, nid); in add_jack_kctl()
604 !is_jack_detectable(codec, nid); in add_jack_kctl()
609 snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), NULL); in add_jack_kctl()
612 strncat(name, " Phantom", sizeof(name) - strlen(name) - 1); in add_jack_kctl()
613 err = snd_hda_jack_add_kctl(codec, nid, name, phantom_jack, 0, NULL); in add_jack_kctl()
618 return snd_hda_jack_detect_enable(codec, nid, 0); in add_jack_kctl()
623 * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
624 * @codec: the HDA codec
627 int snd_hda_jack_add_kctls(struct hda_codec *codec, in snd_hda_jack_add_kctls() argument
633 for (i = 0; i < cfg->num_inputs; i++) { in snd_hda_jack_add_kctls()
636 if (cfg->inputs[i].is_headphone_mic) { in snd_hda_jack_add_kctls()
637 if (auto_cfg_hp_outs(cfg) == 1) in snd_hda_jack_add_kctls()
638 err = add_jack_kctl(codec, auto_cfg_hp_pins(cfg)[0], in snd_hda_jack_add_kctls()
641 err = add_jack_kctl(codec, cfg->inputs[i].pin, in snd_hda_jack_add_kctls()
644 err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, in snd_hda_jack_add_kctls()
650 for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) { in snd_hda_jack_add_kctls()
651 err = add_jack_kctl(codec, *p, cfg, NULL); in snd_hda_jack_add_kctls()
655 for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) { in snd_hda_jack_add_kctls()
656 if (*p == *cfg->line_out_pins) /* might be duplicated */ in snd_hda_jack_add_kctls()
658 err = add_jack_kctl(codec, *p, cfg, NULL); in snd_hda_jack_add_kctls()
662 for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) { in snd_hda_jack_add_kctls()
663 if (*p == *cfg->line_out_pins) /* might be duplicated */ in snd_hda_jack_add_kctls()
665 err = add_jack_kctl(codec, *p, cfg, NULL); in snd_hda_jack_add_kctls()
669 for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) { in snd_hda_jack_add_kctls()
670 err = add_jack_kctl(codec, *p, cfg, NULL); in snd_hda_jack_add_kctls()
674 err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, NULL); in snd_hda_jack_add_kctls()
677 err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, NULL); in snd_hda_jack_add_kctls()
684 static void call_jack_callback(struct hda_codec *codec, unsigned int res, in call_jack_callback() argument
689 for (cb = jack->callback; cb; cb = cb->next) { in call_jack_callback()
690 cb->jack = jack; in call_jack_callback()
691 cb->unsol_res = res; in call_jack_callback()
692 cb->func(codec, cb); in call_jack_callback()
694 if (jack->gated_jack) { in call_jack_callback()
696 snd_hda_jack_tbl_get_mst(codec, jack->gated_jack, in call_jack_callback()
697 jack->dev_id); in call_jack_callback()
699 for (cb = gated->callback; cb; cb = cb->next) { in call_jack_callback()
700 cb->jack = gated; in call_jack_callback()
701 cb->unsol_res = res; in call_jack_callback()
702 cb->func(codec, cb); in call_jack_callback()
709 * snd_hda_jack_unsol_event - Handle an unsolicited event
710 * @codec: the HDA codec
713 void snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res) in snd_hda_jack_unsol_event() argument
718 if (codec->dp_mst) { in snd_hda_jack_unsol_event()
722 event = snd_hda_jack_tbl_get_from_tag(codec, tag, dev_entry); in snd_hda_jack_unsol_event()
724 event = snd_hda_jack_tbl_get_from_tag(codec, tag, 0); in snd_hda_jack_unsol_event()
729 if (event->key_report_jack) { in snd_hda_jack_unsol_event()
731 snd_hda_jack_tbl_get_mst(codec, event->key_report_jack, in snd_hda_jack_unsol_event()
732 event->dev_id); in snd_hda_jack_unsol_event()
734 report_to->jack_dirty = 1; in snd_hda_jack_unsol_event()
736 event->jack_dirty = 1; in snd_hda_jack_unsol_event()
738 call_jack_callback(codec, res, event); in snd_hda_jack_unsol_event()
739 snd_hda_jack_report_sync(codec); in snd_hda_jack_unsol_event()
744 * snd_hda_jack_poll_all - Poll all jacks
745 * @codec: the HDA codec
750 void snd_hda_jack_poll_all(struct hda_codec *codec) in snd_hda_jack_poll_all() argument
752 struct hda_jack_tbl *jack = codec->jacktbl.list; in snd_hda_jack_poll_all()
755 for (i = 0; i < codec->jacktbl.used; i++, jack++) { in snd_hda_jack_poll_all()
757 if (!jack->nid || !jack->jack_dirty || jack->phantom_jack) in snd_hda_jack_poll_all()
759 old_sense = get_jack_plug_state(jack->pin_sense); in snd_hda_jack_poll_all()
760 jack_detect_update(codec, jack); in snd_hda_jack_poll_all()
761 if (old_sense == get_jack_plug_state(jack->pin_sense)) in snd_hda_jack_poll_all()
763 changes = 1; in snd_hda_jack_poll_all()
764 call_jack_callback(codec, 0, jack); in snd_hda_jack_poll_all()
767 snd_hda_jack_report_sync(codec); in snd_hda_jack_poll_all()