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  
11  enum 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  
70  enum wcd_mbhc_detect_logic {
71  	WCD_DETECTION_LEGACY,
72  	WCD_DETECTION_ADC,
73  };
74  
75  enum 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  
82  enum {
83  	WCD_MBHC_ELEC_HS_INS,
84  	WCD_MBHC_ELEC_HS_REM,
85  };
86  
87  enum 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  
96  enum pa_dac_ack_flags {
97  	WCD_MBHC_HPHL_PA_OFF_ACK = 0,
98  	WCD_MBHC_HPHR_PA_OFF_ACK,
99  };
100  
101  enum wcd_mbhc_btn_det_mem {
102  	WCD_MBHC_BTN_DET_V_BTN_LOW,
103  	WCD_MBHC_BTN_DET_V_BTN_HIGH
104  };
105  
106  enum {
107  	MIC_BIAS_1 = 1,
108  	MIC_BIAS_2,
109  	MIC_BIAS_3,
110  	MIC_BIAS_4
111  };
112  
113  enum {
114  	MICB_PULLUP_ENABLE,
115  	MICB_PULLUP_DISABLE,
116  	MICB_ENABLE,
117  	MICB_DISABLE,
118  };
119  
120  enum 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  
143  enum wcd_mbhc_event_state {
144  	WCD_MBHC_EVENT_PA_HPHL,
145  	WCD_MBHC_EVENT_PA_HPHR,
146  };
147  
148  enum 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  
159  enum 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  
167  enum 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  
183  enum mbhc_moisture_rref {
184  	R_OFF,
185  	R_24_KOHM,
186  	R_84_KOHM,
187  	R_184_KOHM,
188  };
189  
190  struct 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  
215  struct 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  
225  struct wcd_mbhc_field {
226  	u16 reg;
227  	u8 mask;
228  };
229  
230  struct wcd_mbhc;
231  
232  struct 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)
271  int wcd_dt_parse_mbhc_data(struct device *dev, struct wcd_mbhc_config *cfg);
272  int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg,
273  		   struct snd_soc_jack *jack);
274  void wcd_mbhc_stop(struct wcd_mbhc *mbhc);
275  void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type);
276  int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc);
277  int wcd_mbhc_typec_report_plug(struct wcd_mbhc *mbhc);
278  int wcd_mbhc_typec_report_unplug(struct wcd_mbhc *mbhc);
279  struct 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  		      const struct wcd_mbhc_field *fields,
283  		      bool impedance_det_en);
284  int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
285  			   uint32_t *zr);
286  void wcd_mbhc_deinit(struct wcd_mbhc *mbhc);
287  int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event);
288  
289  #else
wcd_dt_parse_mbhc_data(struct device * dev,struct wcd_mbhc_config * cfg)290  static inline int wcd_dt_parse_mbhc_data(struct device *dev,
291  					 struct wcd_mbhc_config *cfg)
292  {
293  	return -ENOTSUPP;
294  }
295  
wcd_mbhc_stop(struct wcd_mbhc * mbhc)296  static inline void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
297  {
298  }
299  
wcd_mbhc_init(struct snd_soc_component * component,const struct wcd_mbhc_cb * mbhc_cb,const struct wcd_mbhc_intr * mbhc_cdc_intr_ids,const struct wcd_mbhc_field * fields,bool impedance_det_en)300  static 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  		      const struct wcd_mbhc_field *fields,
304  		      bool impedance_det_en)
305  {
306  	return ERR_PTR(-ENOTSUPP);
307  }
308  
wcd_mbhc_set_hph_type(struct wcd_mbhc * mbhc,int hph_type)309  static inline void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type)
310  {
311  }
312  
wcd_mbhc_get_hph_type(struct wcd_mbhc * mbhc)313  static inline int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc)
314  {
315  	return -ENOTSUPP;
316  }
317  
wcd_mbhc_event_notify(struct wcd_mbhc * mbhc,unsigned long event)318  static inline int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
319  {
320  	return -ENOTSUPP;
321  }
322  
wcd_mbhc_start(struct wcd_mbhc * mbhc,struct wcd_mbhc_config * mbhc_cfg,struct snd_soc_jack * jack)323  static 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  
wcd_mbhc_get_impedance(struct wcd_mbhc * mbhc,uint32_t * zl,uint32_t * zr)330  static 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  }
wcd_mbhc_deinit(struct wcd_mbhc * mbhc)338  static inline void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
339  {
340  }
341  #endif
342  
343  #endif /* __WCD_MBHC_V2_H__ */
344