blob: 71a62b281526142b9e760f0faf6fb721fa2edda6 [file] [log] [blame]
Simmi Pateriya0a44d842013-04-03 01:12:42 +05301/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
Joonwoo Parka8890262012-10-15 12:04:27 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#ifndef __WCD9XXX_MBHC_H__
13#define __WCD9XXX_MBHC_H__
14
15#include "wcd9xxx-resmgr.h"
16
17#define WCD9XXX_CFILT_FAST_MODE 0x00
18#define WCD9XXX_CFILT_SLOW_MODE 0x40
Simmi Pateriya0a44d842013-04-03 01:12:42 +053019#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x70
20#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x40
Joonwoo Parka8890262012-10-15 12:04:27 -070021
22struct mbhc_micbias_regs {
23 u16 cfilt_val;
24 u16 cfilt_ctl;
25 u16 mbhc_reg;
26 u16 int_rbias;
27 u16 ctl_reg;
28 u8 cfilt_sel;
29};
30
Joonwoo Park73375212013-05-07 12:42:44 -070031enum mbhc_v_index {
32 MBHC_V_IDX_CFILT,
33 MBHC_V_IDX_VDDIO,
34 MBHC_V_IDX_NUM,
35};
36
Joonwoo Park520a0f92013-05-14 19:39:58 -070037enum mbhc_cal_type {
38 MBHC_CAL_MCLK,
39 MBHC_CAL_RCO,
40 MBHC_CAL_NUM,
41};
42
Joonwoo Parka8890262012-10-15 12:04:27 -070043/* Data used by MBHC */
44struct mbhc_internal_cal_data {
45 u16 dce_z;
46 u16 dce_mb;
47 u16 sta_z;
48 u16 sta_mb;
49 u32 t_sta_dce;
50 u32 t_dce;
51 u32 t_sta;
52 u32 micb_mv;
Joonwoo Park73375212013-05-07 12:42:44 -070053 u16 v_ins_hu[MBHC_V_IDX_NUM];
54 u16 v_ins_h[MBHC_V_IDX_NUM];
55 u16 v_b1_hu[MBHC_V_IDX_NUM];
56 u16 v_b1_h[MBHC_V_IDX_NUM];
57 u16 v_brh[MBHC_V_IDX_NUM];
Joonwoo Parka8890262012-10-15 12:04:27 -070058 u16 v_brl;
59 u16 v_no_mic;
Joonwoo Parka8890262012-10-15 12:04:27 -070060 s16 v_inval_ins_low;
61 s16 v_inval_ins_high;
62};
63
Simmi Pateriya0a44d842013-04-03 01:12:42 +053064enum wcd9xxx_mbhc_version {
65 WCD9XXX_MBHC_VERSION_UNKNOWN = 0,
66 WCD9XXX_MBHC_VERSION_TAIKO,
67 WCD9XXX_MBHC_VERSION_TAPAN,
68};
69
Joonwoo Parka8890262012-10-15 12:04:27 -070070enum wcd9xxx_mbhc_plug_type {
71 PLUG_TYPE_INVALID = -1,
72 PLUG_TYPE_NONE,
73 PLUG_TYPE_HEADSET,
74 PLUG_TYPE_HEADPHONE,
75 PLUG_TYPE_HIGH_HPH,
76 PLUG_TYPE_GND_MIC_SWAP,
77};
78
79enum wcd9xxx_micbias_num {
80 MBHC_MICBIAS_INVALID = -1,
81 MBHC_MICBIAS1,
82 MBHC_MICBIAS2,
83 MBHC_MICBIAS3,
84 MBHC_MICBIAS4,
85};
86
Joonwoo Parkccccba72013-04-26 11:19:46 -070087enum wcd9xx_mbhc_micbias_enable_bits {
88 MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET,
89 MBHC_MICBIAS_ENABLE_REGULAR_HEADSET,
90};
91
Joonwoo Parka8890262012-10-15 12:04:27 -070092enum wcd9xxx_mbhc_state {
93 MBHC_STATE_NONE = -1,
94 MBHC_STATE_POTENTIAL,
95 MBHC_STATE_POTENTIAL_RECOVERY,
96 MBHC_STATE_RELEASE,
97};
98
99enum wcd9xxx_mbhc_btn_det_mem {
100 MBHC_BTN_DET_V_BTN_LOW,
101 MBHC_BTN_DET_V_BTN_HIGH,
102 MBHC_BTN_DET_N_READY,
103 MBHC_BTN_DET_N_CIC,
104 MBHC_BTN_DET_GAIN
105};
106
107enum wcd9xxx_mbhc_clk_freq {
108 TAIKO_MCLK_12P2MHZ = 0,
109 TAIKO_MCLK_9P6MHZ,
110 TAIKO_NUM_CLK_FREQS,
111};
112
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700113enum wcd9xxx_mbhc_event_state {
114 MBHC_EVENT_PA_HPHL,
115 MBHC_EVENT_PA_HPHR,
116};
117
Joonwoo Parka8890262012-10-15 12:04:27 -0700118struct wcd9xxx_mbhc_general_cfg {
119 u8 t_ldoh;
120 u8 t_bg_fast_settle;
121 u8 t_shutdown_plug_rem;
122 u8 mbhc_nsa;
123 u8 mbhc_navg;
124 u8 v_micbias_l;
125 u8 v_micbias;
126 u8 mbhc_reserved;
127 u16 settle_wait;
128 u16 t_micbias_rampup;
129 u16 t_micbias_rampdown;
130 u16 t_supply_bringup;
131} __packed;
132
133struct wcd9xxx_mbhc_plug_detect_cfg {
134 u32 mic_current;
135 u32 hph_current;
136 u16 t_mic_pid;
137 u16 t_ins_complete;
138 u16 t_ins_retry;
139 u16 v_removal_delta;
140 u8 micbias_slow_ramp;
141 u8 reserved0;
142 u8 reserved1;
143 u8 reserved2;
144} __packed;
145
146struct wcd9xxx_mbhc_plug_type_cfg {
147 u8 av_detect;
148 u8 mono_detect;
149 u8 num_ins_tries;
150 u8 reserved0;
151 s16 v_no_mic;
152 s16 v_av_min;
153 s16 v_av_max;
154 s16 v_hs_min;
155 s16 v_hs_max;
156 u16 reserved1;
157} __packed;
158
159struct wcd9xxx_mbhc_btn_detect_cfg {
160 s8 c[8];
161 u8 nc;
162 u8 n_meas;
163 u8 mbhc_nsc;
164 u8 n_btn_meas;
165 u8 n_btn_con;
166 u8 num_btn;
167 u8 reserved0;
168 u8 reserved1;
169 u16 t_poll;
170 u16 t_bounce_wait;
171 u16 t_rel_timeout;
172 s16 v_btn_press_delta_sta;
173 s16 v_btn_press_delta_cic;
174 u16 t_btn0_timeout;
175 s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
176 s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
177 u8 _n_ready[TAIKO_NUM_CLK_FREQS];
178 u8 _n_cic[TAIKO_NUM_CLK_FREQS];
179 u8 _gain[TAIKO_NUM_CLK_FREQS];
180} __packed;
181
182struct wcd9xxx_mbhc_imped_detect_cfg {
183 u8 _hs_imped_detect;
184 u8 _n_rload;
185 u8 _hph_keep_on;
186 u8 _repeat_rload_calc;
187 u16 _t_dac_ramp_time;
188 u16 _rhph_high;
189 u16 _rhph_low;
190 u16 _rload[0]; /* rload[n_rload] */
191 u16 _alpha[0]; /* alpha[n_rload] */
192 u16 _beta[3];
193} __packed;
194
195struct wcd9xxx_mbhc_config {
196 bool read_fw_bin;
197 /*
198 * void* calibration contains:
199 * struct wcd9xxx_mbhc_general_cfg generic;
200 * struct wcd9xxx_mbhc_plug_detect_cfg plug_det;
201 * struct wcd9xxx_mbhc_plug_type_cfg plug_type;
202 * struct wcd9xxx_mbhc_btn_detect_cfg btn_det;
203 * struct wcd9xxx_mbhc_imped_detect_cfg imped_det;
204 * Note: various size depends on btn_det->num_btn
205 */
206 void *calibration;
207 enum wcd9xxx_micbias_num micbias;
208 int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
209 unsigned int mclk_rate;
210 unsigned int gpio;
211 unsigned int gpio_irq;
212 int gpio_level_insert;
213 bool insert_detect; /* codec has own MBHC_INSERT_DETECT */
Joonwoo Park80a01172012-10-15 16:05:23 -0700214 bool detect_extn_cable;
Joonwoo Parkccccba72013-04-26 11:19:46 -0700215 /* bit mask of enum wcd9xx_mbhc_micbias_enable_bits */
216 unsigned long micbias_enable_flags;
Joonwoo Parka8890262012-10-15 12:04:27 -0700217 /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
218 bool (*swap_gnd_mic) (struct snd_soc_codec *);
219};
220
221struct wcd9xxx_mbhc {
222 bool polling_active;
223 /* Delayed work to report long button press */
224 struct delayed_work mbhc_btn_dwork;
225 int buttons_pressed;
226 enum wcd9xxx_mbhc_state mbhc_state;
227 struct wcd9xxx_mbhc_config *mbhc_cfg;
228
229 struct mbhc_internal_cal_data mbhc_data;
230
231 struct mbhc_micbias_regs mbhc_bias_regs;
232 bool mbhc_micbias_switched;
233
234 u32 hph_status; /* track headhpone status */
235 u8 hphlocp_cnt; /* headphone left ocp retry */
236 u8 hphrocp_cnt; /* headphone right ocp retry */
237
238 /* Work to perform MBHC Firmware Read */
239 struct delayed_work mbhc_firmware_dwork;
240 const struct firmware *mbhc_fw;
241
242 struct delayed_work mbhc_insert_dwork;
243
244 u8 current_plug;
245 struct work_struct correct_plug_swch;
246 /*
247 * Work to perform polling on microphone voltage
248 * in order to correct plug type once plug type
249 * is detected as headphone
250 */
251 struct work_struct correct_plug_noswch;
252 bool hs_detect_work_stop;
253
254 bool lpi_enabled; /* low power insertion detection */
255 bool in_swch_irq_handler;
256
257 struct wcd9xxx_resmgr *resmgr;
258 struct snd_soc_codec *codec;
259
260 bool no_mic_headset_override;
261
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700262 /* track PA/DAC state to sync with userspace */
Joonwoo Parka8890262012-10-15 12:04:27 -0700263 unsigned long hph_pa_dac_state;
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700264 /*
265 * save codec's state with resmgr event notification
266 * bit flags of enum wcd9xxx_mbhc_event_state
267 */
268 unsigned long event_state;
Joonwoo Parka8890262012-10-15 12:04:27 -0700269
270 unsigned long mbhc_last_resume; /* in jiffies */
271
272 bool insert_detect_level_insert;
273
274 struct snd_soc_jack headset_jack;
275 struct snd_soc_jack button_jack;
276
277 struct notifier_block nblock;
278
Joonwoo Parkccccba72013-04-26 11:19:46 -0700279 bool micbias_enable;
280 int (*micbias_enable_cb) (struct snd_soc_codec*, bool);
281
Simmi Pateriya0a44d842013-04-03 01:12:42 +0530282 enum wcd9xxx_mbhc_version mbhc_version;
283
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -0700284 u32 rco_clk_rate;
285
Joonwoo Parka8890262012-10-15 12:04:27 -0700286#ifdef CONFIG_DEBUG_FS
287 struct dentry *debugfs_poke;
288 struct dentry *debugfs_mbhc;
289#endif
290};
291
292#define WCD9XXX_MBHC_CAL_SIZE(buttons, rload) ( \
293 sizeof(enum wcd9xxx_micbias_num) + \
294 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
295 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
296 ((sizeof(s16) + sizeof(s16)) * buttons) + \
297 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
298 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
299 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
300 ((sizeof(u16) + sizeof(u16)) * rload) \
301 )
302
303#define WCD9XXX_MBHC_CAL_GENERAL_PTR(cali) ( \
304 (struct wcd9xxx_mbhc_general_cfg *) cali)
305#define WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali) ( \
306 (struct wcd9xxx_mbhc_plug_detect_cfg *) \
307 &(WCD9XXX_MBHC_CAL_GENERAL_PTR(cali)[1]))
308#define WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
309 (struct wcd9xxx_mbhc_plug_type_cfg *) \
310 &(WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
311#define WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali) ( \
312 (struct wcd9xxx_mbhc_btn_detect_cfg *) \
313 &(WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
314#define WCD9XXX_MBHC_CAL_IMPED_DET_PTR(cali) ( \
315 (struct wcd9xxx_mbhc_imped_detect_cfg *) \
316 (((void *)&WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
317 (WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
318 (sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
319 sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
320 )
321
322/* minimum size of calibration data assuming there is only one button and
323 * one rload.
324 */
325#define WCD9XXX_MBHC_CAL_MIN_SIZE ( \
326 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
327 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
328 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
329 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
330 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
331 (sizeof(u16) * 2) \
332 )
333
334#define WCD9XXX_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
335 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
336 (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
337 sizeof(cfg_ptr->_v_btn_high[0]))))
338
339#define WCD9XXX_MBHC_CAL_IMPED_MIN_SZ ( \
340 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + sizeof(u16) * 2)
341
342#define WCD9XXX_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
343 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
344 (cfg_ptr->_n_rload * \
345 (sizeof(cfg_ptr->_rload[0]) + sizeof(cfg_ptr->_alpha[0]))))
346
347int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
348 struct wcd9xxx_mbhc_config *mbhc_cfg);
349int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
Joonwoo Parkccccba72013-04-26 11:19:46 -0700350 struct snd_soc_codec *codec,
351 int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -0700352 int version,
353 int rco_clk_rate);
Joonwoo Parka8890262012-10-15 12:04:27 -0700354void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
355void *wcd9xxx_mbhc_cal_btn_det_mp(
356 const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
357 const enum wcd9xxx_mbhc_btn_det_mem mem);
358#endif /* __WCD9XXX_MBHC_H__ */