18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Jack-detection handling for HD-audio 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#ifndef __SOUND_HDA_JACK_H 98c2ecf20Sopenharmony_ci#define __SOUND_HDA_JACK_H 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <sound/jack.h> 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_cistruct auto_pin_cfg; 158c2ecf20Sopenharmony_cistruct hda_jack_tbl; 168c2ecf20Sopenharmony_cistruct hda_jack_callback; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_citypedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *); 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistruct hda_jack_callback { 218c2ecf20Sopenharmony_ci hda_nid_t nid; 228c2ecf20Sopenharmony_ci int dev_id; 238c2ecf20Sopenharmony_ci hda_jack_callback_fn func; 248c2ecf20Sopenharmony_ci unsigned int private_data; /* arbitrary data */ 258c2ecf20Sopenharmony_ci unsigned int unsol_res; /* unsolicited event bits */ 268c2ecf20Sopenharmony_ci struct hda_jack_tbl *jack; /* associated jack entry */ 278c2ecf20Sopenharmony_ci struct hda_jack_callback *next; 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistruct hda_jack_tbl { 318c2ecf20Sopenharmony_ci hda_nid_t nid; 328c2ecf20Sopenharmony_ci int dev_id; 338c2ecf20Sopenharmony_ci unsigned char tag; /* unsol event tag */ 348c2ecf20Sopenharmony_ci struct hda_jack_callback *callback; 358c2ecf20Sopenharmony_ci /* jack-detection stuff */ 368c2ecf20Sopenharmony_ci unsigned int pin_sense; /* cached pin-sense value */ 378c2ecf20Sopenharmony_ci unsigned int jack_detect:1; /* capable of jack-detection? */ 388c2ecf20Sopenharmony_ci unsigned int jack_dirty:1; /* needs to update? */ 398c2ecf20Sopenharmony_ci unsigned int phantom_jack:1; /* a fixed, always present port? */ 408c2ecf20Sopenharmony_ci unsigned int block_report:1; /* in a transitional state - do not report to userspace */ 418c2ecf20Sopenharmony_ci hda_nid_t gating_jack; /* valid when gating jack plugged */ 428c2ecf20Sopenharmony_ci hda_nid_t gated_jack; /* gated is dependent on this jack */ 438c2ecf20Sopenharmony_ci int type; 448c2ecf20Sopenharmony_ci int button_state; 458c2ecf20Sopenharmony_ci struct snd_jack *jack; 468c2ecf20Sopenharmony_ci}; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_cistruct hda_jack_keymap { 498c2ecf20Sopenharmony_ci enum snd_jack_types type; 508c2ecf20Sopenharmony_ci int key; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistruct hda_jack_tbl * 548c2ecf20Sopenharmony_cisnd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id); 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/** 578c2ecf20Sopenharmony_ci * snd_hda_jack_tbl_get - query the jack-table entry for the given NID 588c2ecf20Sopenharmony_ci * @codec: the HDA codec 598c2ecf20Sopenharmony_ci * @nid: pin NID to refer to 608c2ecf20Sopenharmony_ci */ 618c2ecf20Sopenharmony_cistatic inline struct hda_jack_tbl * 628c2ecf20Sopenharmony_cisnd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci return snd_hda_jack_tbl_get_mst(codec, nid, 0); 658c2ecf20Sopenharmony_ci} 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct hda_jack_tbl * 688c2ecf20Sopenharmony_cisnd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, 698c2ecf20Sopenharmony_ci unsigned char tag, int dev_id); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_civoid snd_hda_jack_tbl_clear(struct hda_codec *codec); 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_civoid snd_hda_jack_set_dirty_all(struct hda_codec *codec); 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciint snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid, 768c2ecf20Sopenharmony_ci int dev_id); 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_cistruct hda_jack_callback * 798c2ecf20Sopenharmony_cisnd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid, 808c2ecf20Sopenharmony_ci int dev_id, hda_jack_callback_fn func); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci/** 838c2ecf20Sopenharmony_ci * snd_hda_jack_detect_enable - enable the jack-detection 848c2ecf20Sopenharmony_ci * @codec: the HDA codec 858c2ecf20Sopenharmony_ci * @nid: pin NID to enable 868c2ecf20Sopenharmony_ci * @func: callback function to register 878c2ecf20Sopenharmony_ci * 888c2ecf20Sopenharmony_ci * In the case of error, the return value will be a pointer embedded with 898c2ecf20Sopenharmony_ci * errno. Check and handle the return value appropriately with standard 908c2ecf20Sopenharmony_ci * macros such as @IS_ERR() and @PTR_ERR(). 918c2ecf20Sopenharmony_ci */ 928c2ecf20Sopenharmony_cistatic inline struct hda_jack_callback * 938c2ecf20Sopenharmony_cisnd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid, 948c2ecf20Sopenharmony_ci hda_jack_callback_fn cb) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci return snd_hda_jack_detect_enable_callback_mst(codec, nid, 0, cb); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ciint snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid, 1008c2ecf20Sopenharmony_ci hda_nid_t gating_nid); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ciu32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci/* the jack state returned from snd_hda_jack_detect_state() */ 1058c2ecf20Sopenharmony_cienum { 1068c2ecf20Sopenharmony_ci HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM, 1078c2ecf20Sopenharmony_ci}; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ciint snd_hda_jack_detect_state_mst(struct hda_codec *codec, hda_nid_t nid, 1108c2ecf20Sopenharmony_ci int dev_id); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci/** 1138c2ecf20Sopenharmony_ci * snd_hda_jack_detect_state - query pin Presence Detect status 1148c2ecf20Sopenharmony_ci * @codec: the CODEC to sense 1158c2ecf20Sopenharmony_ci * @nid: the pin NID to sense 1168c2ecf20Sopenharmony_ci * 1178c2ecf20Sopenharmony_ci * Query and return the pin's Presence Detect status, as either 1188c2ecf20Sopenharmony_ci * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM. 1198c2ecf20Sopenharmony_ci */ 1208c2ecf20Sopenharmony_cistatic inline int 1218c2ecf20Sopenharmony_cisnd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci return snd_hda_jack_detect_state_mst(codec, nid, 0); 1248c2ecf20Sopenharmony_ci} 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci/** 1278c2ecf20Sopenharmony_ci * snd_hda_jack_detect_mst - Detect the jack 1288c2ecf20Sopenharmony_ci * @codec: the HDA codec 1298c2ecf20Sopenharmony_ci * @nid: pin NID to check jack detection 1308c2ecf20Sopenharmony_ci * @dev_id: pin device entry id 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_cistatic inline bool 1338c2ecf20Sopenharmony_cisnd_hda_jack_detect_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id) 1348c2ecf20Sopenharmony_ci{ 1358c2ecf20Sopenharmony_ci return snd_hda_jack_detect_state_mst(codec, nid, dev_id) != 1368c2ecf20Sopenharmony_ci HDA_JACK_NOT_PRESENT; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci/** 1408c2ecf20Sopenharmony_ci * snd_hda_jack_detect - Detect the jack 1418c2ecf20Sopenharmony_ci * @codec: the HDA codec 1428c2ecf20Sopenharmony_ci * @nid: pin NID to check jack detection 1438c2ecf20Sopenharmony_ci */ 1448c2ecf20Sopenharmony_cistatic inline bool 1458c2ecf20Sopenharmony_cisnd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid) 1468c2ecf20Sopenharmony_ci{ 1478c2ecf20Sopenharmony_ci return snd_hda_jack_detect_mst(codec, nid, 0); 1488c2ecf20Sopenharmony_ci} 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_cibool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid); 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ciint snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid, 1538c2ecf20Sopenharmony_ci int dev_id, const char *name, bool phantom_jack, 1548c2ecf20Sopenharmony_ci int type, const struct hda_jack_keymap *keymap); 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci/** 1578c2ecf20Sopenharmony_ci * snd_hda_jack_add_kctl - Add a kctl for the given pin 1588c2ecf20Sopenharmony_ci * @codec: the HDA codec 1598c2ecf20Sopenharmony_ci * @nid: pin NID to assign 1608c2ecf20Sopenharmony_ci * @name: string name for the jack 1618c2ecf20Sopenharmony_ci * @phantom_jack: flag to deal as a phantom jack 1628c2ecf20Sopenharmony_ci * @type: jack type bits to be reported, 0 for guessing from pincfg 1638c2ecf20Sopenharmony_ci * @keymap: optional jack / key mapping 1648c2ecf20Sopenharmony_ci * 1658c2ecf20Sopenharmony_ci * This assigns a jack-detection kctl to the given pin. The kcontrol 1668c2ecf20Sopenharmony_ci * will have the given name and index. 1678c2ecf20Sopenharmony_ci */ 1688c2ecf20Sopenharmony_cistatic inline int 1698c2ecf20Sopenharmony_cisnd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid, 1708c2ecf20Sopenharmony_ci const char *name, bool phantom_jack, 1718c2ecf20Sopenharmony_ci int type, const struct hda_jack_keymap *keymap) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci return snd_hda_jack_add_kctl_mst(codec, nid, 0, 1748c2ecf20Sopenharmony_ci name, phantom_jack, type, keymap); 1758c2ecf20Sopenharmony_ci} 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ciint snd_hda_jack_add_kctls(struct hda_codec *codec, 1788c2ecf20Sopenharmony_ci const struct auto_pin_cfg *cfg); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_civoid snd_hda_jack_report_sync(struct hda_codec *codec); 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_civoid snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_civoid snd_hda_jack_poll_all(struct hda_codec *codec); 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci#endif /* __SOUND_HDA_JACK_H */ 187