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