162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Jack-detection handling for HD-audio
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#ifndef __SOUND_HDA_JACK_H
962306a36Sopenharmony_ci#define __SOUND_HDA_JACK_H
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/err.h>
1262306a36Sopenharmony_ci#include <sound/jack.h>
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistruct auto_pin_cfg;
1562306a36Sopenharmony_cistruct hda_jack_tbl;
1662306a36Sopenharmony_cistruct hda_jack_callback;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_citypedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct hda_jack_callback {
2162306a36Sopenharmony_ci	hda_nid_t nid;
2262306a36Sopenharmony_ci	int dev_id;
2362306a36Sopenharmony_ci	hda_jack_callback_fn func;
2462306a36Sopenharmony_ci	unsigned int private_data;	/* arbitrary data */
2562306a36Sopenharmony_ci	unsigned int unsol_res;		/* unsolicited event bits */
2662306a36Sopenharmony_ci	struct hda_jack_tbl *jack;	/* associated jack entry */
2762306a36Sopenharmony_ci	struct hda_jack_callback *next;
2862306a36Sopenharmony_ci};
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_cistruct hda_jack_tbl {
3162306a36Sopenharmony_ci	hda_nid_t nid;
3262306a36Sopenharmony_ci	int dev_id;
3362306a36Sopenharmony_ci	unsigned char tag;		/* unsol event tag */
3462306a36Sopenharmony_ci	struct hda_jack_callback *callback;
3562306a36Sopenharmony_ci	/* jack-detection stuff */
3662306a36Sopenharmony_ci	unsigned int pin_sense;		/* cached pin-sense value */
3762306a36Sopenharmony_ci	unsigned int jack_detect:1;	/* capable of jack-detection? */
3862306a36Sopenharmony_ci	unsigned int jack_dirty:1;	/* needs to update? */
3962306a36Sopenharmony_ci	unsigned int phantom_jack:1;    /* a fixed, always present port? */
4062306a36Sopenharmony_ci	unsigned int block_report:1;    /* in a transitional state - do not report to userspace */
4162306a36Sopenharmony_ci	hda_nid_t gating_jack;		/* valid when gating jack plugged */
4262306a36Sopenharmony_ci	hda_nid_t gated_jack;		/* gated is dependent on this jack */
4362306a36Sopenharmony_ci	hda_nid_t key_report_jack;	/* key reports to this jack */
4462306a36Sopenharmony_ci	int type;
4562306a36Sopenharmony_ci	int button_state;
4662306a36Sopenharmony_ci	struct snd_jack *jack;
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct hda_jack_keymap {
5062306a36Sopenharmony_ci	enum snd_jack_types type;
5162306a36Sopenharmony_ci	int key;
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistruct hda_jack_tbl *
5562306a36Sopenharmony_cisnd_hda_jack_tbl_get_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci/**
5862306a36Sopenharmony_ci * snd_hda_jack_tbl_get - query the jack-table entry for the given NID
5962306a36Sopenharmony_ci * @codec: the HDA codec
6062306a36Sopenharmony_ci * @nid: pin NID to refer to
6162306a36Sopenharmony_ci */
6262306a36Sopenharmony_cistatic inline struct hda_jack_tbl *
6362306a36Sopenharmony_cisnd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
6462306a36Sopenharmony_ci{
6562306a36Sopenharmony_ci	return snd_hda_jack_tbl_get_mst(codec, nid, 0);
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_cistruct hda_jack_tbl *
6962306a36Sopenharmony_cisnd_hda_jack_tbl_get_from_tag(struct hda_codec *codec,
7062306a36Sopenharmony_ci			      unsigned char tag, int dev_id);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_civoid snd_hda_jack_tbl_disconnect(struct hda_codec *codec);
7362306a36Sopenharmony_civoid snd_hda_jack_tbl_clear(struct hda_codec *codec);
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_civoid snd_hda_jack_set_dirty_all(struct hda_codec *codec);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ciint snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
7862306a36Sopenharmony_ci			       int dev_id);
7962306a36Sopenharmony_ci
8062306a36Sopenharmony_cistruct hda_jack_callback *
8162306a36Sopenharmony_cisnd_hda_jack_detect_enable_callback_mst(struct hda_codec *codec, hda_nid_t nid,
8262306a36Sopenharmony_ci					int dev_id, hda_jack_callback_fn func);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/**
8562306a36Sopenharmony_ci * snd_hda_jack_detect_enable - enable the jack-detection
8662306a36Sopenharmony_ci * @codec: the HDA codec
8762306a36Sopenharmony_ci * @nid: pin NID to enable
8862306a36Sopenharmony_ci * @func: callback function to register
8962306a36Sopenharmony_ci *
9062306a36Sopenharmony_ci * In the case of error, the return value will be a pointer embedded with
9162306a36Sopenharmony_ci * errno.  Check and handle the return value appropriately with standard
9262306a36Sopenharmony_ci * macros such as @IS_ERR() and @PTR_ERR().
9362306a36Sopenharmony_ci */
9462306a36Sopenharmony_cistatic inline struct hda_jack_callback *
9562306a36Sopenharmony_cisnd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
9662306a36Sopenharmony_ci				    hda_jack_callback_fn cb)
9762306a36Sopenharmony_ci{
9862306a36Sopenharmony_ci	return snd_hda_jack_detect_enable_callback_mst(codec, nid, 0, cb);
9962306a36Sopenharmony_ci}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciint snd_hda_jack_set_gating_jack(struct hda_codec *codec, hda_nid_t gated_nid,
10262306a36Sopenharmony_ci				 hda_nid_t gating_nid);
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ciint snd_hda_jack_bind_keymap(struct hda_codec *codec, hda_nid_t key_nid,
10562306a36Sopenharmony_ci			     const struct hda_jack_keymap *keymap,
10662306a36Sopenharmony_ci			     hda_nid_t jack_nid);
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_civoid snd_hda_jack_set_button_state(struct hda_codec *codec, hda_nid_t jack_nid,
10962306a36Sopenharmony_ci				   int button_state);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciu32 snd_hda_jack_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id);
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/* the jack state returned from snd_hda_jack_detect_state() */
11462306a36Sopenharmony_cienum {
11562306a36Sopenharmony_ci	HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT, HDA_JACK_PHANTOM,
11662306a36Sopenharmony_ci};
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ciint snd_hda_jack_detect_state_mst(struct hda_codec *codec, hda_nid_t nid,
11962306a36Sopenharmony_ci				  int dev_id);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci/**
12262306a36Sopenharmony_ci * snd_hda_jack_detect_state - query pin Presence Detect status
12362306a36Sopenharmony_ci * @codec: the CODEC to sense
12462306a36Sopenharmony_ci * @nid: the pin NID to sense
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci * Query and return the pin's Presence Detect status, as either
12762306a36Sopenharmony_ci * HDA_JACK_NOT_PRESENT, HDA_JACK_PRESENT or HDA_JACK_PHANTOM.
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_cistatic inline int
13062306a36Sopenharmony_cisnd_hda_jack_detect_state(struct hda_codec *codec, hda_nid_t nid)
13162306a36Sopenharmony_ci{
13262306a36Sopenharmony_ci	return snd_hda_jack_detect_state_mst(codec, nid, 0);
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_ci/**
13662306a36Sopenharmony_ci * snd_hda_jack_detect_mst - Detect the jack
13762306a36Sopenharmony_ci * @codec: the HDA codec
13862306a36Sopenharmony_ci * @nid: pin NID to check jack detection
13962306a36Sopenharmony_ci * @dev_id: pin device entry id
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic inline bool
14262306a36Sopenharmony_cisnd_hda_jack_detect_mst(struct hda_codec *codec, hda_nid_t nid, int dev_id)
14362306a36Sopenharmony_ci{
14462306a36Sopenharmony_ci	return snd_hda_jack_detect_state_mst(codec, nid, dev_id) !=
14562306a36Sopenharmony_ci			HDA_JACK_NOT_PRESENT;
14662306a36Sopenharmony_ci}
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci/**
14962306a36Sopenharmony_ci * snd_hda_jack_detect - Detect the jack
15062306a36Sopenharmony_ci * @codec: the HDA codec
15162306a36Sopenharmony_ci * @nid: pin NID to check jack detection
15262306a36Sopenharmony_ci */
15362306a36Sopenharmony_cistatic inline bool
15462306a36Sopenharmony_cisnd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
15562306a36Sopenharmony_ci{
15662306a36Sopenharmony_ci	return snd_hda_jack_detect_mst(codec, nid, 0);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cibool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ciint snd_hda_jack_add_kctl_mst(struct hda_codec *codec, hda_nid_t nid,
16262306a36Sopenharmony_ci			      int dev_id, const char *name, bool phantom_jack,
16362306a36Sopenharmony_ci			      int type, const struct hda_jack_keymap *keymap);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ci/**
16662306a36Sopenharmony_ci * snd_hda_jack_add_kctl - Add a kctl for the given pin
16762306a36Sopenharmony_ci * @codec: the HDA codec
16862306a36Sopenharmony_ci * @nid: pin NID to assign
16962306a36Sopenharmony_ci * @name: string name for the jack
17062306a36Sopenharmony_ci * @phantom_jack: flag to deal as a phantom jack
17162306a36Sopenharmony_ci * @type: jack type bits to be reported, 0 for guessing from pincfg
17262306a36Sopenharmony_ci * @keymap: optional jack / key mapping
17362306a36Sopenharmony_ci *
17462306a36Sopenharmony_ci * This assigns a jack-detection kctl to the given pin.  The kcontrol
17562306a36Sopenharmony_ci * will have the given name and index.
17662306a36Sopenharmony_ci */
17762306a36Sopenharmony_cistatic inline int
17862306a36Sopenharmony_cisnd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
17962306a36Sopenharmony_ci		      const char *name, bool phantom_jack,
18062306a36Sopenharmony_ci		      int type, const struct hda_jack_keymap *keymap)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	return snd_hda_jack_add_kctl_mst(codec, nid, 0,
18362306a36Sopenharmony_ci					 name, phantom_jack, type, keymap);
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ciint snd_hda_jack_add_kctls(struct hda_codec *codec,
18762306a36Sopenharmony_ci			   const struct auto_pin_cfg *cfg);
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_civoid snd_hda_jack_report_sync(struct hda_codec *codec);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_civoid snd_hda_jack_unsol_event(struct hda_codec *codec, unsigned int res);
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_civoid snd_hda_jack_poll_all(struct hda_codec *codec);
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci#endif /* __SOUND_HDA_JACK_H */
196