1/* SPDX-License-Identifier: GPL-2.0 */
2
3#ifndef __WCD_MBHC_V2_H__
4#define __WCD_MBHC_V2_H__
5
6#include <sound/jack.h>
7
8#define WCD_MBHC_FIELD(id, rreg, rmask) \
9	[id] = { .reg = rreg, .mask = rmask }
10
11enum wcd_mbhc_field_function {
12	WCD_MBHC_L_DET_EN,
13	WCD_MBHC_GND_DET_EN,
14	WCD_MBHC_MECH_DETECTION_TYPE,
15	WCD_MBHC_MIC_CLAMP_CTL,
16	WCD_MBHC_ELECT_DETECTION_TYPE,
17	WCD_MBHC_HS_L_DET_PULL_UP_CTRL,
18	WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL,
19	WCD_MBHC_HPHL_PLUG_TYPE,
20	WCD_MBHC_GND_PLUG_TYPE,
21	WCD_MBHC_SW_HPH_LP_100K_TO_GND,
22	WCD_MBHC_ELECT_SCHMT_ISRC,
23	WCD_MBHC_FSM_EN,
24	WCD_MBHC_INSREM_DBNC,
25	WCD_MBHC_BTN_DBNC,
26	WCD_MBHC_HS_VREF,
27	WCD_MBHC_HS_COMP_RESULT,
28	WCD_MBHC_IN2P_CLAMP_STATE,
29	WCD_MBHC_MIC_SCHMT_RESULT,
30	WCD_MBHC_HPHL_SCHMT_RESULT,
31	WCD_MBHC_HPHR_SCHMT_RESULT,
32	WCD_MBHC_OCP_FSM_EN,
33	WCD_MBHC_BTN_RESULT,
34	WCD_MBHC_BTN_ISRC_CTL,
35	WCD_MBHC_ELECT_RESULT,
36	WCD_MBHC_MICB_CTRL,    /* Pull-up and micb control */
37	WCD_MBHC_HPH_CNP_WG_TIME,
38	WCD_MBHC_HPHR_PA_EN,
39	WCD_MBHC_HPHL_PA_EN,
40	WCD_MBHC_HPH_PA_EN,
41	WCD_MBHC_SWCH_LEVEL_REMOVE,
42	WCD_MBHC_PULLDOWN_CTRL,
43	WCD_MBHC_ANC_DET_EN,
44	WCD_MBHC_FSM_STATUS,
45	WCD_MBHC_MUX_CTL,
46	WCD_MBHC_MOISTURE_STATUS,
47	WCD_MBHC_HPHR_GND,
48	WCD_MBHC_HPHL_GND,
49	WCD_MBHC_HPHL_OCP_DET_EN,
50	WCD_MBHC_HPHR_OCP_DET_EN,
51	WCD_MBHC_HPHL_OCP_STATUS,
52	WCD_MBHC_HPHR_OCP_STATUS,
53	WCD_MBHC_ADC_EN,
54	WCD_MBHC_ADC_COMPLETE,
55	WCD_MBHC_ADC_TIMEOUT,
56	WCD_MBHC_ADC_RESULT,
57	WCD_MBHC_MICB2_VOUT,
58	WCD_MBHC_ADC_MODE,
59	WCD_MBHC_DETECTION_DONE,
60	WCD_MBHC_ELECT_ISRC_EN,
61	WCD_MBHC_REG_FUNC_MAX,
62};
63
64#define WCD_MBHC_DEF_BUTTONS 8
65#define WCD_MBHC_KEYCODE_NUM 8
66#define WCD_MBHC_USLEEP_RANGE_MARGIN_US 100
67#define WCD_MBHC_THR_HS_MICB_MV  2700
68#define WCD_MONO_HS_MIN_THR	2
69
70enum wcd_mbhc_detect_logic {
71	WCD_DETECTION_LEGACY,
72	WCD_DETECTION_ADC,
73};
74
75enum wcd_mbhc_cs_mb_en_flag {
76	WCD_MBHC_EN_CS = 0,
77	WCD_MBHC_EN_MB,
78	WCD_MBHC_EN_PULLUP,
79	WCD_MBHC_EN_NONE,
80};
81
82enum {
83	WCD_MBHC_ELEC_HS_INS,
84	WCD_MBHC_ELEC_HS_REM,
85};
86
87enum wcd_mbhc_plug_type {
88	MBHC_PLUG_TYPE_INVALID = -1,
89	MBHC_PLUG_TYPE_NONE,
90	MBHC_PLUG_TYPE_HEADSET,
91	MBHC_PLUG_TYPE_HEADPHONE,
92	MBHC_PLUG_TYPE_HIGH_HPH,
93	MBHC_PLUG_TYPE_GND_MIC_SWAP,
94};
95
96enum pa_dac_ack_flags {
97	WCD_MBHC_HPHL_PA_OFF_ACK = 0,
98	WCD_MBHC_HPHR_PA_OFF_ACK,
99};
100
101enum wcd_mbhc_btn_det_mem {
102	WCD_MBHC_BTN_DET_V_BTN_LOW,
103	WCD_MBHC_BTN_DET_V_BTN_HIGH
104};
105
106enum {
107	MIC_BIAS_1 = 1,
108	MIC_BIAS_2,
109	MIC_BIAS_3,
110	MIC_BIAS_4
111};
112
113enum {
114	MICB_PULLUP_ENABLE,
115	MICB_PULLUP_DISABLE,
116	MICB_ENABLE,
117	MICB_DISABLE,
118};
119
120enum wcd_notify_event {
121	WCD_EVENT_INVALID,
122	/* events for micbias ON and OFF */
123	WCD_EVENT_PRE_MICBIAS_2_OFF,
124	WCD_EVENT_POST_MICBIAS_2_OFF,
125	WCD_EVENT_PRE_MICBIAS_2_ON,
126	WCD_EVENT_POST_MICBIAS_2_ON,
127	WCD_EVENT_PRE_DAPM_MICBIAS_2_OFF,
128	WCD_EVENT_POST_DAPM_MICBIAS_2_OFF,
129	WCD_EVENT_PRE_DAPM_MICBIAS_2_ON,
130	WCD_EVENT_POST_DAPM_MICBIAS_2_ON,
131	/* events for PA ON and OFF */
132	WCD_EVENT_PRE_HPHL_PA_ON,
133	WCD_EVENT_POST_HPHL_PA_OFF,
134	WCD_EVENT_PRE_HPHR_PA_ON,
135	WCD_EVENT_POST_HPHR_PA_OFF,
136	WCD_EVENT_PRE_HPHL_PA_OFF,
137	WCD_EVENT_PRE_HPHR_PA_OFF,
138	WCD_EVENT_OCP_OFF,
139	WCD_EVENT_OCP_ON,
140	WCD_EVENT_LAST,
141};
142
143enum wcd_mbhc_event_state {
144	WCD_MBHC_EVENT_PA_HPHL,
145	WCD_MBHC_EVENT_PA_HPHR,
146};
147
148enum wcd_mbhc_hph_type {
149	WCD_MBHC_HPH_NONE = 0,
150	WCD_MBHC_HPH_MONO,
151	WCD_MBHC_HPH_STEREO,
152};
153
154/*
155 * These enum definitions are directly mapped to the register
156 * definitions
157 */
158
159enum mbhc_hs_pullup_iref {
160	I_DEFAULT = -1,
161	I_OFF = 0,
162	I_1P0_UA,
163	I_2P0_UA,
164	I_3P0_UA,
165};
166
167enum mbhc_hs_pullup_iref_v2 {
168	HS_PULLUP_I_DEFAULT = -1,
169	HS_PULLUP_I_3P0_UA = 0,
170	HS_PULLUP_I_2P25_UA,
171	HS_PULLUP_I_1P5_UA,
172	HS_PULLUP_I_0P75_UA,
173	HS_PULLUP_I_1P125_UA = 0x05,
174	HS_PULLUP_I_0P375_UA = 0x07,
175	HS_PULLUP_I_2P0_UA,
176	HS_PULLUP_I_1P0_UA = 0x0A,
177	HS_PULLUP_I_0P5_UA,
178	HS_PULLUP_I_0P25_UA = 0x0F,
179	HS_PULLUP_I_0P125_UA = 0x17,
180	HS_PULLUP_I_OFF,
181};
182
183enum mbhc_moisture_rref {
184	R_OFF,
185	R_24_KOHM,
186	R_84_KOHM,
187	R_184_KOHM,
188};
189
190struct wcd_mbhc_config {
191	int btn_high[WCD_MBHC_DEF_BUTTONS];
192	int btn_low[WCD_MBHC_DEF_BUTTONS];
193	int v_hs_max;
194	int num_btn;
195	bool mono_stero_detection;
196	bool typec_analog_mux;
197	bool (*swap_gnd_mic)(struct snd_soc_component *component, bool active);
198	bool hs_ext_micbias;
199	bool gnd_det_en;
200	uint32_t linein_th;
201	bool moisture_en;
202	int mbhc_micbias;
203	int anc_micbias;
204	bool moisture_duty_cycle_en;
205	bool hphl_swh; /*track HPHL switch NC / NO */
206	bool gnd_swh; /*track GND switch NC / NO */
207	u32 hs_thr;
208	u32 hph_thr;
209	u32 micb_mv;
210	u32 moist_vref;
211	u32 moist_iref;
212	u32 moist_rref;
213};
214
215struct wcd_mbhc_intr {
216	int mbhc_sw_intr;
217	int mbhc_btn_press_intr;
218	int mbhc_btn_release_intr;
219	int mbhc_hs_ins_intr;
220	int mbhc_hs_rem_intr;
221	int hph_left_ocp;
222	int hph_right_ocp;
223};
224
225struct wcd_mbhc_field {
226	u16 reg;
227	u8 mask;
228};
229
230struct wcd_mbhc;
231
232struct wcd_mbhc_cb {
233	void (*update_cross_conn_thr)(struct snd_soc_component *component);
234	void (*get_micbias_val)(struct snd_soc_component *component, int *mb);
235	void (*bcs_enable)(struct snd_soc_component *component, bool bcs_enable);
236	void (*compute_impedance)(struct snd_soc_component *component,
237				  uint32_t *zl, uint32_t *zr);
238	void (*set_micbias_value)(struct snd_soc_component *component);
239	void (*set_auto_zeroing)(struct snd_soc_component *component,
240			bool enable);
241	void (*clk_setup)(struct snd_soc_component *component, bool enable);
242	bool (*micbias_enable_status)(struct snd_soc_component *component, int micb_num);
243	void (*mbhc_bias)(struct snd_soc_component *component, bool enable);
244	void (*set_btn_thr)(struct snd_soc_component *component,
245			    int *btn_low, int *btn_high,
246			    int num_btn, bool is_micbias);
247	void (*hph_pull_up_control)(struct snd_soc_component *component,
248				    enum mbhc_hs_pullup_iref);
249	int (*mbhc_micbias_control)(struct snd_soc_component *component,
250			int micb_num, int req);
251	void (*mbhc_micb_ramp_control)(struct snd_soc_component *component,
252			bool enable);
253	bool (*extn_use_mb)(struct snd_soc_component *component);
254	int (*mbhc_micb_ctrl_thr_mic)(struct snd_soc_component *component,
255			int micb_num, bool req_en);
256	void (*mbhc_gnd_det_ctrl)(struct snd_soc_component *component,
257			bool enable);
258	void (*hph_pull_down_ctrl)(struct snd_soc_component *component,
259			bool enable);
260	void (*mbhc_moisture_config)(struct snd_soc_component *component);
261	void (*update_anc_state)(struct snd_soc_component *component,
262			bool enable, int anc_num);
263	void (*hph_pull_up_control_v2)(struct snd_soc_component *component,
264			int pull_up_cur);
265	bool (*mbhc_get_moisture_status)(struct snd_soc_component *component);
266	void (*mbhc_moisture_polling_ctrl)(struct snd_soc_component *component, bool enable);
267	void (*mbhc_moisture_detect_en)(struct snd_soc_component *component, bool enable);
268};
269
270#if IS_ENABLED(CONFIG_SND_SOC_WCD_MBHC)
271int wcd_dt_parse_mbhc_data(struct device *dev, struct wcd_mbhc_config *cfg);
272int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg,
273		   struct snd_soc_jack *jack);
274void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
275void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type);
276int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc);
277int wcd_mbhc_typec_report_plug(struct wcd_mbhc *mbhc);
278int wcd_mbhc_typec_report_unplug(struct wcd_mbhc *mbhc);
279struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
280		      const struct wcd_mbhc_cb *mbhc_cb,
281		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
282		      struct wcd_mbhc_field *fields,
283		      bool impedance_det_en);
284int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
285			   uint32_t *zr);
286void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
287int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event);
288
289#else
290static inline int wcd_dt_parse_mbhc_data(struct device *dev,
291					 struct wcd_mbhc_config *cfg)
292{
293	return -ENOTSUPP;
294}
295
296static inline void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
297{
298}
299
300static inline struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
301		      const struct wcd_mbhc_cb *mbhc_cb,
302		      const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
303		      struct wcd_mbhc_field *fields,
304		      bool impedance_det_en)
305{
306	return ERR_PTR(-ENOTSUPP);
307}
308
309static inline void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type)
310{
311}
312
313static inline int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc)
314{
315	return -ENOTSUPP;
316}
317
318static inline int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
319{
320	return -ENOTSUPP;
321}
322
323static inline int wcd_mbhc_start(struct wcd_mbhc *mbhc,
324				 struct wcd_mbhc_config *mbhc_cfg,
325				 struct snd_soc_jack *jack)
326{
327	return 0;
328}
329
330static inline int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc,
331					 uint32_t *zl,
332					 uint32_t *zr)
333{
334	*zl = 0;
335	*zr = 0;
336	return -EINVAL;
337}
338static inline void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
339{
340}
341#endif
342
343#endif /* __WCD_MBHC_V2_H__ */
344