blob: fb1dfdc3fdcc09f6017eabd94da6c858694b1185 [file] [log] [blame]
Joonwoo Parka8890262012-10-15 12:04:27 -07001/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
2 *
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
19
20struct mbhc_micbias_regs {
21 u16 cfilt_val;
22 u16 cfilt_ctl;
23 u16 mbhc_reg;
24 u16 int_rbias;
25 u16 ctl_reg;
26 u8 cfilt_sel;
27};
28
29/* Data used by MBHC */
30struct mbhc_internal_cal_data {
31 u16 dce_z;
32 u16 dce_mb;
33 u16 sta_z;
34 u16 sta_mb;
35 u32 t_sta_dce;
36 u32 t_dce;
37 u32 t_sta;
38 u32 micb_mv;
39 u16 v_ins_hu;
40 u16 v_ins_h;
41 u16 v_b1_hu;
42 u16 v_b1_h;
43 u16 v_b1_huc;
44 u16 v_brh;
45 u16 v_brl;
46 u16 v_no_mic;
47 s16 adj_v_hs_max;
48 u16 adj_v_ins_hu;
49 u16 adj_v_ins_h;
50 s16 v_inval_ins_low;
51 s16 v_inval_ins_high;
52};
53
54enum wcd9xxx_mbhc_plug_type {
55 PLUG_TYPE_INVALID = -1,
56 PLUG_TYPE_NONE,
57 PLUG_TYPE_HEADSET,
58 PLUG_TYPE_HEADPHONE,
59 PLUG_TYPE_HIGH_HPH,
60 PLUG_TYPE_GND_MIC_SWAP,
61};
62
63enum wcd9xxx_micbias_num {
64 MBHC_MICBIAS_INVALID = -1,
65 MBHC_MICBIAS1,
66 MBHC_MICBIAS2,
67 MBHC_MICBIAS3,
68 MBHC_MICBIAS4,
69};
70
71enum wcd9xxx_mbhc_state {
72 MBHC_STATE_NONE = -1,
73 MBHC_STATE_POTENTIAL,
74 MBHC_STATE_POTENTIAL_RECOVERY,
75 MBHC_STATE_RELEASE,
76};
77
78enum wcd9xxx_mbhc_btn_det_mem {
79 MBHC_BTN_DET_V_BTN_LOW,
80 MBHC_BTN_DET_V_BTN_HIGH,
81 MBHC_BTN_DET_N_READY,
82 MBHC_BTN_DET_N_CIC,
83 MBHC_BTN_DET_GAIN
84};
85
86enum wcd9xxx_mbhc_clk_freq {
87 TAIKO_MCLK_12P2MHZ = 0,
88 TAIKO_MCLK_9P6MHZ,
89 TAIKO_NUM_CLK_FREQS,
90};
91
92struct wcd9xxx_mbhc_general_cfg {
93 u8 t_ldoh;
94 u8 t_bg_fast_settle;
95 u8 t_shutdown_plug_rem;
96 u8 mbhc_nsa;
97 u8 mbhc_navg;
98 u8 v_micbias_l;
99 u8 v_micbias;
100 u8 mbhc_reserved;
101 u16 settle_wait;
102 u16 t_micbias_rampup;
103 u16 t_micbias_rampdown;
104 u16 t_supply_bringup;
105} __packed;
106
107struct wcd9xxx_mbhc_plug_detect_cfg {
108 u32 mic_current;
109 u32 hph_current;
110 u16 t_mic_pid;
111 u16 t_ins_complete;
112 u16 t_ins_retry;
113 u16 v_removal_delta;
114 u8 micbias_slow_ramp;
115 u8 reserved0;
116 u8 reserved1;
117 u8 reserved2;
118} __packed;
119
120struct wcd9xxx_mbhc_plug_type_cfg {
121 u8 av_detect;
122 u8 mono_detect;
123 u8 num_ins_tries;
124 u8 reserved0;
125 s16 v_no_mic;
126 s16 v_av_min;
127 s16 v_av_max;
128 s16 v_hs_min;
129 s16 v_hs_max;
130 u16 reserved1;
131} __packed;
132
133struct wcd9xxx_mbhc_btn_detect_cfg {
134 s8 c[8];
135 u8 nc;
136 u8 n_meas;
137 u8 mbhc_nsc;
138 u8 n_btn_meas;
139 u8 n_btn_con;
140 u8 num_btn;
141 u8 reserved0;
142 u8 reserved1;
143 u16 t_poll;
144 u16 t_bounce_wait;
145 u16 t_rel_timeout;
146 s16 v_btn_press_delta_sta;
147 s16 v_btn_press_delta_cic;
148 u16 t_btn0_timeout;
149 s16 _v_btn_low[0]; /* v_btn_low[num_btn] */
150 s16 _v_btn_high[0]; /* v_btn_high[num_btn] */
151 u8 _n_ready[TAIKO_NUM_CLK_FREQS];
152 u8 _n_cic[TAIKO_NUM_CLK_FREQS];
153 u8 _gain[TAIKO_NUM_CLK_FREQS];
154} __packed;
155
156struct wcd9xxx_mbhc_imped_detect_cfg {
157 u8 _hs_imped_detect;
158 u8 _n_rload;
159 u8 _hph_keep_on;
160 u8 _repeat_rload_calc;
161 u16 _t_dac_ramp_time;
162 u16 _rhph_high;
163 u16 _rhph_low;
164 u16 _rload[0]; /* rload[n_rload] */
165 u16 _alpha[0]; /* alpha[n_rload] */
166 u16 _beta[3];
167} __packed;
168
169struct wcd9xxx_mbhc_config {
170 bool read_fw_bin;
171 /*
172 * void* calibration contains:
173 * struct wcd9xxx_mbhc_general_cfg generic;
174 * struct wcd9xxx_mbhc_plug_detect_cfg plug_det;
175 * struct wcd9xxx_mbhc_plug_type_cfg plug_type;
176 * struct wcd9xxx_mbhc_btn_detect_cfg btn_det;
177 * struct wcd9xxx_mbhc_imped_detect_cfg imped_det;
178 * Note: various size depends on btn_det->num_btn
179 */
180 void *calibration;
181 enum wcd9xxx_micbias_num micbias;
182 int (*mclk_cb_fn) (struct snd_soc_codec*, int, bool);
183 unsigned int mclk_rate;
184 unsigned int gpio;
185 unsigned int gpio_irq;
186 int gpio_level_insert;
187 bool insert_detect; /* codec has own MBHC_INSERT_DETECT */
Joonwoo Park80a01172012-10-15 16:05:23 -0700188 bool detect_extn_cable;
Joonwoo Parka8890262012-10-15 12:04:27 -0700189 /* swap_gnd_mic returns true if extern GND/MIC swap switch toggled */
190 bool (*swap_gnd_mic) (struct snd_soc_codec *);
191};
192
193struct wcd9xxx_mbhc {
194 bool polling_active;
195 /* Delayed work to report long button press */
196 struct delayed_work mbhc_btn_dwork;
197 int buttons_pressed;
198 enum wcd9xxx_mbhc_state mbhc_state;
199 struct wcd9xxx_mbhc_config *mbhc_cfg;
200
201 struct mbhc_internal_cal_data mbhc_data;
202
203 struct mbhc_micbias_regs mbhc_bias_regs;
204 bool mbhc_micbias_switched;
205
206 u32 hph_status; /* track headhpone status */
207 u8 hphlocp_cnt; /* headphone left ocp retry */
208 u8 hphrocp_cnt; /* headphone right ocp retry */
209
210 /* Work to perform MBHC Firmware Read */
211 struct delayed_work mbhc_firmware_dwork;
212 const struct firmware *mbhc_fw;
213
214 struct delayed_work mbhc_insert_dwork;
215
216 u8 current_plug;
217 struct work_struct correct_plug_swch;
218 /*
219 * Work to perform polling on microphone voltage
220 * in order to correct plug type once plug type
221 * is detected as headphone
222 */
223 struct work_struct correct_plug_noswch;
224 bool hs_detect_work_stop;
225
226 bool lpi_enabled; /* low power insertion detection */
227 bool in_swch_irq_handler;
228
229 struct wcd9xxx_resmgr *resmgr;
230 struct snd_soc_codec *codec;
231
232 bool no_mic_headset_override;
233
234 /* track PA/DAC state */
235 unsigned long hph_pa_dac_state;
236
237 unsigned long mbhc_last_resume; /* in jiffies */
238
239 bool insert_detect_level_insert;
240
241 struct snd_soc_jack headset_jack;
242 struct snd_soc_jack button_jack;
243
244 struct notifier_block nblock;
245
246#ifdef CONFIG_DEBUG_FS
247 struct dentry *debugfs_poke;
248 struct dentry *debugfs_mbhc;
249#endif
250};
251
252#define WCD9XXX_MBHC_CAL_SIZE(buttons, rload) ( \
253 sizeof(enum wcd9xxx_micbias_num) + \
254 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
255 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
256 ((sizeof(s16) + sizeof(s16)) * buttons) + \
257 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
258 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
259 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
260 ((sizeof(u16) + sizeof(u16)) * rload) \
261 )
262
263#define WCD9XXX_MBHC_CAL_GENERAL_PTR(cali) ( \
264 (struct wcd9xxx_mbhc_general_cfg *) cali)
265#define WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali) ( \
266 (struct wcd9xxx_mbhc_plug_detect_cfg *) \
267 &(WCD9XXX_MBHC_CAL_GENERAL_PTR(cali)[1]))
268#define WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali) ( \
269 (struct wcd9xxx_mbhc_plug_type_cfg *) \
270 &(WCD9XXX_MBHC_CAL_PLUG_DET_PTR(cali)[1]))
271#define WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali) ( \
272 (struct wcd9xxx_mbhc_btn_detect_cfg *) \
273 &(WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(cali)[1]))
274#define WCD9XXX_MBHC_CAL_IMPED_DET_PTR(cali) ( \
275 (struct wcd9xxx_mbhc_imped_detect_cfg *) \
276 (((void *)&WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)[1]) + \
277 (WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->num_btn * \
278 (sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_low[0]) + \
279 sizeof(WCD9XXX_MBHC_CAL_BTN_DET_PTR(cali)->_v_btn_high[0])))) \
280 )
281
282/* minimum size of calibration data assuming there is only one button and
283 * one rload.
284 */
285#define WCD9XXX_MBHC_CAL_MIN_SIZE ( \
286 sizeof(struct wcd9xxx_mbhc_general_cfg) + \
287 sizeof(struct wcd9xxx_mbhc_plug_detect_cfg) + \
288 sizeof(struct wcd9xxx_mbhc_plug_type_cfg) + \
289 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
290 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
291 (sizeof(u16) * 2) \
292 )
293
294#define WCD9XXX_MBHC_CAL_BTN_SZ(cfg_ptr) ( \
295 sizeof(struct wcd9xxx_mbhc_btn_detect_cfg) + \
296 (cfg_ptr->num_btn * (sizeof(cfg_ptr->_v_btn_low[0]) + \
297 sizeof(cfg_ptr->_v_btn_high[0]))))
298
299#define WCD9XXX_MBHC_CAL_IMPED_MIN_SZ ( \
300 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + sizeof(u16) * 2)
301
302#define WCD9XXX_MBHC_CAL_IMPED_SZ(cfg_ptr) ( \
303 sizeof(struct wcd9xxx_mbhc_imped_detect_cfg) + \
304 (cfg_ptr->_n_rload * \
305 (sizeof(cfg_ptr->_rload[0]) + sizeof(cfg_ptr->_alpha[0]))))
306
307int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
308 struct wcd9xxx_mbhc_config *mbhc_cfg);
309int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
310 struct snd_soc_codec *codec);
311void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc);
312void *wcd9xxx_mbhc_cal_btn_det_mp(
313 const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
314 const enum wcd9xxx_mbhc_btn_det_mem mem);
315#endif /* __WCD9XXX_MBHC_H__ */