blob: 29dd84a4e018337f2097089e0399ae7e3e3d97f2 [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 Pateriya95466b12013-05-09 20:08:46 +053019#define WCD9XXX_CFILT_EXT_PRCHG_EN 0x30
20#define WCD9XXX_CFILT_EXT_PRCHG_DSBL 0x00
Joonwoo Parka8890262012-10-15 12:04:27 -070021
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -070022#define WCD9XXX_USLEEP_RANGE_MARGIN_US 100
23
Joonwoo Parka8890262012-10-15 12:04:27 -070024struct mbhc_micbias_regs {
25 u16 cfilt_val;
26 u16 cfilt_ctl;
27 u16 mbhc_reg;
28 u16 int_rbias;
29 u16 ctl_reg;
30 u8 cfilt_sel;
31};
32
Joonwoo Park73375212013-05-07 12:42:44 -070033enum mbhc_v_index {
34 MBHC_V_IDX_CFILT,
35 MBHC_V_IDX_VDDIO,
36 MBHC_V_IDX_NUM,
37};
38
Joonwoo Park520a0f92013-05-14 19:39:58 -070039enum mbhc_cal_type {
40 MBHC_CAL_MCLK,
41 MBHC_CAL_RCO,
42 MBHC_CAL_NUM,
43};
44
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -070045enum mbhc_impedance_detect_stages {
46 PRE_MEAS,
47 POST_MEAS,
48 PA_DISABLE,
49};
50
Joonwoo Parka8890262012-10-15 12:04:27 -070051/* Data used by MBHC */
52struct mbhc_internal_cal_data {
53 u16 dce_z;
Phani Kumar Uppalapati3559a7e2013-06-24 13:52:31 -070054 u16 dce_nsc_cs_z;
Joonwoo Parka8890262012-10-15 12:04:27 -070055 u16 dce_mb;
56 u16 sta_z;
57 u16 sta_mb;
58 u32 t_sta_dce;
59 u32 t_dce;
60 u32 t_sta;
61 u32 micb_mv;
Joonwoo Park73375212013-05-07 12:42:44 -070062 u16 v_ins_hu[MBHC_V_IDX_NUM];
63 u16 v_ins_h[MBHC_V_IDX_NUM];
64 u16 v_b1_hu[MBHC_V_IDX_NUM];
65 u16 v_b1_h[MBHC_V_IDX_NUM];
66 u16 v_brh[MBHC_V_IDX_NUM];
Joonwoo Parka8890262012-10-15 12:04:27 -070067 u16 v_brl;
68 u16 v_no_mic;
Joonwoo Parka8890262012-10-15 12:04:27 -070069 s16 v_inval_ins_low;
70 s16 v_inval_ins_high;
Phani Kumar Uppalapati3559a7e2013-06-24 13:52:31 -070071 u16 v_cs_ins_h;
Joonwoo Parka8890262012-10-15 12:04:27 -070072};
73
74enum wcd9xxx_mbhc_plug_type {
75 PLUG_TYPE_INVALID = -1,
76 PLUG_TYPE_NONE,
77 PLUG_TYPE_HEADSET,
78 PLUG_TYPE_HEADPHONE,
79 PLUG_TYPE_HIGH_HPH,
80 PLUG_TYPE_GND_MIC_SWAP,
81};
82
83enum wcd9xxx_micbias_num {
84 MBHC_MICBIAS_INVALID = -1,
85 MBHC_MICBIAS1,
86 MBHC_MICBIAS2,
87 MBHC_MICBIAS3,
88 MBHC_MICBIAS4,
89};
90
Joonwoo Parkccccba72013-04-26 11:19:46 -070091enum wcd9xx_mbhc_micbias_enable_bits {
92 MBHC_MICBIAS_ENABLE_THRESHOLD_HEADSET,
93 MBHC_MICBIAS_ENABLE_REGULAR_HEADSET,
94};
95
Phani Kumar Uppalapati3559a7e2013-06-24 13:52:31 -070096enum wcd9xx_mbhc_cs_enable_bits {
97 MBHC_CS_ENABLE_POLLING,
98 MBHC_CS_ENABLE_INSERTION,
99 MBHC_CS_ENABLE_REMOVAL,
100};
101
Joonwoo Parka8890262012-10-15 12:04:27 -0700102enum wcd9xxx_mbhc_state {
103 MBHC_STATE_NONE = -1,
104 MBHC_STATE_POTENTIAL,
105 MBHC_STATE_POTENTIAL_RECOVERY,
106 MBHC_STATE_RELEASE,
107};
108
109enum wcd9xxx_mbhc_btn_det_mem {
110 MBHC_BTN_DET_V_BTN_LOW,
111 MBHC_BTN_DET_V_BTN_HIGH,
112 MBHC_BTN_DET_N_READY,
113 MBHC_BTN_DET_N_CIC,
114 MBHC_BTN_DET_GAIN
115};
116
117enum wcd9xxx_mbhc_clk_freq {
118 TAIKO_MCLK_12P2MHZ = 0,
119 TAIKO_MCLK_9P6MHZ,
120 TAIKO_NUM_CLK_FREQS,
121};
122
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700123enum wcd9xxx_mbhc_event_state {
124 MBHC_EVENT_PA_HPHL,
125 MBHC_EVENT_PA_HPHR,
126};
127
Joonwoo Parka8890262012-10-15 12:04:27 -0700128struct wcd9xxx_mbhc_general_cfg {
129 u8 t_ldoh;
130 u8 t_bg_fast_settle;
131 u8 t_shutdown_plug_rem;
132 u8 mbhc_nsa;
133 u8 mbhc_navg;
134 u8 v_micbias_l;
135 u8 v_micbias;
136 u8 mbhc_reserved;
137 u16 settle_wait;
138 u16 t_micbias_rampup;
139 u16 t_micbias_rampdown;
140 u16 t_supply_bringup;
141} __packed;
142
143struct wcd9xxx_mbhc_plug_detect_cfg {
144 u32 mic_current;
145 u32 hph_current;
146 u16 t_mic_pid;
147 u16 t_ins_complete;
148 u16 t_ins_retry;
149 u16 v_removal_delta;
150 u8 micbias_slow_ramp;
151 u8 reserved0;
152 u8 reserved1;
153 u8 reserved2;
154} __packed;
155
156struct wcd9xxx_mbhc_plug_type_cfg {
157 u8 av_detect;
158 u8 mono_detect;
159 u8 num_ins_tries;
160 u8 reserved0;
161 s16 v_no_mic;
162 s16 v_av_min;
163 s16 v_av_max;
164 s16 v_hs_min;
165 s16 v_hs_max;
166 u16 reserved1;
167} __packed;
168
169struct wcd9xxx_mbhc_btn_detect_cfg {
170 s8 c[8];
171 u8 nc;
172 u8 n_meas;
173 u8 mbhc_nsc;
174 u8 n_btn_meas;
175 u8 n_btn_con;
176 u8 num_btn;
177 u8 reserved0;
178 u8 reserved1;
179 u16 t_poll;
180 u16 t_bounce_wait;
181 u16 t_rel_timeout;
182 s16 v_btn_press_delta_sta;
183 s16 v_btn_press_delta_cic;
184 u16 t_btn0_timeout;
185 s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
186 s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
187 u8 _n_ready[TAIKO_NUM_CLK_FREQS];
188 u8 _n_cic[TAIKO_NUM_CLK_FREQS];
189 u8 _gain[TAIKO_NUM_CLK_FREQS];
190} __packed;
191
192struct wcd9xxx_mbhc_imped_detect_cfg {
193 u8 _hs_imped_detect;
194 u8 _n_rload;
195 u8 _hph_keep_on;
196 u8 _repeat_rload_calc;
197 u16 _t_dac_ramp_time;
198 u16 _rhph_high;
199 u16 _rhph_low;
200 u16 _rload[0]; /* rload[n_rload] */
201 u16 _alpha[0]; /* alpha[n_rload] */
202 u16 _beta[3];
203} __packed;
204
205struct wcd9xxx_mbhc_config {
206 bool read_fw_bin;
207 /*
208 * void* calibration contains:
209 * struct wcd9xxx_mbhc_general_cfg generic;
210 * struct wcd9xxx_mbhc_plug_detect_cfg plug_det;
211 * struct wcd9xxx_mbhc_plug_type_cfg plug_type;
212 * struct wcd9xxx_mbhc_btn_detect_cfg btn_det;
213 * struct wcd9xxx_mbhc_imped_detect_cfg imped_det;
214 * Note: various size depends on btn_det->num_btn
215 */
216 void *calibration;
217 enum wcd9xxx_micbias_num micbias;
218 int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
219 unsigned int mclk_rate;
220 unsigned int gpio;
221 unsigned int gpio_irq;
222 int gpio_level_insert;
223 bool insert_detect; /* codec has own MBHC_INSERT_DETECT */
Joonwoo Park80a01172012-10-15 16:05:23 -0700224 bool detect_extn_cable;
Joonwoo Parkccccba72013-04-26 11:19:46 -0700225 /* bit mask of enum wcd9xx_mbhc_micbias_enable_bits */
226 unsigned long micbias_enable_flags;
Joonwoo Parka8890262012-10-15 12:04:27 -0700227 /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
228 bool (*swap_gnd_mic) (struct snd_soc_codec *);
Phani Kumar Uppalapati3559a7e2013-06-24 13:52:31 -0700229 unsigned long cs_enable_flags;
Bhalchandra Gajare6a2296b2013-09-19 13:15:08 -0700230 bool use_int_rbias;
Simmi Pateriya4b5159f2013-11-14 10:43:24 +0530231 bool do_recalibration;
Simmi Pateriya4e545052013-11-15 07:41:06 +0530232 bool use_vddio_meas;
Joonwoo Parka8890262012-10-15 12:04:27 -0700233};
234
Simmi Pateriya95466b12013-05-09 20:08:46 +0530235struct wcd9xxx_cfilt_mode {
236 u8 reg_mode_val;
237 u8 cur_mode_val;
Bhalchandra Gajare8e5fe252013-07-15 19:42:21 -0700238 u8 reg_mask;
Simmi Pateriya95466b12013-05-09 20:08:46 +0530239};
240
Bhalchandra Gajare16748932013-10-01 18:16:05 -0700241struct wcd9xxx_mbhc_intr {
242 int poll_plug_rem;
243 int shortavg_complete;
244 int potential_button_press;
245 int button_release;
246 int dce_est_complete;
247 int insertion;
248 int hph_left_ocp;
249 int hph_right_ocp;
250 int hs_jack_switch;
251};
252
Simmi Pateriya95466b12013-05-09 20:08:46 +0530253struct wcd9xxx_mbhc_cb {
254 void (*enable_mux_bias_block) (struct snd_soc_codec *);
255 void (*cfilt_fast_mode) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
256 void (*codec_specific_cal) (struct snd_soc_codec *,
257 struct wcd9xxx_mbhc *);
Simmi Pateriya95466b12013-05-09 20:08:46 +0530258 struct wcd9xxx_cfilt_mode (*switch_cfilt_mode) (struct wcd9xxx_mbhc *,
259 bool);
260 void (*select_cfilt) (struct snd_soc_codec *, struct wcd9xxx_mbhc *);
Bhalchandra Gajare8e5fe252013-07-15 19:42:21 -0700261 enum wcd9xxx_cdc_type (*get_cdc_type) (void);
262 void (*enable_clock_gate) (struct snd_soc_codec *, bool);
Phani Kumar Uppalapati01a77e12013-08-08 15:31:35 -0700263 int (*setup_zdet) (struct wcd9xxx_mbhc *,
264 enum mbhc_impedance_detect_stages stage);
265 void (*compute_impedance) (s16 *, s16 *, uint32_t *, uint32_t *);
Bhalchandra Gajare2763c722013-09-11 17:10:22 -0700266 void (*enable_mbhc_txfe) (struct snd_soc_codec *, bool);
Bhalchandra Gajaredd01bf32013-09-05 14:00:29 -0700267 int (*enable_mb_source) (struct snd_soc_codec *, bool);
Bhalchandra Gajare6a2296b2013-09-19 13:15:08 -0700268 void (*setup_int_rbias) (struct snd_soc_codec *, bool);
Bhalchandra Gajaref19a9262013-09-19 15:40:08 -0700269 void (*pull_mb_to_vddio) (struct snd_soc_codec *, bool);
Simmi Pateriya95466b12013-05-09 20:08:46 +0530270};
271
Joonwoo Parka8890262012-10-15 12:04:27 -0700272struct wcd9xxx_mbhc {
273 bool polling_active;
274 /* Delayed work to report long button press */
275 struct delayed_work mbhc_btn_dwork;
276 int buttons_pressed;
277 enum wcd9xxx_mbhc_state mbhc_state;
278 struct wcd9xxx_mbhc_config *mbhc_cfg;
Simmi Pateriya95466b12013-05-09 20:08:46 +0530279 const struct wcd9xxx_mbhc_cb *mbhc_cb;
Joonwoo Parka8890262012-10-15 12:04:27 -0700280
281 struct mbhc_internal_cal_data mbhc_data;
282
283 struct mbhc_micbias_regs mbhc_bias_regs;
284 bool mbhc_micbias_switched;
285
286 u32 hph_status; /* track headhpone status */
287 u8 hphlocp_cnt; /* headphone left ocp retry */
288 u8 hphrocp_cnt; /* headphone right ocp retry */
289
290 /* Work to perform MBHC Firmware Read */
291 struct delayed_work mbhc_firmware_dwork;
292 const struct firmware *mbhc_fw;
293
294 struct delayed_work mbhc_insert_dwork;
295
296 u8 current_plug;
297 struct work_struct correct_plug_swch;
298 /*
299 * Work to perform polling on microphone voltage
300 * in order to correct plug type once plug type
301 * is detected as headphone
302 */
303 struct work_struct correct_plug_noswch;
304 bool hs_detect_work_stop;
305
306 bool lpi_enabled; /* low power insertion detection */
307 bool in_swch_irq_handler;
308
309 struct wcd9xxx_resmgr *resmgr;
310 struct snd_soc_codec *codec;
311
312 bool no_mic_headset_override;
313
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700314 /* track PA/DAC state to sync with userspace */
Joonwoo Parka8890262012-10-15 12:04:27 -0700315 unsigned long hph_pa_dac_state;
Joonwoo Park2cee50a2013-05-15 14:09:06 -0700316 /*
317 * save codec's state with resmgr event notification
318 * bit flags of enum wcd9xxx_mbhc_event_state
319 */
320 unsigned long event_state;
Joonwoo Parka8890262012-10-15 12:04:27 -0700321
322 unsigned long mbhc_last_resume; /* in jiffies */
323
324 bool insert_detect_level_insert;
325
326 struct snd_soc_jack headset_jack;
327 struct snd_soc_jack button_jack;
328
329 struct notifier_block nblock;
330
Joonwoo Parkccccba72013-04-26 11:19:46 -0700331 bool micbias_enable;
332 int (*micbias_enable_cb) (struct snd_soc_codec*, bool);
333
Phani Kumar Uppalapatid7549e12013-07-12 22:22:03 -0700334 bool impedance_detect;
Joonwoo Parkb755e9e2013-05-28 13:14:05 -0700335 /* impedance of hphl and hphr */
336 uint32_t zl, zr;
337
Phani Kumar Uppalapati43bc4152013-05-24 00:44:20 -0700338 u32 rco_clk_rate;
339
Joonwoo Park218e73f2013-08-21 16:22:18 -0700340 bool update_z;
Bhalchandra Gajare16748932013-10-01 18:16:05 -0700341 /* Holds codec specific interrupt mapping */
342 const struct wcd9xxx_mbhc_intr *intr_ids;
343
Joonwoo Parka8890262012-10-15 12:04:27 -0700344#ifdef CONFIG_DEBUG_FS
345 struct dentry *debugfs_poke;
346 struct dentry *debugfs_mbhc;
347#endif
348};
349
350#define WCD9XXX_MBHC_CAL_SIZE(buttons, rload) ( \
351 sizeof(enum wcd9xxx_micbias_num) + \
352 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
353 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
354 ((sizeof(s16) + sizeof(s16)) * buttons) + \
355 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
356 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
357 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
358 ((sizeof(u16) + sizeof(u16)) * rload) \
359 )
360
361#define WCD9XXX_MBHC_CAL_GENERAL_PTR(cali) ( \
362 (struct wcd9xxx_mbhc_general_cfg *) cali)
363#define WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali) ( \
364 (struct wcd9xxx_mbhc_plug_detect_cfg *) \
365 &(WCD9XXX_MBHC_CAL_GENERAL_PTR(cali)[1]))
366#define WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
367 (struct wcd9xxx_mbhc_plug_type_cfg *) \
368 &(WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
369#define WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali) ( \
370 (struct wcd9xxx_mbhc_btn_detect_cfg *) \
371 &(WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
372#define WCD9XXX_MBHC_CAL_IMPED_DET_PTR(cali) ( \
373 (struct wcd9xxx_mbhc_imped_detect_cfg *) \
374 (((void *)&WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
375 (WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
376 (sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
377 sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
378 )
379
380/* minimum size of calibration data assuming there is only one button and
381 * one rload.
382 */
383#define WCD9XXX_MBHC_CAL_MIN_SIZE ( \
384 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
385 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
386 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
387 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
388 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
389 (sizeof(u16) * 2) \
390 )
391
392#define WCD9XXX_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
393 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
394 (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
395 sizeof(cfg_ptr->_v_btn_high[0]))))
396
397#define WCD9XXX_MBHC_CAL_IMPED_MIN_SZ ( \
398 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + sizeof(u16) * 2)
399
400#define WCD9XXX_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
401 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
402 (cfg_ptr->_n_rload * \
403 (sizeof(cfg_ptr->_rload[0]) + sizeof(cfg_ptr->_alpha[0]))))
404
405int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
406 struct wcd9xxx_mbhc_config *mbhc_cfg);
Joonwoo Parke7d724e2013-08-19 15:51:01 -0700407void wcd9xxx_mbhc_stop(struct wcd9xxx_mbhc *mbhc);
Joonwoo Parka8890262012-10-15 12:04:27 -0700408int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
Joonwoo Parkccccba72013-04-26 11:19:46 -0700409 struct snd_soc_codec *codec,
410 int (*micbias_enable_cb) (struct snd_soc_codec*, bool),
Simmi Pateriya95466b12013-05-09 20:08:46 +0530411 const struct wcd9xxx_mbhc_cb *mbhc_cb,
Bhalchandra Gajare16748932013-10-01 18:16:05 -0700412 const struct wcd9xxx_mbhc_intr *mbhc_cdc_intr_ids,
Phani Kumar Uppalapatid7549e12013-07-12 22:22:03 -0700413 int rco_clk_rate,
414 bool impedance_det_en);
Joonwoo Parka8890262012-10-15 12:04:27 -0700415void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
416void *wcd9xxx_mbhc_cal_btn_det_mp(
417 const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
418 const enum wcd9xxx_mbhc_btn_det_mem mem);
Joonwoo Parkb755e9e2013-05-28 13:14:05 -0700419int wcd9xxx_mbhc_get_impedance(struct wcd9xxx_mbhc *mbhc, uint32_t *zl,
420 uint32_t *zr);
Joonwoo Parka8890262012-10-15 12:04:27 -0700421#endif /* __WCD9XXX_MBHC_H__ */