| 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); |
| 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 |
| 290 | static inline int wcd_dt_parse_mbhc_data(struct device *dev, |
| 291 | struct wcd_mbhc_config *cfg) |
| 292 | { |
| 293 | return -ENOTSUPP; |
| 294 | } |
| 295 | |
| 296 | static inline void wcd_mbhc_stop(struct wcd_mbhc *mbhc) |
| 297 | { |
| 298 | } |
| 299 | |
| 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 | |
| 309 | static inline void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type) |
| 310 | { |
| 311 | } |
| 312 | |
| 313 | static inline int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc) |
| 314 | { |
| 315 | return -ENOTSUPP; |
| 316 | } |
| 317 | |
| 318 | static inline int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event) |
| 319 | { |
| 320 | return -ENOTSUPP; |
| 321 | } |
| 322 | |
| 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 | |
| 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 | } |
| 338 | static inline void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) |
| 339 | { |
| 340 | } |
| 341 | #endif |
| 342 | |
| 343 | #endif /* __WCD_MBHC_V2_H__ */ |
| 344 | |