blob: 88f0567f67d88273e5cb87d3d75df139d2dedfce [file] [log] [blame]
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08001/* 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 */
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -070012
Joonwoo Parka8890262012-10-15 12:04:27 -070013#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/firmware.h>
16#include <linux/slab.h>
17#include <linux/platform_device.h>
18#include <linux/device.h>
19#include <linux/printk.h>
20#include <linux/ratelimit.h>
21#include <linux/debugfs.h>
22#include <linux/mfd/wcd9xxx/core.h>
23#include <linux/mfd/wcd9xxx/wcd9xxx_registers.h>
24#include <linux/mfd/wcd9xxx/wcd9320_registers.h>
25#include <linux/mfd/wcd9xxx/pdata.h>
26#include <sound/pcm.h>
27#include <sound/pcm_params.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30#include <sound/tlv.h>
31#include <linux/bitops.h>
32#include <linux/delay.h>
33#include <linux/pm_runtime.h>
34#include <linux/kernel.h>
35#include <linux/gpio.h>
36#include "wcd9320.h"
37#include "wcd9xxx-mbhc.h"
38#include "wcd9xxx-resmgr.h"
39
40#define WCD9XXX_JACK_MASK (SND_JACK_HEADSET | SND_JACK_OC_HPHL | \
Joonwoo Park80a01172012-10-15 16:05:23 -070041 SND_JACK_OC_HPHR | SND_JACK_LINEOUT | \
42 SND_JACK_UNSUPPORTED)
Joonwoo Parka8890262012-10-15 12:04:27 -070043#define WCD9XXX_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
44 SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
45 SND_JACK_BTN_4 | SND_JACK_BTN_5 | \
46 SND_JACK_BTN_6 | SND_JACK_BTN_7)
47
48#define NUM_DCE_PLUG_DETECT 3
Joonwoo Park20bc9da2013-01-16 12:58:06 -080049#define NUM_DCE_PLUG_INS_DETECT 4
Joonwoo Parka8890262012-10-15 12:04:27 -070050#define NUM_ATTEMPTS_INSERT_DETECT 25
51#define NUM_ATTEMPTS_TO_REPORT 5
52
53#define FAKE_INS_LOW 10
54#define FAKE_INS_HIGH 80
55#define FAKE_INS_HIGH_NO_SWCH 150
56#define FAKE_REMOVAL_MIN_PERIOD_MS 50
57#define FAKE_INS_DELTA_SCALED_MV 300
58
59#define BUTTON_MIN 0x8000
60#define STATUS_REL_DETECTION 0x0C
61
62#define HS_DETECT_PLUG_TIME_MS (5 * 1000)
63#define HS_DETECT_PLUG_INERVAL_MS 100
64#define SWCH_REL_DEBOUNCE_TIME_MS 50
65#define SWCH_IRQ_DEBOUNCE_TIME_US 5000
66
67#define GND_MIC_SWAP_THRESHOLD 2
68#define OCP_ATTEMPT 1
69
70#define FW_READ_ATTEMPTS 15
71#define FW_READ_TIMEOUT 2000000
72
Joonwoo Park2e6bd1e2012-10-18 13:48:55 -070073#define BUTTON_POLLING_SUPPORTED true
Joonwoo Parka8890262012-10-15 12:04:27 -070074
75#define MCLK_RATE_12288KHZ 12288000
76#define MCLK_RATE_9600KHZ 9600000
77#define WCD9XXX_RCO_CLK_RATE MCLK_RATE_12288KHZ
78
79#define DEFAULT_DCE_STA_WAIT 55
80#define DEFAULT_DCE_WAIT 60000
81#define DEFAULT_STA_WAIT 5000
82
83#define VDDIO_MICBIAS_MV 1800
84
Joonwoo Park20bc9da2013-01-16 12:58:06 -080085#define WCD9XXX_HPHL_STATUS_READY_WAIT_US 1000
Joonwoo Park7902f4c2013-02-20 15:21:25 -080086#define WCD9XXX_MUX_SWITCH_READY_WAIT_US 100
Joonwoo Park20bc9da2013-01-16 12:58:06 -080087#define WCD9XXX_MEAS_DELTA_MAX_MV 50
Joonwoo Park141d6182013-03-05 12:25:46 -080088#define WCD9XXX_MEAS_INVALD_RANGE_LOW_MV 20
89#define WCD9XXX_MEAS_INVALD_RANGE_HIGH_MV 80
Joonwoo Park20bc9da2013-01-16 12:58:06 -080090#define WCD9XXX_GM_SWAP_THRES_MIN_MV 150
91#define WCD9XXX_GM_SWAP_THRES_MAX_MV 500
92
93#define WCD9XXX_USLEEP_RANGE_MARGIN_US 1000
94
95static bool detect_use_vddio_switch;
96
97struct wcd9xxx_mbhc_detect {
98 u16 dce;
99 u16 sta;
100 u16 hphl_status;
101 bool swap_gnd;
102 bool vddio;
103 bool hwvalue;
104 /* internal purpose from here */
105 bool _above_no_mic;
106 bool _below_v_hs_max;
107 s16 _vdces;
108 enum wcd9xxx_mbhc_plug_type _type;
109};
110
Joonwoo Parka8890262012-10-15 12:04:27 -0700111enum meas_type {
112 STA = 0,
113 DCE,
114};
115
116enum {
117 MBHC_USE_HPHL_TRIGGER = 1,
118 MBHC_USE_MB_TRIGGER = 2
119};
120
121/*
122 * Flags to track of PA and DAC state.
123 * PA and DAC should be tracked separately as AUXPGA loopback requires
124 * only PA to be turned on without DAC being on.
125 */
126enum pa_dac_ack_flags {
127 WCD9XXX_HPHL_PA_OFF_ACK = 0,
128 WCD9XXX_HPHR_PA_OFF_ACK,
129 WCD9XXX_HPHL_DAC_OFF_ACK,
130 WCD9XXX_HPHR_DAC_OFF_ACK
131};
132
133static bool wcd9xxx_mbhc_polling(struct wcd9xxx_mbhc *mbhc)
134{
135 return mbhc->polling_active;
136}
137
138static void wcd9xxx_turn_onoff_override(struct snd_soc_codec *codec, bool on)
139{
140 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, on << 2);
141}
142
143/* called under codec_resource_lock acquisition */
144static void wcd9xxx_pause_hs_polling(struct wcd9xxx_mbhc *mbhc)
145{
146 struct snd_soc_codec *codec = mbhc->codec;
147
148 pr_debug("%s: enter\n", __func__);
149 if (!mbhc->polling_active) {
150 pr_debug("polling not active, nothing to pause\n");
151 return;
152 }
153
154 /* Soft reset MBHC block */
155 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
156 pr_debug("%s: leave\n", __func__);
157}
158
159/* called under codec_resource_lock acquisition */
160static void wcd9xxx_start_hs_polling(struct wcd9xxx_mbhc *mbhc)
161{
162 struct snd_soc_codec *codec = mbhc->codec;
163 int mbhc_state = mbhc->mbhc_state;
164
165 pr_debug("%s: enter\n", __func__);
166 if (!mbhc->polling_active) {
167 pr_debug("Polling is not active, do not start polling\n");
168 return;
169 }
170 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
171
172 if (!mbhc->no_mic_headset_override &&
173 mbhc_state == MBHC_STATE_POTENTIAL) {
174 pr_debug("%s recovering MBHC state macine\n", __func__);
175 mbhc->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
176 /* set to max button press threshold */
177 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL, 0x7F);
178 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, 0xFF);
179 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B4_CTL, 0x7F);
180 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL, 0xFF);
181 /* set to max */
182 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B6_CTL, 0x7F);
183 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL, 0xFF);
184 }
185
186 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x1);
187 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x0);
188 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x1);
189 pr_debug("%s: leave\n", __func__);
190}
191
192/* called under codec_resource_lock acquisition */
193static void __wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc,
194 int vddio_switch, bool restartpolling,
195 bool checkpolling)
196{
197 int cfilt_k_val;
198 bool override;
199 struct snd_soc_codec *codec;
200
201 codec = mbhc->codec;
202
203 if (vddio_switch && !mbhc->mbhc_micbias_switched &&
204 (!checkpolling || mbhc->polling_active)) {
205 if (restartpolling)
206 wcd9xxx_pause_hs_polling(mbhc);
207 override = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL) &
208 0x04;
209 if (!override)
210 wcd9xxx_turn_onoff_override(codec, true);
211 /* Adjust threshold if Mic Bias voltage changes */
212 if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
213 cfilt_k_val = wcd9xxx_resmgr_get_k_val(mbhc->resmgr,
214 VDDIO_MICBIAS_MV);
215 usleep_range(10000, 10000);
216 snd_soc_update_bits(codec,
217 mbhc->mbhc_bias_regs.cfilt_val,
218 0xFC, (cfilt_k_val << 2));
219 usleep_range(10000, 10000);
220 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL,
221 mbhc->mbhc_data.adj_v_ins_hu & 0xFF);
222 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
223 (mbhc->mbhc_data.adj_v_ins_hu >> 8) &
224 0xFF);
225 pr_debug("%s: Programmed MBHC thresholds to VDDIO\n",
226 __func__);
227 }
228
229 /* Enable MIC BIAS Switch to VDDIO */
230 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg,
231 0x80, 0x80);
232 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg,
233 0x10, 0x00);
234 if (!override)
235 wcd9xxx_turn_onoff_override(codec, false);
236 if (restartpolling)
237 wcd9xxx_start_hs_polling(mbhc);
238
239 mbhc->mbhc_micbias_switched = true;
240 pr_debug("%s: VDDIO switch enabled\n", __func__);
241 } else if (!vddio_switch && mbhc->mbhc_micbias_switched) {
242 if ((!checkpolling || mbhc->polling_active) &&
243 restartpolling)
244 wcd9xxx_pause_hs_polling(mbhc);
245 /* Reprogram thresholds */
246 if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
247 cfilt_k_val =
248 wcd9xxx_resmgr_get_k_val(mbhc->resmgr,
249 mbhc->mbhc_data.micb_mv);
250 snd_soc_update_bits(codec,
251 mbhc->mbhc_bias_regs.cfilt_val,
252 0xFC, (cfilt_k_val << 2));
253 usleep_range(10000, 10000);
254 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL,
255 mbhc->mbhc_data.v_ins_hu & 0xFF);
256 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
257 (mbhc->mbhc_data.v_ins_hu >> 8) & 0xFF);
258 pr_debug("%s: Programmed MBHC thresholds to MICBIAS\n",
259 __func__);
260 }
261
262 /* Disable MIC BIAS Switch to VDDIO */
263 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80,
264 0x00);
265 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x10,
266 0x00);
267
268 if ((!checkpolling || mbhc->polling_active) && restartpolling)
269 wcd9xxx_start_hs_polling(mbhc);
270
271 mbhc->mbhc_micbias_switched = false;
272 pr_debug("%s: VDDIO switch disabled\n", __func__);
273 }
274}
275
276static void wcd9xxx_switch_micbias(struct wcd9xxx_mbhc *mbhc, int vddio_switch)
277{
278 return __wcd9xxx_switch_micbias(mbhc, vddio_switch, true, true);
279}
280
281static s16 wcd9xxx_get_current_v_ins(struct wcd9xxx_mbhc *mbhc, bool hu)
282{
283 s16 v_ins;
284 if ((mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
285 mbhc->mbhc_micbias_switched)
286 v_ins = hu ? (s16)mbhc->mbhc_data.adj_v_ins_hu :
287 (s16)mbhc->mbhc_data.adj_v_ins_h;
288 else
289 v_ins = hu ? (s16)mbhc->mbhc_data.v_ins_hu :
290 (s16)mbhc->mbhc_data.v_ins_h;
291 return v_ins;
292}
293
294void *wcd9xxx_mbhc_cal_btn_det_mp(
295 const struct wcd9xxx_mbhc_btn_detect_cfg *btn_det,
296 const enum wcd9xxx_mbhc_btn_det_mem mem)
297{
298 void *ret = &btn_det->_v_btn_low;
299
300 switch (mem) {
301 case MBHC_BTN_DET_GAIN:
302 ret += sizeof(btn_det->_n_cic);
303 case MBHC_BTN_DET_N_CIC:
304 ret += sizeof(btn_det->_n_ready);
305 case MBHC_BTN_DET_N_READY:
306 ret += sizeof(btn_det->_v_btn_high[0]) * btn_det->num_btn;
307 case MBHC_BTN_DET_V_BTN_HIGH:
308 ret += sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn;
309 case MBHC_BTN_DET_V_BTN_LOW:
310 /* do nothing */
311 break;
312 default:
313 ret = NULL;
314 }
315
316 return ret;
317}
318EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_cal_btn_det_mp);
319
320static void wcd9xxx_calibrate_hs_polling(struct wcd9xxx_mbhc *mbhc)
321{
322 struct snd_soc_codec *codec = mbhc->codec;
323 const s16 v_ins_hu = wcd9xxx_get_current_v_ins(mbhc, true);
324
325 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B1_CTL, v_ins_hu & 0xFF);
326 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B2_CTL,
327 (v_ins_hu >> 8) & 0xFF);
328
329 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B3_CTL,
330 mbhc->mbhc_data.v_b1_hu & 0xFF);
331 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B4_CTL,
332 (mbhc->mbhc_data.v_b1_hu >> 8) & 0xFF);
333
334 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B5_CTL,
335 mbhc->mbhc_data.v_b1_h & 0xFF);
336 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B6_CTL,
337 (mbhc->mbhc_data.v_b1_h >> 8) & 0xFF);
338
339 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B9_CTL,
340 mbhc->mbhc_data.v_brh & 0xFF);
341 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B10_CTL,
342 (mbhc->mbhc_data.v_brh >> 8) & 0xFF);
343
344 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B11_CTL,
345 mbhc->mbhc_data.v_brl & 0xFF);
346 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_VOLT_B12_CTL,
347 (mbhc->mbhc_data.v_brl >> 8) & 0xFF);
348}
349
350static void wcd9xxx_codec_switch_cfilt_mode(struct wcd9xxx_mbhc *mbhc,
351 bool fast)
352{
353 struct snd_soc_codec *codec = mbhc->codec;
354 u8 reg_mode_val, cur_mode_val;
355
356 if (fast)
357 reg_mode_val = WCD9XXX_CFILT_FAST_MODE;
358 else
359 reg_mode_val = WCD9XXX_CFILT_SLOW_MODE;
360
361 cur_mode_val =
362 snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl) & 0x40;
363
364 if (cur_mode_val != reg_mode_val) {
365 if (mbhc->polling_active)
366 wcd9xxx_pause_hs_polling(mbhc);
367 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
368 reg_mode_val);
369 if (mbhc->polling_active)
370 wcd9xxx_start_hs_polling(mbhc);
371 pr_debug("%s: CFILT mode change (%x to %x)\n", __func__,
372 cur_mode_val, reg_mode_val);
373 } else {
374 pr_debug("%s: CFILT Value is already %x\n",
375 __func__, cur_mode_val);
376 }
377}
378
Joonwoo Park3699ca32013-02-08 12:06:15 -0800379static void wcd9xxx_jack_report(struct wcd9xxx_mbhc *mbhc,
380 struct snd_soc_jack *jack, int status, int mask)
Joonwoo Parka8890262012-10-15 12:04:27 -0700381{
Joonwoo Parkaf21f032013-03-05 18:07:40 -0800382 if (jack == &mbhc->headset_jack) {
Joonwoo Park3699ca32013-02-08 12:06:15 -0800383 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
384 WCD9XXX_COND_HPH_MIC,
385 status & SND_JACK_MICROPHONE);
Joonwoo Parkaf21f032013-03-05 18:07:40 -0800386 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
387 WCD9XXX_COND_HPH,
388 status & SND_JACK_HEADPHONE);
389 }
Joonwoo Park3699ca32013-02-08 12:06:15 -0800390
Joonwoo Parka8890262012-10-15 12:04:27 -0700391 snd_soc_jack_report_no_dapm(jack, status, mask);
392}
393
394static void __hphocp_off_report(struct wcd9xxx_mbhc *mbhc, u32 jack_status,
395 int irq)
396{
397 struct snd_soc_codec *codec;
398
399 pr_debug("%s: clear ocp status %x\n", __func__, jack_status);
400 codec = mbhc->codec;
401 if (mbhc->hph_status & jack_status) {
402 mbhc->hph_status &= ~jack_status;
Joonwoo Park3699ca32013-02-08 12:06:15 -0800403 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -0700404 mbhc->hph_status, WCD9XXX_JACK_MASK);
405 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
406 0x00);
407 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
408 0x10);
409 /*
410 * reset retry counter as PA is turned off signifying
411 * start of new OCP detection session
412 */
413 if (WCD9XXX_IRQ_HPH_PA_OCPL_FAULT)
414 mbhc->hphlocp_cnt = 0;
415 else
416 mbhc->hphrocp_cnt = 0;
417 wcd9xxx_enable_irq(codec->control_data, irq);
418 }
419}
420
421static void hphrocp_off_report(struct wcd9xxx_mbhc *mbhc, u32 jack_status)
422{
423 __hphocp_off_report(mbhc, SND_JACK_OC_HPHR,
424 WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
425}
426
427static void hphlocp_off_report(struct wcd9xxx_mbhc *mbhc, u32 jack_status)
428{
429 __hphocp_off_report(mbhc, SND_JACK_OC_HPHL,
430 WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
431}
432
433static void wcd9xxx_get_mbhc_micbias_regs(struct wcd9xxx_mbhc *mbhc,
434 struct mbhc_micbias_regs *micbias_regs)
435{
436 unsigned int cfilt;
437 struct wcd9xxx_pdata *pdata = mbhc->resmgr->pdata;
438
439 switch (mbhc->mbhc_cfg->micbias) {
440 case MBHC_MICBIAS1:
441 cfilt = pdata->micbias.bias1_cfilt_sel;
442 micbias_regs->mbhc_reg = WCD9XXX_A_MICB_1_MBHC;
443 micbias_regs->int_rbias = WCD9XXX_A_MICB_1_INT_RBIAS;
444 micbias_regs->ctl_reg = WCD9XXX_A_MICB_1_CTL;
445 break;
446 case MBHC_MICBIAS2:
447 cfilt = pdata->micbias.bias2_cfilt_sel;
448 micbias_regs->mbhc_reg = WCD9XXX_A_MICB_2_MBHC;
449 micbias_regs->int_rbias = WCD9XXX_A_MICB_2_INT_RBIAS;
450 micbias_regs->ctl_reg = WCD9XXX_A_MICB_2_CTL;
451 break;
452 case MBHC_MICBIAS3:
453 cfilt = pdata->micbias.bias3_cfilt_sel;
454 micbias_regs->mbhc_reg = WCD9XXX_A_MICB_3_MBHC;
455 micbias_regs->int_rbias = WCD9XXX_A_MICB_3_INT_RBIAS;
456 micbias_regs->ctl_reg = WCD9XXX_A_MICB_3_CTL;
457 break;
458 case MBHC_MICBIAS4:
459 cfilt = pdata->micbias.bias4_cfilt_sel;
460 micbias_regs->mbhc_reg = mbhc->resmgr->reg_addr->micb_4_mbhc;
461 micbias_regs->int_rbias =
462 mbhc->resmgr->reg_addr->micb_4_int_rbias;
463 micbias_regs->ctl_reg = mbhc->resmgr->reg_addr->micb_4_ctl;
464 break;
465 default:
466 /* Should never reach here */
467 pr_err("%s: Invalid MIC BIAS for MBHC\n", __func__);
468 return;
469 }
470
471 micbias_regs->cfilt_sel = cfilt;
472
473 switch (cfilt) {
474 case WCD9XXX_CFILT1_SEL:
475 micbias_regs->cfilt_val = WCD9XXX_A_MICB_CFILT_1_VAL;
476 micbias_regs->cfilt_ctl = WCD9XXX_A_MICB_CFILT_1_CTL;
477 mbhc->mbhc_data.micb_mv =
478 mbhc->resmgr->pdata->micbias.cfilt1_mv;
479 break;
480 case WCD9XXX_CFILT2_SEL:
481 micbias_regs->cfilt_val = WCD9XXX_A_MICB_CFILT_2_VAL;
482 micbias_regs->cfilt_ctl = WCD9XXX_A_MICB_CFILT_2_CTL;
483 mbhc->mbhc_data.micb_mv =
484 mbhc->resmgr->pdata->micbias.cfilt2_mv;
485 break;
486 case WCD9XXX_CFILT3_SEL:
487 micbias_regs->cfilt_val = WCD9XXX_A_MICB_CFILT_3_VAL;
488 micbias_regs->cfilt_ctl = WCD9XXX_A_MICB_CFILT_3_CTL;
489 mbhc->mbhc_data.micb_mv =
490 mbhc->resmgr->pdata->micbias.cfilt3_mv;
491 break;
492 }
493}
494
495static void wcd9xxx_clr_and_turnon_hph_padac(struct wcd9xxx_mbhc *mbhc)
496{
497 bool pa_turned_on = false;
498 struct snd_soc_codec *codec = mbhc->codec;
499 u8 wg_time;
500
501 wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME) ;
502 wg_time += 1;
503
504 if (test_and_clear_bit(WCD9XXX_HPHR_DAC_OFF_ACK,
505 &mbhc->hph_pa_dac_state)) {
506 pr_debug("%s: HPHR clear flag and enable DAC\n", __func__);
507 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL,
508 0xC0, 0xC0);
509 }
510 if (test_and_clear_bit(WCD9XXX_HPHL_DAC_OFF_ACK,
511 &mbhc->hph_pa_dac_state)) {
512 pr_debug("%s: HPHL clear flag and enable DAC\n", __func__);
513 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL,
514 0xC0, 0xC0);
515 }
516
517 if (test_and_clear_bit(WCD9XXX_HPHR_PA_OFF_ACK,
518 &mbhc->hph_pa_dac_state)) {
519 pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
520 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x10,
521 1 << 4);
522 pa_turned_on = true;
523 }
524 if (test_and_clear_bit(WCD9XXX_HPHL_PA_OFF_ACK,
525 &mbhc->hph_pa_dac_state)) {
526 pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
527 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x20, 1
528 << 5);
529 pa_turned_on = true;
530 }
531
532 if (pa_turned_on) {
533 pr_debug("%s: PA was turned off by MBHC and not by DAPM\n",
534 __func__);
535 usleep_range(wg_time * 1000, wg_time * 1000);
536 }
537}
538
539static int wcd9xxx_cancel_btn_work(struct wcd9xxx_mbhc *mbhc)
540{
541 int r;
542 r = cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork);
543 if (r)
544 /* if scheduled mbhc.mbhc_btn_dwork is canceled from here,
545 * we have to unlock from here instead btn_work */
546 wcd9xxx_unlock_sleep(mbhc->resmgr->core);
547 return r;
548}
549
550static bool wcd9xxx_is_hph_dac_on(struct snd_soc_codec *codec, int left)
551{
552 u8 hph_reg_val = 0;
553 if (left)
554 hph_reg_val = snd_soc_read(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL);
555 else
556 hph_reg_val = snd_soc_read(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL);
557
558 return (hph_reg_val & 0xC0) ? true : false;
559}
560
561static bool wcd9xxx_is_hph_pa_on(struct snd_soc_codec *codec)
562{
563 u8 hph_reg_val = 0;
564 hph_reg_val = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_EN);
565
566 return (hph_reg_val & 0x30) ? true : false;
567}
568
569/* called under codec_resource_lock acquisition */
570static void wcd9xxx_set_and_turnoff_hph_padac(struct wcd9xxx_mbhc *mbhc)
571{
572 u8 wg_time;
573 struct snd_soc_codec *codec = mbhc->codec;
574
575 wg_time = snd_soc_read(codec, WCD9XXX_A_RX_HPH_CNP_WG_TIME);
576 wg_time += 1;
577
578 /* If headphone PA is on, check if userspace receives
579 * removal event to sync-up PA's state */
580 if (wcd9xxx_is_hph_pa_on(codec)) {
581 pr_debug("%s PA is on, setting PA_OFF_ACK\n", __func__);
582 set_bit(WCD9XXX_HPHL_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
583 set_bit(WCD9XXX_HPHR_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
584 } else {
585 pr_debug("%s PA is off\n", __func__);
586 }
587
588 if (wcd9xxx_is_hph_dac_on(codec, 1))
589 set_bit(WCD9XXX_HPHL_DAC_OFF_ACK, &mbhc->hph_pa_dac_state);
590 if (wcd9xxx_is_hph_dac_on(codec, 0))
591 set_bit(WCD9XXX_HPHR_DAC_OFF_ACK, &mbhc->hph_pa_dac_state);
592
593 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_CNP_EN, 0x30, 0x00);
Joonwoo Park67c0dbf2013-01-25 10:47:38 -0800594 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_L_DAC_CTL, 0x80, 0x00);
Joonwoo Parka8890262012-10-15 12:04:27 -0700595 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_R_DAC_CTL, 0xC0, 0x00);
596 usleep_range(wg_time * 1000, wg_time * 1000);
597}
598
599static void wcd9xxx_insert_detect_setup(struct wcd9xxx_mbhc *mbhc, bool ins)
600{
601 if (!mbhc->mbhc_cfg->insert_detect)
602 return;
603 pr_debug("%s: Setting up %s detection\n", __func__,
604 ins ? "insert" : "removal");
Joonwoo Park2e6bd1e2012-10-18 13:48:55 -0700605 /* Disable detection to avoid glitch */
606 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 0);
Joonwoo Parka8890262012-10-15 12:04:27 -0700607 snd_soc_write(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT,
Joonwoo Park2e6bd1e2012-10-18 13:48:55 -0700608 (0x68 | (ins ? (1 << 1) : 0)));
609 /* Re-enable detection */
610 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MBHC_INSERT_DETECT, 1, 1);
Joonwoo Parka8890262012-10-15 12:04:27 -0700611}
612
613/* called under codec_resource_lock acquisition */
614static void wcd9xxx_report_plug(struct wcd9xxx_mbhc *mbhc, int insertion,
615 enum snd_jack_types jack_type)
616{
617 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
618
Joonwoo Park80a01172012-10-15 16:05:23 -0700619 pr_debug("%s: enter insertion %d hph_status %x\n",
620 __func__, insertion, mbhc->hph_status);
Joonwoo Parka8890262012-10-15 12:04:27 -0700621 if (!insertion) {
622 /* Report removal */
623 mbhc->hph_status &= ~jack_type;
624 /*
625 * cancel possibly scheduled btn work and
626 * report release if we reported button press
627 */
628 if (wcd9xxx_cancel_btn_work(mbhc))
629 pr_debug("%s: button press is canceled\n", __func__);
630 else if (mbhc->buttons_pressed) {
631 pr_debug("%s: release of button press%d\n",
632 __func__, jack_type);
Joonwoo Park3699ca32013-02-08 12:06:15 -0800633 wcd9xxx_jack_report(mbhc, &mbhc->button_jack, 0,
Joonwoo Parka8890262012-10-15 12:04:27 -0700634 mbhc->buttons_pressed);
635 mbhc->buttons_pressed &=
636 ~WCD9XXX_JACK_BUTTON_MASK;
637 }
638 pr_debug("%s: Reporting removal %d(%x)\n", __func__,
639 jack_type, mbhc->hph_status);
Joonwoo Park3699ca32013-02-08 12:06:15 -0800640 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack, mbhc->hph_status,
Joonwoo Parka8890262012-10-15 12:04:27 -0700641 WCD9XXX_JACK_MASK);
642 wcd9xxx_set_and_turnoff_hph_padac(mbhc);
643 hphrocp_off_report(mbhc, SND_JACK_OC_HPHR);
644 hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
645 mbhc->current_plug = PLUG_TYPE_NONE;
646 mbhc->polling_active = false;
647 } else {
Joonwoo Park80a01172012-10-15 16:05:23 -0700648 if (mbhc->mbhc_cfg->detect_extn_cable) {
649 /* Report removal of current jack type */
Joonwoo Park20bc9da2013-01-16 12:58:06 -0800650 if (mbhc->hph_status && mbhc->hph_status != jack_type) {
Joonwoo Park80a01172012-10-15 16:05:23 -0700651 pr_debug("%s: Reporting removal (%x)\n",
652 __func__, mbhc->hph_status);
Joonwoo Park3699ca32013-02-08 12:06:15 -0800653 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
Joonwoo Park80a01172012-10-15 16:05:23 -0700654 0, WCD9XXX_JACK_MASK);
655 mbhc->hph_status = 0;
656 }
657 }
Joonwoo Parka8890262012-10-15 12:04:27 -0700658 /* Report insertion */
659 mbhc->hph_status |= jack_type;
660
661 if (jack_type == SND_JACK_HEADPHONE) {
662 mbhc->current_plug = PLUG_TYPE_HEADPHONE;
663 } else if (jack_type == SND_JACK_UNSUPPORTED) {
664 mbhc->current_plug = PLUG_TYPE_GND_MIC_SWAP;
665 } else if (jack_type == SND_JACK_HEADSET) {
666 mbhc->polling_active = BUTTON_POLLING_SUPPORTED;
667 mbhc->current_plug = PLUG_TYPE_HEADSET;
Joonwoo Park80a01172012-10-15 16:05:23 -0700668 } else if (jack_type == SND_JACK_LINEOUT) {
669 mbhc->current_plug = PLUG_TYPE_HIGH_HPH;
Joonwoo Parka8890262012-10-15 12:04:27 -0700670 }
671 pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
672 jack_type, mbhc->hph_status);
Joonwoo Park3699ca32013-02-08 12:06:15 -0800673 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -0700674 mbhc->hph_status, WCD9XXX_JACK_MASK);
675 wcd9xxx_clr_and_turnon_hph_padac(mbhc);
676 }
677 /* Setup insert detect */
678 wcd9xxx_insert_detect_setup(mbhc, !insertion);
Joonwoo Park80a01172012-10-15 16:05:23 -0700679
680 pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status);
Joonwoo Parka8890262012-10-15 12:04:27 -0700681}
682
683/* should be called under interrupt context that hold suspend */
684static void wcd9xxx_schedule_hs_detect_plug(struct wcd9xxx_mbhc *mbhc,
685 struct work_struct *work)
686{
687 pr_debug("%s: scheduling wcd9xxx_correct_swch_plug\n", __func__);
688 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
689 mbhc->hs_detect_work_stop = false;
690 wcd9xxx_lock_sleep(mbhc->resmgr->core);
691 schedule_work(work);
692}
693
694/* called under codec_resource_lock acquisition */
695static void wcd9xxx_cancel_hs_detect_plug(struct wcd9xxx_mbhc *mbhc,
696 struct work_struct *work)
697{
698 pr_debug("%s: Canceling correct_plug_swch\n", __func__);
699 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
700 mbhc->hs_detect_work_stop = true;
701 wmb();
702 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
703 if (cancel_work_sync(work)) {
704 pr_debug("%s: correct_plug_swch is canceled\n",
705 __func__);
706 wcd9xxx_unlock_sleep(mbhc->resmgr->core);
707 }
708 WCD9XXX_BCL_LOCK(mbhc->resmgr);
709}
710
711static s16 wcd9xxx_get_current_v_hs_max(struct wcd9xxx_mbhc *mbhc)
712{
713 s16 v_hs_max;
714 struct wcd9xxx_mbhc_plug_type_cfg *plug_type;
715
716 plug_type = WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
717 if ((mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) &&
718 mbhc->mbhc_micbias_switched)
719 v_hs_max = mbhc->mbhc_data.adj_v_hs_max;
720 else
721 v_hs_max = plug_type->v_hs_max;
722 return v_hs_max;
723}
724
Joonwoo Parka8890262012-10-15 12:04:27 -0700725static short wcd9xxx_read_sta_result(struct snd_soc_codec *codec)
726{
727 u8 bias_msb, bias_lsb;
728 short bias_value;
729
730 bias_msb = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B3_STATUS);
731 bias_lsb = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B2_STATUS);
732 bias_value = (bias_msb << 8) | bias_lsb;
733 return bias_value;
734}
735
736static short wcd9xxx_read_dce_result(struct snd_soc_codec *codec)
737{
738 u8 bias_msb, bias_lsb;
739 short bias_value;
740
741 bias_msb = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B5_STATUS);
742 bias_lsb = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B4_STATUS);
743 bias_value = (bias_msb << 8) | bias_lsb;
744 return bias_value;
745}
746
747static void wcd9xxx_turn_onoff_rel_detection(struct snd_soc_codec *codec,
748 bool on)
749{
750 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x02, on << 1);
751}
752
753static short __wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce,
754 bool override_bypass, bool noreldetection)
755{
756 short bias_value;
757 struct snd_soc_codec *codec = mbhc->codec;
758
759 wcd9xxx_disable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_POTENTIAL);
760 if (noreldetection)
761 wcd9xxx_turn_onoff_rel_detection(codec, false);
762
763 /* Turn on the override */
764 if (!override_bypass)
765 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x4, 0x4);
766 if (dce) {
767 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
768 0x8);
769 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
770 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
771 0x0);
772 usleep_range(mbhc->mbhc_data.t_sta_dce,
773 mbhc->mbhc_data.t_sta_dce);
774 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x4);
775 usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce);
776 bias_value = wcd9xxx_read_dce_result(codec);
777 } else {
778 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
779 0x8);
780 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
781 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
782 0x0);
783 usleep_range(mbhc->mbhc_data.t_sta_dce,
784 mbhc->mbhc_data.t_sta_dce);
785 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x2);
786 usleep_range(mbhc->mbhc_data.t_sta,
787 mbhc->mbhc_data.t_sta);
788 bias_value = wcd9xxx_read_sta_result(codec);
789 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8,
790 0x8);
791 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x0);
792 }
793 /* Turn off the override after measuring mic voltage */
794 if (!override_bypass)
795 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04,
796 0x00);
797
798 if (noreldetection)
799 wcd9xxx_turn_onoff_rel_detection(codec, true);
800 wcd9xxx_enable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_POTENTIAL);
801
802 return bias_value;
803}
804
805static short wcd9xxx_codec_sta_dce(struct wcd9xxx_mbhc *mbhc, int dce,
806 bool norel)
807{
808 return __wcd9xxx_codec_sta_dce(mbhc, dce, false, norel);
809}
810
811static s32 wcd9xxx_codec_sta_dce_v(struct wcd9xxx_mbhc *mbhc, s8 dce,
812 u16 bias_value)
813{
814 s16 value, z, mb;
815 s32 mv;
816
817 value = bias_value;
818 if (dce) {
819 z = (mbhc->mbhc_data.dce_z);
820 mb = (mbhc->mbhc_data.dce_mb);
821 mv = (value - z) * (s32)mbhc->mbhc_data.micb_mv / (mb - z);
822 } else {
823 z = (mbhc->mbhc_data.sta_z);
824 mb = (mbhc->mbhc_data.sta_mb);
825 mv = (value - z) * (s32)mbhc->mbhc_data.micb_mv / (mb - z);
826 }
827
828 return mv;
829}
830
831/* called only from interrupt which is under codec_resource_lock acquisition */
832static short wcd9xxx_mbhc_setup_hs_polling(struct wcd9xxx_mbhc *mbhc)
833{
834 struct snd_soc_codec *codec = mbhc->codec;
835 short bias_value;
836 u8 cfilt_mode;
837
838 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
839
840 pr_debug("%s: enter\n", __func__);
841 if (!mbhc->mbhc_cfg->calibration) {
842 pr_err("%s: Error, no calibration exists\n", __func__);
843 return -ENODEV;
844 }
845
846 /*
847 * Request BG and clock.
848 * These will be released by wcd9xxx_cleanup_hs_polling
849 */
850 wcd9xxx_resmgr_get_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
851 wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
852
853 snd_soc_update_bits(codec, WCD9XXX_A_CLK_BUFF_EN1, 0x05, 0x01);
854
855 /* Make sure CFILT is in fast mode, save current mode */
856 cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
857 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x70, 0x00);
858
Joonwoo Parka8890262012-10-15 12:04:27 -0700859 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
860 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
861
862 snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x80, 0x80);
863 snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x1F, 0x1C);
864 snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0x40, 0x40);
865
866 snd_soc_update_bits(codec, WCD9XXX_A_TX_7_MBHC_EN, 0x80, 0x00);
867 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
868 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x00);
869
870 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x2, 0x2);
871 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x8, 0x8);
872
873 wcd9xxx_calibrate_hs_polling(mbhc);
874
875 /* don't flip override */
876 bias_value = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
877 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
878 cfilt_mode);
879 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
880
881 return bias_value;
882}
883
884static void wcd9xxx_shutdown_hs_removal_detect(struct wcd9xxx_mbhc *mbhc)
885{
886 struct snd_soc_codec *codec = mbhc->codec;
887 const struct wcd9xxx_mbhc_general_cfg *generic =
888 WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration);
889
890 /* Need MBHC clock */
891 wcd9xxx_resmgr_get_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
892
893 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x2, 0x2);
894 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x6, 0x0);
895 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x80, 0x00);
896
897 usleep_range(generic->t_shutdown_plug_rem,
898 generic->t_shutdown_plug_rem);
899
900 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0xA, 0x8);
901
902 /* Put requested CLK back */
903 wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
904
905 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x00);
906}
907
908static void wcd9xxx_cleanup_hs_polling(struct wcd9xxx_mbhc *mbhc)
909{
910 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
911
912 wcd9xxx_shutdown_hs_removal_detect(mbhc);
913
914 /* Release clock and BG requested by wcd9xxx_mbhc_setup_hs_polling */
915 wcd9xxx_resmgr_put_clk_block(mbhc->resmgr, WCD9XXX_CLK_RCO);
916 wcd9xxx_resmgr_put_bandgap(mbhc->resmgr, WCD9XXX_BANDGAP_MBHC_MODE);
917
918 mbhc->polling_active = false;
919 mbhc->mbhc_state = MBHC_STATE_NONE;
920}
921
922static s16 scale_v_micb_vddio(struct wcd9xxx_mbhc *mbhc, int v, bool tovddio)
923{
924 int r;
925 int vddio_k, mb_k;
926 vddio_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, VDDIO_MICBIAS_MV);
927 mb_k = wcd9xxx_resmgr_get_k_val(mbhc->resmgr, mbhc->mbhc_data.micb_mv);
928 if (tovddio)
929 r = v * vddio_k / mb_k;
930 else
931 r = v * mb_k / vddio_k;
932 return r;
933}
934
935/* called under codec_resource_lock acquisition */
936static void wcd9xxx_codec_hphr_gnd_switch(struct snd_soc_codec *codec, bool on)
937{
938 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01, on);
939 if (on)
940 usleep_range(5000, 5000);
941}
942
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -0700943static void wcd9xxx_onoff_vddio_switch(struct wcd9xxx_mbhc *mbhc, bool on)
944{
945 if (on) {
946 snd_soc_update_bits(mbhc->codec, mbhc->mbhc_bias_regs.mbhc_reg,
947 1 << 7, 1 << 7);
948 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MAD_ANA_CTRL,
949 1 << 4, 0);
950 } else {
951 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_MAD_ANA_CTRL,
952 1 << 4, 1 << 4);
953 snd_soc_update_bits(mbhc->codec, mbhc->mbhc_bias_regs.mbhc_reg,
954 1 << 7, 0);
955 }
956 if (on)
957 usleep_range(10000, 10000);
958}
959
Joonwoo Park20bc9da2013-01-16 12:58:06 -0800960static int wcd9xxx_hphl_status(struct wcd9xxx_mbhc *mbhc)
961{
962 u16 hph, status;
963 struct snd_soc_codec *codec = mbhc->codec;
964
965 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
966 hph = snd_soc_read(codec, WCD9XXX_A_MBHC_HPH);
967 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x12, 0x02);
968 usleep_range(WCD9XXX_HPHL_STATUS_READY_WAIT_US,
969 WCD9XXX_HPHL_STATUS_READY_WAIT_US +
970 WCD9XXX_USLEEP_RANGE_MARGIN_US);
971 status = snd_soc_read(codec, WCD9XXX_A_RX_HPH_L_STATUS);
972 snd_soc_write(codec, WCD9XXX_A_MBHC_HPH, hph);
973 return status;
974}
975
976/*
977 * wcd9xxx_find_plug_type : Find out and return the best plug type with given
978 * list of wcd9xxx_mbhc_detect structure.
979 */
980static enum wcd9xxx_mbhc_plug_type
981wcd9xxx_find_plug_type(struct wcd9xxx_mbhc *mbhc,
982 struct wcd9xxx_mbhc_detect *dt, const int size)
983{
984 int i;
985 int ch;
986 enum wcd9xxx_mbhc_plug_type type;
987 int vdce;
988 struct wcd9xxx_mbhc_detect *d, *dprev, *dgnd = NULL;
989 int maxv = 0, minv = 0;
990 const struct wcd9xxx_mbhc_plug_type_cfg *plug_type =
991 WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
992 const s16 hs_max = plug_type->v_hs_max;
993 const s16 no_mic = plug_type->v_no_mic;
994
995 for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
996 vdce = wcd9xxx_codec_sta_dce_v(mbhc, true, d->dce);
997 if (d->vddio)
998 d->_vdces = scale_v_micb_vddio(mbhc, vdce, false);
999 else
1000 d->_vdces = vdce;
1001
1002 if (d->_vdces >= no_mic && d->_vdces < hs_max)
1003 d->_type = PLUG_TYPE_HEADSET;
1004 else if (d->_vdces < no_mic)
1005 d->_type = PLUG_TYPE_HEADPHONE;
1006 else
1007 d->_type = PLUG_TYPE_HIGH_HPH;
1008
1009 ch += d->hphl_status & 0x01;
1010 if (!d->swap_gnd && !d->hwvalue) {
1011 if (maxv < d->_vdces)
1012 maxv = d->_vdces;
1013 if (!minv || minv > d->_vdces)
1014 minv = d->_vdces;
1015 }
1016
1017 pr_debug("%s: DCE #%d, %04x, V %04d(%04d), GND %d, VDDIO %d, HPHL %d TYPE %d\n",
1018 __func__, i, d->dce, vdce, d->_vdces,
1019 d->swap_gnd, d->vddio, d->hphl_status & 0x01,
1020 d->_type);
Joonwoo Park141d6182013-03-05 12:25:46 -08001021
1022
1023 /*
1024 * If GND and MIC prongs are aligned to HPHR and GND of
1025 * headphone, codec measures the voltage based on
1026 * impedance between HPHR and GND which results in ~80mv.
1027 * Avoid this.
1028 */
1029 if (d->_vdces >= WCD9XXX_MEAS_INVALD_RANGE_LOW_MV &&
1030 d->_vdces <= WCD9XXX_MEAS_INVALD_RANGE_HIGH_MV) {
1031 pr_debug("%s: within invalid range\n", __func__);
1032 type = PLUG_TYPE_INVALID;
1033 goto exit;
1034 }
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001035 }
1036 if (ch != size && ch > 0) {
1037 pr_debug("%s: Invalid, inconsistent HPHL\n", __func__);
1038 type = PLUG_TYPE_INVALID;
1039 goto exit;
1040 }
1041
1042 for (i = 0, d = dt, ch = 0; i < size; i++, d++) {
1043 if ((i > 0) && (d->_type != dprev->_type)) {
1044 pr_debug("%s: Invalid, inconsistent types\n", __func__);
1045 type = PLUG_TYPE_INVALID;
1046 goto exit;
1047 }
1048
1049 if (!d->swap_gnd && !d->hwvalue &&
1050 (abs(minv - d->_vdces) > WCD9XXX_MEAS_DELTA_MAX_MV ||
1051 abs(maxv - d->_vdces) > WCD9XXX_MEAS_DELTA_MAX_MV)) {
1052 pr_debug("%s: Invalid, delta %dmv, %dmv and %dmv\n",
1053 __func__, d->_vdces, minv, maxv);
1054 type = PLUG_TYPE_INVALID;
1055 goto exit;
1056 } else if (d->swap_gnd) {
1057 dgnd = d;
1058 }
1059 dprev = d;
1060 }
1061
1062 WARN_ON(i != size);
1063 type = dt->_type;
1064 if (type == PLUG_TYPE_HEADSET && dgnd) {
1065 if ((dgnd->_vdces + WCD9XXX_GM_SWAP_THRES_MIN_MV <
1066 minv) &&
1067 (dgnd->_vdces + WCD9XXX_GM_SWAP_THRES_MAX_MV >
1068 maxv))
1069 type = PLUG_TYPE_GND_MIC_SWAP;
1070 }
1071
1072exit:
1073 pr_debug("%s: Plug type %d detected\n", __func__, type);
1074 return type;
1075}
1076
Joonwoo Parka8890262012-10-15 12:04:27 -07001077static enum wcd9xxx_mbhc_plug_type
1078wcd9xxx_codec_get_plug_type(struct wcd9xxx_mbhc *mbhc, bool highhph)
1079{
1080 int i;
Joonwoo Parka8890262012-10-15 12:04:27 -07001081 struct wcd9xxx_mbhc_plug_type_cfg *plug_type_ptr;
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001082 struct wcd9xxx_mbhc_detect rt[NUM_DCE_PLUG_INS_DETECT];
1083 enum wcd9xxx_mbhc_plug_type type = PLUG_TYPE_INVALID;
Joonwoo Parka8890262012-10-15 12:04:27 -07001084 struct snd_soc_codec *codec = mbhc->codec;
Joonwoo Parka8890262012-10-15 12:04:27 -07001085
Joonwoo Park80a01172012-10-15 16:05:23 -07001086 pr_debug("%s: enter\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001087 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
1088
1089 /* make sure override is on */
1090 WARN_ON(!(snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL) & 0x04));
1091
1092 /* GND and MIC swap detection requires at least 2 rounds of DCE */
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001093 BUG_ON(NUM_DCE_PLUG_INS_DETECT < 2);
Joonwoo Parka8890262012-10-15 12:04:27 -07001094
1095 plug_type_ptr =
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001096 WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
Joonwoo Parka8890262012-10-15 12:04:27 -07001097
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001098 rt[0].hphl_status = wcd9xxx_hphl_status(mbhc);
1099 rt[0].dce = wcd9xxx_mbhc_setup_hs_polling(mbhc);
1100 rt[0].swap_gnd = false;
1101 rt[0].vddio = false;
1102 rt[0].hwvalue = true;
1103 for (i = 1; i < NUM_DCE_PLUG_INS_DETECT; i++) {
1104 rt[i].swap_gnd = (i == NUM_DCE_PLUG_INS_DETECT - 2);
1105 if (detect_use_vddio_switch)
1106 rt[i].vddio = (i == NUM_DCE_PLUG_INS_DETECT - 1);
1107 else
1108 rt[i].vddio = false;
1109 rt[i].hphl_status = wcd9xxx_hphl_status(mbhc);
1110 rt[i].hwvalue = false;
1111 if (rt[i].swap_gnd)
1112 wcd9xxx_codec_hphr_gnd_switch(codec, true);
1113 if (rt[i].vddio)
1114 wcd9xxx_onoff_vddio_switch(mbhc, true);
1115 rt[i].dce = __wcd9xxx_codec_sta_dce(mbhc, 1, true, true);
1116 if (rt[i].vddio)
1117 wcd9xxx_onoff_vddio_switch(mbhc, false);
1118 if (rt[i].swap_gnd)
1119 wcd9xxx_codec_hphr_gnd_switch(codec, false);
Joonwoo Parka8890262012-10-15 12:04:27 -07001120 }
1121
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001122 type = wcd9xxx_find_plug_type(mbhc, rt, ARRAY_SIZE(rt));
Joonwoo Parka8890262012-10-15 12:04:27 -07001123
Joonwoo Park80a01172012-10-15 16:05:23 -07001124 pr_debug("%s: leave\n", __func__);
Joonwoo Park20bc9da2013-01-16 12:58:06 -08001125 return type;
Joonwoo Parka8890262012-10-15 12:04:27 -07001126}
1127
1128static bool wcd9xxx_swch_level_remove(struct wcd9xxx_mbhc *mbhc)
1129{
1130 if (mbhc->mbhc_cfg->gpio)
1131 return (gpio_get_value_cansleep(mbhc->mbhc_cfg->gpio) !=
1132 mbhc->mbhc_cfg->gpio_level_insert);
1133 else if (mbhc->mbhc_cfg->insert_detect)
1134 return snd_soc_read(mbhc->codec,
1135 WCD9XXX_A_MBHC_INSERT_DET_STATUS) &
1136 (1 << 2);
1137 else
1138 WARN(1, "Invalid jack detection configuration\n");
1139
1140 return true;
1141}
1142
1143static bool is_clk_active(struct snd_soc_codec *codec)
1144{
1145 return !!(snd_soc_read(codec, WCD9XXX_A_CDC_CLK_MCLK_CTL) & 0x05);
1146}
1147
1148static int wcd9xxx_enable_hs_detect(struct wcd9xxx_mbhc *mbhc,
1149 int insertion, int trigger, bool padac_off)
1150{
1151 struct snd_soc_codec *codec = mbhc->codec;
1152 int central_bias_enabled = 0;
1153 const struct wcd9xxx_mbhc_general_cfg *generic =
1154 WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration);
1155 const struct wcd9xxx_mbhc_plug_detect_cfg *plug_det =
1156 WCD9XXX_MBHC_CAL_PLUG_DET_PTR(mbhc->mbhc_cfg->calibration);
1157
Joonwoo Park80a01172012-10-15 16:05:23 -07001158 pr_debug("%s: enter insertion(%d) trigger(0x%x)\n",
1159 __func__, insertion, trigger);
1160
Joonwoo Parka8890262012-10-15 12:04:27 -07001161 if (!mbhc->mbhc_cfg->calibration) {
1162 pr_err("Error, no wcd9xxx calibration\n");
1163 return -EINVAL;
1164 }
1165
1166 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x1, 0);
1167
1168 /*
1169 * Make sure mic bias and Mic line schmitt trigger
1170 * are turned OFF
1171 */
1172 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
1173 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
1174
1175 if (insertion) {
1176 wcd9xxx_switch_micbias(mbhc, 0);
1177
1178 /* DAPM can manipulate PA/DAC bits concurrently */
1179 if (padac_off == true)
1180 wcd9xxx_set_and_turnoff_hph_padac(mbhc);
1181
1182 if (trigger & MBHC_USE_HPHL_TRIGGER) {
1183 /* Enable HPH Schmitt Trigger */
1184 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x11,
1185 0x11);
1186 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x0C,
1187 plug_det->hph_current << 2);
1188 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x02,
1189 0x02);
1190 }
1191 if (trigger & MBHC_USE_MB_TRIGGER) {
1192 /* enable the mic line schmitt trigger */
1193 snd_soc_update_bits(codec,
1194 mbhc->mbhc_bias_regs.mbhc_reg,
1195 0x60, plug_det->mic_current << 5);
1196 snd_soc_update_bits(codec,
1197 mbhc->mbhc_bias_regs.mbhc_reg,
1198 0x80, 0x80);
1199 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
1200 snd_soc_update_bits(codec,
1201 mbhc->mbhc_bias_regs.ctl_reg, 0x01,
1202 0x00);
1203 snd_soc_update_bits(codec,
1204 mbhc->mbhc_bias_regs.mbhc_reg,
1205 0x10, 0x10);
1206 }
1207
1208 /* setup for insetion detection */
1209 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x2, 0);
1210 } else {
1211 pr_debug("setup for removal detection\n");
1212 /* Make sure the HPH schmitt trigger is OFF */
1213 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x12, 0x00);
1214
1215 /* enable the mic line schmitt trigger */
1216 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg,
1217 0x01, 0x00);
1218 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x60,
1219 plug_det->mic_current << 5);
1220 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg,
1221 0x80, 0x80);
1222 usleep_range(plug_det->t_mic_pid, plug_det->t_mic_pid);
1223 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg,
1224 0x10, 0x10);
1225
1226 /* Setup for low power removal detection */
1227 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x2,
1228 0x2);
1229 }
1230
1231 if (snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_CTL) & 0x4) {
1232 /* called by interrupt */
1233 if (!is_clk_active(codec)) {
1234 wcd9xxx_resmgr_enable_config_mode(codec, 1);
1235 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
1236 0x06, 0);
1237 usleep_range(generic->t_shutdown_plug_rem,
1238 generic->t_shutdown_plug_rem);
1239 wcd9xxx_resmgr_enable_config_mode(codec, 0);
1240 } else
1241 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL,
1242 0x06, 0);
1243 }
1244
1245 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.int_rbias, 0x80, 0);
1246
1247 /* If central bandgap disabled */
1248 if (!(snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE1) & 1)) {
1249 snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE1, 0x3, 0x3);
1250 usleep_range(generic->t_bg_fast_settle,
1251 generic->t_bg_fast_settle);
1252 central_bias_enabled = 1;
1253 }
1254
1255 /* If LDO_H disabled */
1256 if (snd_soc_read(codec, WCD9XXX_A_PIN_CTL_OE0) & 0x80) {
1257 snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x10, 0);
1258 snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0x80);
1259 usleep_range(generic->t_ldoh, generic->t_ldoh);
1260 snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE0, 0x80, 0);
1261
1262 if (central_bias_enabled)
1263 snd_soc_update_bits(codec, WCD9XXX_A_PIN_CTL_OE1, 0x1,
1264 0);
1265 }
1266
1267 snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc, 0x3,
1268 mbhc->mbhc_cfg->micbias);
1269
1270 wcd9xxx_enable_irq(mbhc->resmgr->core, WCD9XXX_IRQ_MBHC_INSERTION);
1271 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x1, 0x1);
Joonwoo Park80a01172012-10-15 16:05:23 -07001272 pr_debug("%s: leave\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001273
1274 return 0;
1275}
1276
1277/* called under codec_resource_lock acquisition */
1278static void wcd9xxx_find_plug_and_report(struct wcd9xxx_mbhc *mbhc,
1279 enum wcd9xxx_mbhc_plug_type plug_type)
1280{
Joonwoo Park80a01172012-10-15 16:05:23 -07001281 pr_debug("%s: enter current_plug(%d) new_plug(%d)\n",
1282 __func__, mbhc->current_plug, plug_type);
1283
Joonwoo Parka8890262012-10-15 12:04:27 -07001284 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
1285
1286 if (plug_type == PLUG_TYPE_HEADPHONE &&
1287 mbhc->current_plug == PLUG_TYPE_NONE) {
1288 /*
1289 * Nothing was reported previously
1290 * report a headphone or unsupported
1291 */
1292 wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
1293 wcd9xxx_cleanup_hs_polling(mbhc);
1294 } else if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
Joonwoo Park80a01172012-10-15 16:05:23 -07001295 if (!mbhc->mbhc_cfg->detect_extn_cable) {
1296 if (mbhc->current_plug == PLUG_TYPE_HEADSET)
1297 wcd9xxx_report_plug(mbhc, 0,
1298 SND_JACK_HEADSET);
1299 else if (mbhc->current_plug == PLUG_TYPE_HEADPHONE)
1300 wcd9xxx_report_plug(mbhc, 0,
1301 SND_JACK_HEADPHONE);
1302 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001303 wcd9xxx_report_plug(mbhc, 1, SND_JACK_UNSUPPORTED);
1304 wcd9xxx_cleanup_hs_polling(mbhc);
1305 } else if (plug_type == PLUG_TYPE_HEADSET) {
1306 /*
1307 * If Headphone was reported previously, this will
1308 * only report the mic line
1309 */
1310 wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADSET);
1311 msleep(100);
1312 wcd9xxx_start_hs_polling(mbhc);
1313 } else if (plug_type == PLUG_TYPE_HIGH_HPH) {
Joonwoo Park80a01172012-10-15 16:05:23 -07001314 if (mbhc->mbhc_cfg->detect_extn_cable) {
1315 /* High impedance device found. Report as LINEOUT*/
1316 wcd9xxx_report_plug(mbhc, 1, SND_JACK_LINEOUT);
1317 wcd9xxx_cleanup_hs_polling(mbhc);
1318 pr_debug("%s: setup mic trigger for further detection\n",
1319 __func__);
1320 mbhc->lpi_enabled = true;
1321 /*
1322 * Do not enable HPHL trigger. If playback is active,
1323 * it might lead to continuous false HPHL triggers
1324 */
1325 wcd9xxx_enable_hs_detect(mbhc, 1, MBHC_USE_MB_TRIGGER,
1326 false);
1327 } else {
1328 if (mbhc->current_plug == PLUG_TYPE_NONE)
1329 wcd9xxx_report_plug(mbhc, 1,
1330 SND_JACK_HEADPHONE);
1331 wcd9xxx_cleanup_hs_polling(mbhc);
1332 pr_debug("setup mic trigger for further detection\n");
1333 mbhc->lpi_enabled = true;
1334 wcd9xxx_enable_hs_detect(mbhc, 1, MBHC_USE_MB_TRIGGER |
1335 MBHC_USE_HPHL_TRIGGER,
1336 false);
1337 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001338 } else {
1339 WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
1340 mbhc->current_plug, plug_type);
1341 }
Joonwoo Park80a01172012-10-15 16:05:23 -07001342 pr_debug("%s: leave\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001343}
1344
1345/* called under codec_resource_lock acquisition */
1346static void wcd9xxx_mbhc_decide_swch_plug(struct wcd9xxx_mbhc *mbhc)
1347{
1348 enum wcd9xxx_mbhc_plug_type plug_type;
1349 struct snd_soc_codec *codec = mbhc->codec;
1350
1351 pr_debug("%s: enter\n", __func__);
1352
1353 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
1354
1355 wcd9xxx_turn_onoff_override(codec, true);
1356 plug_type = wcd9xxx_codec_get_plug_type(mbhc, true);
1357 wcd9xxx_turn_onoff_override(codec, false);
1358
1359 if (wcd9xxx_swch_level_remove(mbhc)) {
1360 pr_debug("%s: Switch level is low when determining plug\n",
1361 __func__);
1362 return;
1363 }
1364
1365 if (plug_type == PLUG_TYPE_INVALID ||
1366 plug_type == PLUG_TYPE_GND_MIC_SWAP) {
1367 wcd9xxx_schedule_hs_detect_plug(mbhc,
1368 &mbhc->correct_plug_swch);
1369 } else if (plug_type == PLUG_TYPE_HEADPHONE) {
1370 wcd9xxx_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
1371 wcd9xxx_schedule_hs_detect_plug(mbhc,
1372 &mbhc->correct_plug_swch);
1373 } else {
1374 pr_debug("%s: Valid plug found, determine plug type %d\n",
1375 __func__, plug_type);
1376 wcd9xxx_find_plug_and_report(mbhc, plug_type);
1377 }
Joonwoo Park80a01172012-10-15 16:05:23 -07001378 pr_debug("%s: leave\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001379}
1380
1381/* called under codec_resource_lock acquisition */
1382static void wcd9xxx_mbhc_detect_plug_type(struct wcd9xxx_mbhc *mbhc)
1383{
1384 struct snd_soc_codec *codec = mbhc->codec;
1385 const struct wcd9xxx_mbhc_plug_detect_cfg *plug_det =
1386 WCD9XXX_MBHC_CAL_PLUG_DET_PTR(mbhc->mbhc_cfg->calibration);
1387
Joonwoo Park80a01172012-10-15 16:05:23 -07001388 pr_debug("%s: enter\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001389 WCD9XXX_BCL_ASSERT_LOCKED(mbhc->resmgr);
1390
1391 /*
1392 * Turn on the override,
1393 * wcd9xxx_mbhc_setup_hs_polling requires override on
1394 */
1395 wcd9xxx_turn_onoff_override(codec, true);
1396 if (plug_det->t_ins_complete > 20)
1397 msleep(plug_det->t_ins_complete);
1398 else
1399 usleep_range(plug_det->t_ins_complete * 1000,
1400 plug_det->t_ins_complete * 1000);
1401 /* Turn off the override */
1402 wcd9xxx_turn_onoff_override(codec, false);
1403
1404 if (wcd9xxx_swch_level_remove(mbhc))
1405 pr_debug("%s: Switch level low when determining plug\n",
1406 __func__);
1407 else
1408 wcd9xxx_mbhc_decide_swch_plug(mbhc);
Joonwoo Park80a01172012-10-15 16:05:23 -07001409 pr_debug("%s: leave\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001410}
1411
1412/* called only from interrupt which is under codec_resource_lock acquisition */
1413static void wcd9xxx_hs_insert_irq_swch(struct wcd9xxx_mbhc *mbhc,
1414 bool is_removal)
1415{
1416 if (!is_removal) {
1417 pr_debug("%s: MIC trigger insertion interrupt\n", __func__);
1418
1419 rmb();
1420 if (mbhc->lpi_enabled)
1421 msleep(100);
1422
1423 rmb();
1424 if (!mbhc->lpi_enabled) {
1425 pr_debug("%s: lpi is disabled\n", __func__);
1426 } else if (!wcd9xxx_swch_level_remove(mbhc)) {
1427 pr_debug("%s: Valid insertion, detect plug type\n",
1428 __func__);
1429 wcd9xxx_mbhc_decide_swch_plug(mbhc);
1430 } else {
1431 pr_debug("%s: Invalid insertion stop plug detection\n",
1432 __func__);
1433 }
Joonwoo Park80a01172012-10-15 16:05:23 -07001434 } else if (mbhc->mbhc_cfg->detect_extn_cable) {
1435 pr_debug("%s: Removal\n", __func__);
1436 if (!wcd9xxx_swch_level_remove(mbhc)) {
1437 /*
1438 * Switch indicates, something is still inserted.
1439 * This could be extension cable i.e. headset is
1440 * removed from extension cable.
1441 */
1442 /* cancel detect plug */
1443 wcd9xxx_cancel_hs_detect_plug(mbhc,
1444 &mbhc->correct_plug_swch);
1445 wcd9xxx_mbhc_decide_swch_plug(mbhc);
1446 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001447 } else {
1448 pr_err("%s: Switch IRQ used, invalid MBHC Removal\n", __func__);
1449 }
1450}
1451
1452static bool is_valid_mic_voltage(struct wcd9xxx_mbhc *mbhc, s32 mic_mv)
1453{
1454 const struct wcd9xxx_mbhc_plug_type_cfg *plug_type =
1455 WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
1456 const s16 v_hs_max = wcd9xxx_get_current_v_hs_max(mbhc);
1457
1458 return (!(mic_mv > 10 && mic_mv < 80) && (mic_mv > plug_type->v_no_mic)
1459 && (mic_mv < v_hs_max)) ? true : false;
1460}
1461
1462/*
1463 * called under codec_resource_lock acquisition
1464 * returns true if mic voltage range is back to normal insertion
1465 * returns false either if timedout or removed
1466 */
1467static bool wcd9xxx_hs_remove_settle(struct wcd9xxx_mbhc *mbhc)
1468{
1469 int i;
1470 bool timedout, settled = false;
1471 s32 mic_mv[NUM_DCE_PLUG_DETECT];
1472 short mb_v[NUM_DCE_PLUG_DETECT];
1473 unsigned long retry = 0, timeout;
1474
1475 timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
1476 while (!(timedout = time_after(jiffies, timeout))) {
1477 retry++;
1478 if (wcd9xxx_swch_level_remove(mbhc)) {
1479 pr_debug("%s: Switch indicates removal\n", __func__);
1480 break;
1481 }
1482
1483 if (retry > 1)
1484 msleep(250);
1485 else
1486 msleep(50);
1487
1488 if (wcd9xxx_swch_level_remove(mbhc)) {
1489 pr_debug("%s: Switch indicates removal\n", __func__);
1490 break;
1491 }
1492
1493 for (i = 0; i < NUM_DCE_PLUG_DETECT; i++) {
1494 mb_v[i] = wcd9xxx_codec_sta_dce(mbhc, 1, true);
1495 mic_mv[i] = wcd9xxx_codec_sta_dce_v(mbhc, 1 , mb_v[i]);
1496 pr_debug("%s : DCE run %lu, mic_mv = %d(%x)\n",
1497 __func__, retry, mic_mv[i], mb_v[i]);
1498 }
1499
1500 if (wcd9xxx_swch_level_remove(mbhc)) {
1501 pr_debug("%s: Switcn indicates removal\n", __func__);
1502 break;
1503 }
1504
1505 if (mbhc->current_plug == PLUG_TYPE_NONE) {
1506 pr_debug("%s : headset/headphone is removed\n",
1507 __func__);
1508 break;
1509 }
1510
1511 for (i = 0; i < NUM_DCE_PLUG_DETECT; i++)
1512 if (!is_valid_mic_voltage(mbhc, mic_mv[i]))
1513 break;
1514
1515 if (i == NUM_DCE_PLUG_DETECT) {
1516 pr_debug("%s: MIC voltage settled\n", __func__);
1517 settled = true;
1518 msleep(200);
1519 break;
1520 }
1521 }
1522
1523 if (timedout)
1524 pr_debug("%s: Microphone did not settle in %d seconds\n",
1525 __func__, HS_DETECT_PLUG_TIME_MS);
1526 return settled;
1527}
1528
1529/* called only from interrupt which is under codec_resource_lock acquisition */
1530static void wcd9xxx_hs_remove_irq_swch(struct wcd9xxx_mbhc *mbhc)
1531{
Joonwoo Park80a01172012-10-15 16:05:23 -07001532 pr_debug("%s: enter\n", __func__);
Joonwoo Parka8890262012-10-15 12:04:27 -07001533 if (wcd9xxx_hs_remove_settle(mbhc))
1534 wcd9xxx_start_hs_polling(mbhc);
Joonwoo Park80a01172012-10-15 16:05:23 -07001535 pr_debug("%s: leave\n", __func__);
1536}
1537
1538/* called only from interrupt which is under codec_resource_lock acquisition */
1539static void wcd9xxx_hs_remove_irq_noswch(struct wcd9xxx_mbhc *mbhc)
1540{
1541 short bias_value;
1542 bool removed = true;
1543 struct snd_soc_codec *codec = mbhc->codec;
1544 const struct wcd9xxx_mbhc_general_cfg *generic =
1545 WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration);
1546 int min_us = FAKE_REMOVAL_MIN_PERIOD_MS * 1000;
1547
1548 pr_debug("%s: enter\n", __func__);
1549 if (mbhc->current_plug != PLUG_TYPE_HEADSET) {
1550 pr_debug("%s(): Headset is not inserted, ignore removal\n",
1551 __func__);
1552 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
1553 0x08, 0x08);
1554 return;
1555 }
1556
1557 usleep_range(generic->t_shutdown_plug_rem,
1558 generic->t_shutdown_plug_rem);
1559
1560 do {
1561 bias_value = wcd9xxx_codec_sta_dce(mbhc, 1, true);
1562 pr_debug("%s: DCE %d,%d, %d us left\n", __func__, bias_value,
1563 wcd9xxx_codec_sta_dce_v(mbhc, 1, bias_value), min_us);
1564 if (bias_value < wcd9xxx_get_current_v_ins(mbhc, false)) {
1565 pr_debug("%s: checking false removal\n", __func__);
1566 msleep(500);
1567 removed = !wcd9xxx_hs_remove_settle(mbhc);
1568 pr_debug("%s: headset %sactually removed\n", __func__,
1569 removed ? "" : "not ");
1570 break;
1571 }
1572 min_us -= mbhc->mbhc_data.t_dce;
1573 } while (min_us > 0);
1574
1575 if (removed) {
1576 if (mbhc->mbhc_cfg->detect_extn_cable) {
1577 if (!wcd9xxx_swch_level_remove(mbhc)) {
1578 /*
1579 * extension cable is still plugged in
1580 * report it as LINEOUT device
1581 */
1582 wcd9xxx_report_plug(mbhc, 1, SND_JACK_LINEOUT);
1583 wcd9xxx_cleanup_hs_polling(mbhc);
1584 wcd9xxx_enable_hs_detect(mbhc, 1,
1585 MBHC_USE_MB_TRIGGER,
1586 false);
1587 }
1588 } else {
1589 /* Cancel possibly running hs_detect_work */
1590 wcd9xxx_cancel_hs_detect_plug(mbhc,
1591 &mbhc->correct_plug_noswch);
1592 /*
1593 * If this removal is not false, first check the micbias
1594 * switch status and switch it to LDOH if it is already
1595 * switched to VDDIO.
1596 */
1597 wcd9xxx_switch_micbias(mbhc, 0);
1598
1599 wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADSET);
1600 wcd9xxx_cleanup_hs_polling(mbhc);
1601 wcd9xxx_enable_hs_detect(mbhc, 1, MBHC_USE_MB_TRIGGER |
1602 MBHC_USE_HPHL_TRIGGER,
1603 true);
1604 }
1605 } else {
1606 wcd9xxx_start_hs_polling(mbhc);
1607 }
1608 pr_debug("%s: leave\n", __func__);
1609}
1610
1611/* called only from interrupt which is under codec_resource_lock acquisition */
1612static void wcd9xxx_hs_insert_irq_extn(struct wcd9xxx_mbhc *mbhc,
1613 bool is_mb_trigger)
1614{
1615 /* Cancel possibly running hs_detect_work */
1616 wcd9xxx_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
1617
1618 if (is_mb_trigger) {
1619 pr_debug("%s: Waiting for Headphone left trigger\n", __func__);
1620 wcd9xxx_enable_hs_detect(mbhc, 1, MBHC_USE_HPHL_TRIGGER, false);
1621 } else {
1622 pr_debug("%s: HPHL trigger received, detecting plug type\n",
1623 __func__);
1624 wcd9xxx_mbhc_detect_plug_type(mbhc);
1625 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001626}
1627
1628static irqreturn_t wcd9xxx_hs_remove_irq(int irq, void *data)
1629{
1630 bool vddio;
1631 struct wcd9xxx_mbhc *mbhc = data;
1632
1633 pr_debug("%s: enter, removal interrupt\n", __func__);
1634 WCD9XXX_BCL_LOCK(mbhc->resmgr);
Joonwoo Park3699ca32013-02-08 12:06:15 -08001635 /*
1636 * While we don't know whether MIC is there or not, let the resmgr know
1637 * so micbias can be disabled temporarily
1638 */
Joonwoo Parkaf21f032013-03-05 18:07:40 -08001639 if (mbhc->current_plug == PLUG_TYPE_HEADSET) {
Joonwoo Park3699ca32013-02-08 12:06:15 -08001640 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1641 WCD9XXX_COND_HPH_MIC, false);
Joonwoo Parkaf21f032013-03-05 18:07:40 -08001642 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1643 WCD9XXX_COND_HPH, false);
1644 } else if (mbhc->current_plug == PLUG_TYPE_HEADPHONE) {
1645 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1646 WCD9XXX_COND_HPH, false);
1647 }
Joonwoo Park3699ca32013-02-08 12:06:15 -08001648
Joonwoo Parka8890262012-10-15 12:04:27 -07001649 vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
1650 mbhc->mbhc_micbias_switched);
1651 if (vddio)
Joonwoo Park91226742013-01-22 15:26:27 -08001652 __wcd9xxx_switch_micbias(mbhc, 0, false, true);
Joonwoo Parka8890262012-10-15 12:04:27 -07001653
Joonwoo Park80a01172012-10-15 16:05:23 -07001654 if (mbhc->mbhc_cfg->detect_extn_cable &&
1655 !wcd9xxx_swch_level_remove(mbhc))
1656 wcd9xxx_hs_remove_irq_noswch(mbhc);
1657 else
1658 wcd9xxx_hs_remove_irq_swch(mbhc);
Joonwoo Parka8890262012-10-15 12:04:27 -07001659
1660 /*
1661 * if driver turned off vddio switch and headset is not removed,
1662 * turn on the vddio switch back, if headset is removed then vddio
1663 * switch is off by time now and shouldn't be turn on again from here
1664 */
Joonwoo Park91226742013-01-22 15:26:27 -08001665 if (vddio && (mbhc->current_plug == PLUG_TYPE_HEADSET))
1666 __wcd9xxx_switch_micbias(mbhc, 1, true, true);
Joonwoo Park3699ca32013-02-08 12:06:15 -08001667
Joonwoo Parkaf21f032013-03-05 18:07:40 -08001668 if (mbhc->current_plug == PLUG_TYPE_HEADSET) {
1669 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1670 WCD9XXX_COND_HPH, true);
Joonwoo Park3699ca32013-02-08 12:06:15 -08001671 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1672 WCD9XXX_COND_HPH_MIC, true);
Joonwoo Parkaf21f032013-03-05 18:07:40 -08001673 } else if (mbhc->current_plug == PLUG_TYPE_HEADPHONE) {
1674 wcd9xxx_resmgr_cond_update_cond(mbhc->resmgr,
1675 WCD9XXX_COND_HPH, true);
1676 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001677 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
1678
1679 return IRQ_HANDLED;
1680}
1681
1682static irqreturn_t wcd9xxx_hs_insert_irq(int irq, void *data)
1683{
1684 bool is_mb_trigger, is_removal;
1685 struct wcd9xxx_mbhc *mbhc = data;
1686 struct snd_soc_codec *codec = mbhc->codec;
1687
1688 pr_debug("%s: enter\n", __func__);
1689 WCD9XXX_BCL_LOCK(mbhc->resmgr);
1690 wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_INSERTION);
1691
1692 is_mb_trigger = !!(snd_soc_read(codec, mbhc->mbhc_bias_regs.mbhc_reg) &
1693 0x10);
1694 is_removal = !!(snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_INT_CTL) & 0x02);
1695 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_INT_CTL, 0x03, 0x00);
1696
1697 /* Turn off both HPH and MIC line schmitt triggers */
1698 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
1699 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
1700 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
1701
Joonwoo Park80a01172012-10-15 16:05:23 -07001702 if (mbhc->mbhc_cfg->detect_extn_cable &&
1703 mbhc->current_plug == PLUG_TYPE_HIGH_HPH)
1704 wcd9xxx_hs_insert_irq_extn(mbhc, is_mb_trigger);
1705 else
1706 wcd9xxx_hs_insert_irq_swch(mbhc, is_removal);
Joonwoo Parka8890262012-10-15 12:04:27 -07001707
1708 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
1709 return IRQ_HANDLED;
1710}
1711
1712static void wcd9xxx_btn_lpress_fn(struct work_struct *work)
1713{
1714 struct delayed_work *dwork;
1715 short bias_value;
1716 int dce_mv, sta_mv;
1717 struct wcd9xxx_mbhc *mbhc;
1718
1719 pr_debug("%s:\n", __func__);
1720
1721 dwork = to_delayed_work(work);
1722 mbhc = container_of(dwork, struct wcd9xxx_mbhc, mbhc_btn_dwork);
1723
1724 bias_value = wcd9xxx_read_sta_result(mbhc->codec);
1725 sta_mv = wcd9xxx_codec_sta_dce_v(mbhc, 0, bias_value);
1726
1727 bias_value = wcd9xxx_read_dce_result(mbhc->codec);
1728 dce_mv = wcd9xxx_codec_sta_dce_v(mbhc, 1, bias_value);
1729 pr_debug("%s: STA: %d, DCE: %d\n", __func__, sta_mv, dce_mv);
1730
1731 pr_debug("%s: Reporting long button press event\n", __func__);
Joonwoo Park3699ca32013-02-08 12:06:15 -08001732 wcd9xxx_jack_report(mbhc, &mbhc->button_jack, mbhc->buttons_pressed,
Joonwoo Parka8890262012-10-15 12:04:27 -07001733 mbhc->buttons_pressed);
1734
1735 pr_debug("%s: leave\n", __func__);
1736 wcd9xxx_unlock_sleep(mbhc->resmgr->core);
1737}
1738
1739static void wcd9xxx_mbhc_insert_work(struct work_struct *work)
1740{
1741 struct delayed_work *dwork;
1742 struct wcd9xxx_mbhc *mbhc;
1743 struct snd_soc_codec *codec;
1744 struct wcd9xxx *core;
1745
1746 dwork = to_delayed_work(work);
1747 mbhc = container_of(dwork, struct wcd9xxx_mbhc, mbhc_insert_dwork);
1748 codec = mbhc->codec;
1749 core = mbhc->resmgr->core;
1750
1751 pr_debug("%s:\n", __func__);
1752
1753 /* Turn off both HPH and MIC line schmitt triggers */
1754 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.mbhc_reg, 0x90, 0x00);
1755 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x13, 0x00);
1756 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
1757 wcd9xxx_disable_irq_sync(core, WCD9XXX_IRQ_MBHC_INSERTION);
1758 wcd9xxx_mbhc_detect_plug_type(mbhc);
1759 wcd9xxx_unlock_sleep(core);
1760}
1761
1762static bool wcd9xxx_mbhc_fw_validate(const struct firmware *fw)
1763{
1764 u32 cfg_offset;
1765 struct wcd9xxx_mbhc_imped_detect_cfg *imped_cfg;
1766 struct wcd9xxx_mbhc_btn_detect_cfg *btn_cfg;
1767
1768 if (fw->size < WCD9XXX_MBHC_CAL_MIN_SIZE)
1769 return false;
1770
1771 /*
1772 * Previous check guarantees that there is enough fw data up
1773 * to num_btn
1774 */
1775 btn_cfg = WCD9XXX_MBHC_CAL_BTN_DET_PTR(fw->data);
1776 cfg_offset = (u32) ((void *) btn_cfg - (void *) fw->data);
1777 if (fw->size < (cfg_offset + WCD9XXX_MBHC_CAL_BTN_SZ(btn_cfg)))
1778 return false;
1779
1780 /*
1781 * Previous check guarantees that there is enough fw data up
1782 * to start of impedance detection configuration
1783 */
1784 imped_cfg = WCD9XXX_MBHC_CAL_IMPED_DET_PTR(fw->data);
1785 cfg_offset = (u32) ((void *) imped_cfg - (void *) fw->data);
1786
1787 if (fw->size < (cfg_offset + WCD9XXX_MBHC_CAL_IMPED_MIN_SZ))
1788 return false;
1789
1790 if (fw->size < (cfg_offset + WCD9XXX_MBHC_CAL_IMPED_SZ(imped_cfg)))
1791 return false;
1792
1793 return true;
1794}
1795
1796static u16 wcd9xxx_codec_v_sta_dce(struct wcd9xxx_mbhc *mbhc,
1797 enum meas_type dce, s16 vin_mv)
1798{
1799 s16 diff, zero;
1800 u32 mb_mv, in;
1801 u16 value;
1802
1803 mb_mv = mbhc->mbhc_data.micb_mv;
1804
1805 if (mb_mv == 0) {
1806 pr_err("%s: Mic Bias voltage is set to zero\n", __func__);
1807 return -EINVAL;
1808 }
1809
1810 if (dce) {
1811 diff = (mbhc->mbhc_data.dce_mb) - (mbhc->mbhc_data.dce_z);
1812 zero = (mbhc->mbhc_data.dce_z);
1813 } else {
1814 diff = (mbhc->mbhc_data.sta_mb) - (mbhc->mbhc_data.sta_z);
1815 zero = (mbhc->mbhc_data.sta_z);
1816 }
1817 in = (u32) diff * vin_mv;
1818
1819 value = (u16) (in / mb_mv) + zero;
1820 return value;
1821}
1822
1823static void wcd9xxx_mbhc_calc_thres(struct wcd9xxx_mbhc *mbhc)
1824{
1825 struct snd_soc_codec *codec;
1826 s16 btn_mv = 0, btn_delta_mv;
1827 struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
1828 struct wcd9xxx_mbhc_plug_type_cfg *plug_type;
1829 u16 *btn_high;
1830 int i;
1831
1832 pr_debug("%s: enter\n", __func__);
1833 codec = mbhc->codec;
1834 btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
1835 plug_type = WCD9XXX_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
1836
1837 mbhc->mbhc_data.v_ins_hu =
1838 wcd9xxx_codec_v_sta_dce(mbhc, STA, plug_type->v_hs_max);
1839 mbhc->mbhc_data.v_ins_h =
1840 wcd9xxx_codec_v_sta_dce(mbhc, DCE, plug_type->v_hs_max);
1841
1842 mbhc->mbhc_data.v_inval_ins_low = FAKE_INS_LOW;
1843 mbhc->mbhc_data.v_inval_ins_high = FAKE_INS_HIGH;
1844
1845 if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV) {
1846 mbhc->mbhc_data.adj_v_hs_max =
1847 scale_v_micb_vddio(mbhc, plug_type->v_hs_max, true);
1848 mbhc->mbhc_data.adj_v_ins_hu =
1849 wcd9xxx_codec_v_sta_dce(mbhc, STA,
1850 mbhc->mbhc_data.adj_v_hs_max);
1851 mbhc->mbhc_data.adj_v_ins_h =
1852 wcd9xxx_codec_v_sta_dce(mbhc, DCE,
1853 mbhc->mbhc_data.adj_v_hs_max);
1854 mbhc->mbhc_data.v_inval_ins_low =
1855 scale_v_micb_vddio(mbhc, mbhc->mbhc_data.v_inval_ins_low,
1856 false);
1857 mbhc->mbhc_data.v_inval_ins_high =
1858 scale_v_micb_vddio(mbhc, mbhc->mbhc_data.v_inval_ins_high,
1859 false);
1860 }
1861
1862 btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_det,
1863 MBHC_BTN_DET_V_BTN_HIGH);
1864 for (i = 0; i < btn_det->num_btn; i++)
1865 btn_mv = btn_high[i] > btn_mv ? btn_high[i] : btn_mv;
1866
1867 mbhc->mbhc_data.v_b1_h = wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_mv);
1868 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_sta;
1869 mbhc->mbhc_data.v_b1_hu =
1870 wcd9xxx_codec_v_sta_dce(mbhc, STA, btn_delta_mv);
1871
1872 btn_delta_mv = btn_mv + btn_det->v_btn_press_delta_cic;
1873
1874 mbhc->mbhc_data.v_b1_huc =
1875 wcd9xxx_codec_v_sta_dce(mbhc, DCE, btn_delta_mv);
1876
1877 mbhc->mbhc_data.v_brh = mbhc->mbhc_data.v_b1_h;
1878 mbhc->mbhc_data.v_brl = BUTTON_MIN;
1879
1880 mbhc->mbhc_data.v_no_mic =
1881 wcd9xxx_codec_v_sta_dce(mbhc, STA, plug_type->v_no_mic);
1882 pr_debug("%s: leave\n", __func__);
1883}
1884
1885static void wcd9xxx_onoff_ext_mclk(struct wcd9xxx_mbhc *mbhc, bool on)
1886{
1887 /*
1888 * XXX: {codec}_mclk_enable holds WCD9XXX_BCL_LOCK,
1889 * therefore wcd9xxx_onoff_ext_mclk caller SHOULDN'T hold
1890 * WCD9XXX_BCL_LOCK when it calls wcd9xxx_onoff_ext_mclk()
1891 */
1892 mbhc->mbhc_cfg->mclk_cb_fn(mbhc->codec, on, false);
1893}
1894
1895static void wcd9xxx_correct_swch_plug(struct work_struct *work)
1896{
1897 struct wcd9xxx_mbhc *mbhc;
1898 struct snd_soc_codec *codec;
Joonwoo Park80a01172012-10-15 16:05:23 -07001899 enum wcd9xxx_mbhc_plug_type plug_type = PLUG_TYPE_INVALID;
Joonwoo Parka8890262012-10-15 12:04:27 -07001900 unsigned long timeout;
1901 int retry = 0, pt_gnd_mic_swap_cnt = 0;
1902 bool correction = false;
1903
1904 pr_debug("%s: enter\n", __func__);
1905
1906 mbhc = container_of(work, struct wcd9xxx_mbhc, correct_plug_swch);
1907 codec = mbhc->codec;
1908
1909 wcd9xxx_onoff_ext_mclk(mbhc, true);
1910
1911 /*
1912 * Keep override on during entire plug type correction work.
1913 *
1914 * This is okay under the assumption that any switch irqs which use
1915 * MBHC block cancel and sync this work so override is off again
1916 * prior to switch interrupt handler's MBHC block usage.
1917 * Also while this correction work is running, we can guarantee
1918 * DAPM doesn't use any MBHC block as this work only runs with
1919 * headphone detection.
1920 */
1921 wcd9xxx_turn_onoff_override(codec, true);
1922
1923 timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
1924 while (!time_after(jiffies, timeout)) {
1925 ++retry;
1926 rmb();
1927 if (mbhc->hs_detect_work_stop) {
1928 pr_debug("%s: stop requested\n", __func__);
1929 break;
1930 }
1931
1932 msleep(HS_DETECT_PLUG_INERVAL_MS);
1933 if (wcd9xxx_swch_level_remove(mbhc)) {
1934 pr_debug("%s: Switch level is low\n", __func__);
1935 break;
1936 }
1937
1938 /* can race with removal interrupt */
1939 WCD9XXX_BCL_LOCK(mbhc->resmgr);
1940 plug_type = wcd9xxx_codec_get_plug_type(mbhc, true);
1941 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
1942
Joonwoo Park80a01172012-10-15 16:05:23 -07001943 pr_debug("%s: attempt(%d) current_plug(%d) new_plug(%d)\n",
1944 __func__, retry, mbhc->current_plug, plug_type);
Joonwoo Parka8890262012-10-15 12:04:27 -07001945 if (plug_type == PLUG_TYPE_INVALID) {
1946 pr_debug("Invalid plug in attempt # %d\n", retry);
Joonwoo Park80a01172012-10-15 16:05:23 -07001947 if (!mbhc->mbhc_cfg->detect_extn_cable &&
1948 retry == NUM_ATTEMPTS_TO_REPORT &&
Joonwoo Parka8890262012-10-15 12:04:27 -07001949 mbhc->current_plug == PLUG_TYPE_NONE) {
1950 wcd9xxx_report_plug(mbhc, 1,
1951 SND_JACK_HEADPHONE);
1952 }
1953 } else if (plug_type == PLUG_TYPE_HEADPHONE) {
1954 pr_debug("Good headphone detected, continue polling\n");
Joonwoo Park80a01172012-10-15 16:05:23 -07001955 if (mbhc->mbhc_cfg->detect_extn_cable) {
1956 if (mbhc->current_plug != plug_type)
1957 wcd9xxx_report_plug(mbhc, 1,
1958 SND_JACK_HEADPHONE);
1959 } else if (mbhc->current_plug == PLUG_TYPE_NONE) {
Joonwoo Parka8890262012-10-15 12:04:27 -07001960 wcd9xxx_report_plug(mbhc, 1,
1961 SND_JACK_HEADPHONE);
Joonwoo Park80a01172012-10-15 16:05:23 -07001962 }
Joonwoo Parka8890262012-10-15 12:04:27 -07001963 } else {
1964 if (plug_type == PLUG_TYPE_GND_MIC_SWAP) {
1965 pt_gnd_mic_swap_cnt++;
1966 if (pt_gnd_mic_swap_cnt <
1967 GND_MIC_SWAP_THRESHOLD)
1968 continue;
1969 else if (pt_gnd_mic_swap_cnt >
1970 GND_MIC_SWAP_THRESHOLD) {
1971 /*
1972 * This is due to GND/MIC switch didn't
1973 * work, Report unsupported plug
1974 */
1975 } else if (mbhc->mbhc_cfg->swap_gnd_mic) {
1976 /*
1977 * if switch is toggled, check again,
1978 * otherwise report unsupported plug
1979 */
1980 if (mbhc->mbhc_cfg->swap_gnd_mic(codec))
1981 continue;
1982 }
1983 } else
1984 pt_gnd_mic_swap_cnt = 0;
1985
1986 WCD9XXX_BCL_LOCK(mbhc->resmgr);
1987 /* Turn off override */
1988 wcd9xxx_turn_onoff_override(codec, false);
1989 /*
1990 * The valid plug also includes PLUG_TYPE_GND_MIC_SWAP
1991 */
1992 wcd9xxx_find_plug_and_report(mbhc, plug_type);
1993 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
1994 pr_debug("Attempt %d found correct plug %d\n", retry,
1995 plug_type);
1996 correction = true;
1997 break;
1998 }
1999 }
2000
2001 /* Turn off override */
2002 if (!correction)
2003 wcd9xxx_turn_onoff_override(codec, false);
2004
2005 wcd9xxx_onoff_ext_mclk(mbhc, false);
Joonwoo Park80a01172012-10-15 16:05:23 -07002006
2007 if (mbhc->mbhc_cfg->detect_extn_cable) {
2008 WCD9XXX_BCL_LOCK(mbhc->resmgr);
2009 if (mbhc->current_plug == PLUG_TYPE_HEADPHONE ||
2010 mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP ||
2011 mbhc->current_plug == PLUG_TYPE_INVALID ||
2012 plug_type == PLUG_TYPE_INVALID) {
2013 /* Enable removal detection */
2014 wcd9xxx_cleanup_hs_polling(mbhc);
2015 wcd9xxx_enable_hs_detect(mbhc, 0, 0, false);
2016 }
2017 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
2018 }
2019 pr_debug("%s: leave current_plug(%d)\n", __func__, mbhc->current_plug);
Joonwoo Parka8890262012-10-15 12:04:27 -07002020 /* unlock sleep */
2021 wcd9xxx_unlock_sleep(mbhc->resmgr->core);
2022}
2023
2024static void wcd9xxx_swch_irq_handler(struct wcd9xxx_mbhc *mbhc)
2025{
2026 bool insert;
2027 bool is_removed = false;
2028 struct snd_soc_codec *codec = mbhc->codec;
2029
2030 pr_debug("%s: enter\n", __func__);
2031
2032 mbhc->in_swch_irq_handler = true;
2033 /* Wait here for debounce time */
2034 usleep_range(SWCH_IRQ_DEBOUNCE_TIME_US, SWCH_IRQ_DEBOUNCE_TIME_US);
2035
2036 WCD9XXX_BCL_LOCK(mbhc->resmgr);
2037
2038 /* cancel pending button press */
2039 if (wcd9xxx_cancel_btn_work(mbhc))
2040 pr_debug("%s: button press is canceled\n", __func__);
2041
2042 insert = !wcd9xxx_swch_level_remove(mbhc);
2043 pr_debug("%s: Current plug type %d, insert %d\n", __func__,
2044 mbhc->current_plug, insert);
2045 if ((mbhc->current_plug == PLUG_TYPE_NONE) && insert) {
2046 mbhc->lpi_enabled = false;
2047 wmb();
2048
2049 /* cancel detect plug */
2050 wcd9xxx_cancel_hs_detect_plug(mbhc,
2051 &mbhc->correct_plug_swch);
2052
2053 /* Disable Mic Bias pull down and HPH Switch to GND */
2054 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01,
2055 0x00);
2056 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01, 0x00);
2057 wcd9xxx_mbhc_detect_plug_type(mbhc);
2058 } else if ((mbhc->current_plug != PLUG_TYPE_NONE) && !insert) {
2059 mbhc->lpi_enabled = false;
2060 wmb();
2061
2062 /* cancel detect plug */
2063 wcd9xxx_cancel_hs_detect_plug(mbhc,
2064 &mbhc->correct_plug_swch);
2065
2066 if (mbhc->current_plug == PLUG_TYPE_HEADPHONE) {
2067 wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
2068 is_removed = true;
2069 } else if (mbhc->current_plug == PLUG_TYPE_GND_MIC_SWAP) {
2070 wcd9xxx_report_plug(mbhc, 0, SND_JACK_UNSUPPORTED);
2071 is_removed = true;
2072 } else if (mbhc->current_plug == PLUG_TYPE_HEADSET) {
2073 wcd9xxx_pause_hs_polling(mbhc);
2074 wcd9xxx_cleanup_hs_polling(mbhc);
2075 wcd9xxx_report_plug(mbhc, 0, SND_JACK_HEADSET);
2076 is_removed = true;
Joonwoo Park80a01172012-10-15 16:05:23 -07002077 } else if (mbhc->current_plug == PLUG_TYPE_HIGH_HPH) {
2078 wcd9xxx_report_plug(mbhc, 0, SND_JACK_LINEOUT);
2079 is_removed = true;
Joonwoo Parka8890262012-10-15 12:04:27 -07002080 }
2081
2082 if (is_removed) {
2083 /* Enable Mic Bias pull down and HPH Switch to GND */
2084 snd_soc_update_bits(codec,
2085 mbhc->mbhc_bias_regs.ctl_reg, 0x01,
2086 0x01);
2087 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01,
2088 0x01);
2089 /* Make sure mic trigger is turned off */
2090 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg,
2091 0x01, 0x01);
2092 snd_soc_update_bits(codec,
2093 mbhc->mbhc_bias_regs.mbhc_reg,
2094 0x90, 0x00);
2095 /* Reset MBHC State Machine */
2096 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
2097 0x08, 0x08);
2098 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
2099 0x08, 0x00);
2100 /* Turn off override */
2101 wcd9xxx_turn_onoff_override(codec, false);
2102 }
2103 }
2104
2105 mbhc->in_swch_irq_handler = false;
2106 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
2107 pr_debug("%s: leave\n", __func__);
2108}
2109
2110static irqreturn_t wcd9xxx_mech_plug_detect_irq(int irq, void *data)
2111{
2112 int r = IRQ_HANDLED;
2113 struct wcd9xxx_mbhc *mbhc = data;
2114
2115 pr_debug("%s: enter\n", __func__);
2116 if (unlikely(wcd9xxx_lock_sleep(mbhc->resmgr->core) == false)) {
2117 pr_warn("%s: failed to hold suspend\n", __func__);
2118 r = IRQ_NONE;
2119 } else {
2120 /* Call handler */
2121 wcd9xxx_swch_irq_handler(mbhc);
2122 wcd9xxx_unlock_sleep(mbhc->resmgr->core);
2123 }
2124
2125 pr_debug("%s: leave %d\n", __func__, r);
2126 return r;
2127}
2128
2129/* called under codec_resource_lock acquisition */
2130static void wcd9xxx_codec_drive_v_to_micbias(struct wcd9xxx_mbhc *mbhc,
2131 int usec)
2132{
2133 int cfilt_k_val;
2134 bool set = true;
2135
2136 if (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
2137 mbhc->mbhc_micbias_switched) {
2138 pr_debug("%s: set mic V to micbias V\n", __func__);
2139 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_CDC_MBHC_CLK_CTL,
2140 0x2, 0x2);
2141 wcd9xxx_turn_onoff_override(mbhc->codec, true);
2142 while (1) {
2143 cfilt_k_val =
2144 wcd9xxx_resmgr_get_k_val(mbhc->resmgr,
2145 set ? mbhc->mbhc_data.micb_mv :
2146 VDDIO_MICBIAS_MV);
2147 snd_soc_update_bits(mbhc->codec,
2148 mbhc->mbhc_bias_regs.cfilt_val,
2149 0xFC, (cfilt_k_val << 2));
2150 if (!set)
2151 break;
2152 usleep_range(usec, usec);
2153 set = false;
2154 }
2155 wcd9xxx_turn_onoff_override(mbhc->codec, false);
2156 }
2157}
2158
2159static int wcd9xxx_is_fake_press(struct wcd9xxx_mbhc *mbhc)
2160{
2161 int i;
2162 int r = 0;
2163 const int dces = NUM_DCE_PLUG_DETECT;
2164 s16 mb_v, v_ins_hu, v_ins_h;
2165
2166 v_ins_hu = wcd9xxx_get_current_v_ins(mbhc, true);
2167 v_ins_h = wcd9xxx_get_current_v_ins(mbhc, false);
2168
2169 for (i = 0; i < dces; i++) {
2170 usleep_range(10000, 10000);
2171 if (i == 0) {
2172 mb_v = wcd9xxx_codec_sta_dce(mbhc, 0, true);
2173 pr_debug("%s: STA[0]: %d,%d\n", __func__, mb_v,
2174 wcd9xxx_codec_sta_dce_v(mbhc, 0, mb_v));
2175 if (mb_v < (s16)mbhc->mbhc_data.v_b1_hu ||
2176 mb_v > v_ins_hu) {
2177 r = 1;
2178 break;
2179 }
2180 } else {
2181 mb_v = wcd9xxx_codec_sta_dce(mbhc, 1, true);
2182 pr_debug("%s: DCE[%d]: %d,%d\n", __func__, i, mb_v,
2183 wcd9xxx_codec_sta_dce_v(mbhc, 1, mb_v));
2184 if (mb_v < (s16)mbhc->mbhc_data.v_b1_h ||
2185 mb_v > v_ins_h) {
2186 r = 1;
2187 break;
2188 }
2189 }
2190 }
2191
2192 return r;
2193}
2194
2195/* called under codec_resource_lock acquisition */
2196static int wcd9xxx_determine_button(const struct wcd9xxx_mbhc *mbhc,
2197 const s32 micmv)
2198{
2199 s16 *v_btn_low, *v_btn_high;
2200 struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
2201 int i, btn = -1;
2202
2203 btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
2204 v_btn_low = wcd9xxx_mbhc_cal_btn_det_mp(btn_det,
2205 MBHC_BTN_DET_V_BTN_LOW);
2206 v_btn_high = wcd9xxx_mbhc_cal_btn_det_mp(btn_det,
2207 MBHC_BTN_DET_V_BTN_HIGH);
2208
2209 for (i = 0; i < btn_det->num_btn; i++) {
2210 if ((v_btn_low[i] <= micmv) && (v_btn_high[i] >= micmv)) {
2211 btn = i;
2212 break;
2213 }
2214 }
2215
2216 if (btn == -1)
2217 pr_debug("%s: couldn't find button number for mic mv %d\n",
2218 __func__, micmv);
2219
2220 return btn;
2221}
2222
2223static int wcd9xxx_get_button_mask(const int btn)
2224{
2225 int mask = 0;
2226 switch (btn) {
2227 case 0:
2228 mask = SND_JACK_BTN_0;
2229 break;
2230 case 1:
2231 mask = SND_JACK_BTN_1;
2232 break;
2233 case 2:
2234 mask = SND_JACK_BTN_2;
2235 break;
2236 case 3:
2237 mask = SND_JACK_BTN_3;
2238 break;
2239 case 4:
2240 mask = SND_JACK_BTN_4;
2241 break;
2242 case 5:
2243 mask = SND_JACK_BTN_5;
2244 break;
2245 case 6:
2246 mask = SND_JACK_BTN_6;
2247 break;
2248 case 7:
2249 mask = SND_JACK_BTN_7;
2250 break;
2251 }
2252 return mask;
2253}
2254
2255irqreturn_t wcd9xxx_dce_handler(int irq, void *data)
2256{
2257 int i, mask;
2258 short dce, sta;
2259 s32 mv, mv_s, stamv_s;
2260 bool vddio;
2261 u8 mbhc_status;
2262 int btn = -1, meas = 0;
2263 struct wcd9xxx_mbhc *mbhc = data;
2264 const struct wcd9xxx_mbhc_btn_detect_cfg *d =
2265 WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
2266 short btnmeas[d->n_btn_meas + 1];
2267 struct snd_soc_codec *codec = mbhc->codec;
2268 struct wcd9xxx *core = mbhc->resmgr->core;
2269 int n_btn_meas = d->n_btn_meas;
2270
2271 pr_debug("%s: enter\n", __func__);
2272
2273 WCD9XXX_BCL_LOCK(mbhc->resmgr);
2274 mbhc_status = snd_soc_read(codec, WCD9XXX_A_CDC_MBHC_B1_STATUS) & 0x3E;
2275
2276 if (mbhc->mbhc_state == MBHC_STATE_POTENTIAL_RECOVERY) {
2277 pr_debug("%s: mbhc is being recovered, skip button press\n",
2278 __func__);
2279 goto done;
2280 }
2281
2282 mbhc->mbhc_state = MBHC_STATE_POTENTIAL;
2283
2284 if (!mbhc->polling_active) {
2285 pr_warn("%s: mbhc polling is not active, skip button press\n",
2286 __func__);
2287 goto done;
2288 }
2289
2290 dce = wcd9xxx_read_dce_result(codec);
2291 mv = wcd9xxx_codec_sta_dce_v(mbhc, 1, dce);
2292
2293 /* If switch nterrupt already kicked in, ignore button press */
2294 if (mbhc->in_swch_irq_handler) {
2295 pr_debug("%s: Swtich level changed, ignore button press\n",
2296 __func__);
2297 btn = -1;
2298 goto done;
2299 }
2300
2301 /* Measure scaled HW DCE */
2302 vddio = (mbhc->mbhc_data.micb_mv != VDDIO_MICBIAS_MV &&
2303 mbhc->mbhc_micbias_switched);
2304 mv_s = vddio ? scale_v_micb_vddio(mbhc, mv, false) : mv;
2305
2306 /* Measure scaled HW STA */
2307 sta = wcd9xxx_read_sta_result(codec);
2308 stamv_s = wcd9xxx_codec_sta_dce_v(mbhc, 0, sta);
2309 if (vddio)
2310 stamv_s = scale_v_micb_vddio(mbhc, stamv_s, false);
2311 if (mbhc_status != STATUS_REL_DETECTION) {
2312 if (mbhc->mbhc_last_resume &&
2313 !time_after(jiffies, mbhc->mbhc_last_resume + HZ)) {
2314 pr_debug("%s: Button is released after resume\n",
2315 __func__);
2316 n_btn_meas = 0;
2317 } else {
2318 pr_debug("%s: Button is released without resume",
2319 __func__);
2320 btn = wcd9xxx_determine_button(mbhc, mv_s);
2321 if (btn != wcd9xxx_determine_button(mbhc, stamv_s))
2322 btn = -1;
2323 goto done;
2324 }
2325 }
2326
2327 pr_debug("%s: Meas HW - STA 0x%x,%d,%d\n", __func__,
2328 sta & 0xFFFF, wcd9xxx_codec_sta_dce_v(mbhc, 0, sta), stamv_s);
2329
2330 /* determine pressed button */
2331 btnmeas[meas++] = wcd9xxx_determine_button(mbhc, mv_s);
2332 pr_debug("%s: Meas HW - DCE 0x%x,%d,%d button %d\n", __func__,
2333 dce & 0xFFFF, mv, mv_s, btnmeas[meas - 1]);
2334 if (n_btn_meas == 0)
2335 btn = btnmeas[0];
2336 for (; ((d->n_btn_meas) && (meas < (d->n_btn_meas + 1))); meas++) {
2337 dce = wcd9xxx_codec_sta_dce(mbhc, 1, false);
2338 mv = wcd9xxx_codec_sta_dce_v(mbhc, 1, dce);
2339 mv_s = vddio ? scale_v_micb_vddio(mbhc, mv, false) : mv;
2340
2341 btnmeas[meas] = wcd9xxx_determine_button(mbhc, mv_s);
2342 pr_debug("%s: Meas %d - DCE 0x%x,%d,%d button %d\n",
2343 __func__, meas, dce & 0xFFFF, mv, mv_s, btnmeas[meas]);
2344 /*
2345 * if large enough measurements are collected,
2346 * start to check if last all n_btn_con measurements were
2347 * in same button low/high range
2348 */
2349 if (meas + 1 >= d->n_btn_con) {
2350 for (i = 0; i < d->n_btn_con; i++)
2351 if ((btnmeas[meas] < 0) ||
2352 (btnmeas[meas] != btnmeas[meas - i]))
2353 break;
2354 if (i == d->n_btn_con) {
2355 /* button pressed */
2356 btn = btnmeas[meas];
2357 break;
2358 } else if ((n_btn_meas - meas) < (d->n_btn_con - 1)) {
2359 /*
2360 * if left measurements are less than n_btn_con,
2361 * it's impossible to find button number
2362 */
2363 break;
2364 }
2365 }
2366 }
2367
2368 if (btn >= 0) {
2369 if (mbhc->in_swch_irq_handler) {
2370 pr_debug(
2371 "%s: Switch irq triggered, ignore button press\n",
2372 __func__);
2373 goto done;
2374 }
2375 mask = wcd9xxx_get_button_mask(btn);
2376 mbhc->buttons_pressed |= mask;
2377 wcd9xxx_lock_sleep(core);
2378 if (schedule_delayed_work(&mbhc->mbhc_btn_dwork,
2379 msecs_to_jiffies(400)) == 0) {
2380 WARN(1, "Button pressed twice without release event\n");
2381 wcd9xxx_unlock_sleep(core);
2382 }
2383 } else {
2384 pr_debug("%s: bogus button press, too short press?\n",
2385 __func__);
2386 }
2387
2388 done:
2389 pr_debug("%s: leave\n", __func__);
2390 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
2391 return IRQ_HANDLED;
2392}
2393
2394static irqreturn_t wcd9xxx_release_handler(int irq, void *data)
2395{
2396 int ret;
2397 struct wcd9xxx_mbhc *mbhc = data;
2398
2399 pr_debug("%s: enter\n", __func__);
2400 WCD9XXX_BCL_LOCK(mbhc->resmgr);
2401 mbhc->mbhc_state = MBHC_STATE_RELEASE;
2402
2403 wcd9xxx_codec_drive_v_to_micbias(mbhc, 10000);
2404
2405 if (mbhc->buttons_pressed & WCD9XXX_JACK_BUTTON_MASK) {
2406 ret = wcd9xxx_cancel_btn_work(mbhc);
2407 if (ret == 0) {
2408 pr_debug("%s: Reporting long button release event\n",
2409 __func__);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002410 wcd9xxx_jack_report(mbhc, &mbhc->button_jack, 0,
Joonwoo Parka8890262012-10-15 12:04:27 -07002411 mbhc->buttons_pressed);
2412 } else {
2413 if (wcd9xxx_is_fake_press(mbhc)) {
2414 pr_debug("%s: Fake button press interrupt\n",
2415 __func__);
2416 } else {
2417 if (mbhc->in_swch_irq_handler) {
2418 pr_debug("%s: Switch irq kicked in, ignore\n",
2419 __func__);
2420 } else {
2421 pr_debug("%s: Reporting btn press\n",
2422 __func__);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002423 wcd9xxx_jack_report(mbhc,
2424 &mbhc->button_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -07002425 mbhc->buttons_pressed,
2426 mbhc->buttons_pressed);
2427 pr_debug("%s: Reporting btn release\n",
2428 __func__);
Joonwoo Park3699ca32013-02-08 12:06:15 -08002429 wcd9xxx_jack_report(mbhc,
2430 &mbhc->button_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -07002431 0, mbhc->buttons_pressed);
2432 }
2433 }
2434 }
2435
2436 mbhc->buttons_pressed &= ~WCD9XXX_JACK_BUTTON_MASK;
2437 }
2438
2439 wcd9xxx_calibrate_hs_polling(mbhc);
2440
2441 msleep(SWCH_REL_DEBOUNCE_TIME_MS);
2442 wcd9xxx_start_hs_polling(mbhc);
2443
2444 pr_debug("%s: leave\n", __func__);
2445 WCD9XXX_BCL_UNLOCK(mbhc->resmgr);
2446 return IRQ_HANDLED;
2447}
2448
2449static irqreturn_t wcd9xxx_hphl_ocp_irq(int irq, void *data)
2450{
2451 struct wcd9xxx_mbhc *mbhc = data;
2452 struct snd_soc_codec *codec;
2453
2454 pr_info("%s: received HPHL OCP irq\n", __func__);
2455
2456 if (mbhc) {
2457 codec = mbhc->codec;
2458 if (mbhc->hphlocp_cnt++ < OCP_ATTEMPT) {
2459 pr_info("%s: retry\n", __func__);
2460 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
2461 0x10, 0x00);
2462 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL,
2463 0x10, 0x10);
2464 } else {
2465 wcd9xxx_disable_irq(codec->control_data,
2466 WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
2467 mbhc->hphlocp_cnt = 0;
2468 mbhc->hph_status |= SND_JACK_OC_HPHL;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002469 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -07002470 mbhc->hph_status,
2471 WCD9XXX_JACK_MASK);
2472 }
2473 } else {
2474 pr_err("%s: Bad wcd9xxx private data\n", __func__);
2475 }
2476
2477 return IRQ_HANDLED;
2478}
2479
2480static irqreturn_t wcd9xxx_hphr_ocp_irq(int irq, void *data)
2481{
2482 struct wcd9xxx_mbhc *mbhc = data;
2483 struct snd_soc_codec *codec;
2484
2485 pr_info("%s: received HPHR OCP irq\n", __func__);
2486 codec = mbhc->codec;
2487 if (mbhc->hphrocp_cnt++ < OCP_ATTEMPT) {
2488 pr_info("%s: retry\n", __func__);
2489 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
2490 0x00);
2491 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
2492 0x10);
2493 } else {
2494 wcd9xxx_disable_irq(mbhc->resmgr->core,
2495 WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
2496 mbhc->hphrocp_cnt = 0;
2497 mbhc->hph_status |= SND_JACK_OC_HPHR;
Joonwoo Park3699ca32013-02-08 12:06:15 -08002498 wcd9xxx_jack_report(mbhc, &mbhc->headset_jack,
Joonwoo Parka8890262012-10-15 12:04:27 -07002499 mbhc->hph_status, WCD9XXX_JACK_MASK);
2500 }
2501
2502 return IRQ_HANDLED;
2503}
2504
2505static int wcd9xxx_acdb_mclk_index(const int rate)
2506{
2507 if (rate == MCLK_RATE_12288KHZ)
2508 return 0;
2509 else if (rate == MCLK_RATE_9600KHZ)
2510 return 1;
2511 else {
2512 BUG_ON(1);
2513 return -EINVAL;
2514 }
2515}
2516
2517static void wcd9xxx_update_mbhc_clk_rate(struct wcd9xxx_mbhc *mbhc, u32 rate)
2518{
2519 u32 dce_wait, sta_wait;
2520 u8 ncic, nmeas, navg;
2521 void *calibration;
2522 u8 *n_cic, *n_ready;
2523 struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
2524 u8 npoll = 4, nbounce_wait = 30;
2525 struct snd_soc_codec *codec = mbhc->codec;
2526 int idx = wcd9xxx_acdb_mclk_index(rate);
2527 int idxmclk = wcd9xxx_acdb_mclk_index(mbhc->mbhc_cfg->mclk_rate);
2528
2529 pr_debug("%s: Updating clock rate dependents, rate = %u\n", __func__,
2530 rate);
2531 calibration = mbhc->mbhc_cfg->calibration;
2532
2533 /*
2534 * First compute the DCE / STA wait times depending on tunable
2535 * parameters. The value is computed in microseconds
2536 */
2537 btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(calibration);
2538 n_ready = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_N_READY);
2539 n_cic = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_N_CIC);
2540 nmeas = WCD9XXX_MBHC_CAL_BTN_DET_PTR(calibration)->n_meas;
2541 navg = WCD9XXX_MBHC_CAL_GENERAL_PTR(calibration)->mbhc_navg;
2542
2543 /* ncic stays with the same what we had during calibration */
2544 ncic = n_cic[idxmclk];
2545 dce_wait = (1000 * 512 * ncic * (nmeas + 1)) / (rate / 1000);
2546 sta_wait = (1000 * 128 * (navg + 1)) / (rate / 1000);
2547 mbhc->mbhc_data.t_dce = dce_wait;
2548 mbhc->mbhc_data.t_sta = sta_wait;
2549 mbhc->mbhc_data.t_sta_dce = ((1000 * 256) / (rate / 1000) *
2550 n_ready[idx]) + 10;
2551
2552 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_TIMER_B1_CTL, n_ready[idx]);
2553 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_TIMER_B6_CTL, ncic);
2554
2555 if (rate == MCLK_RATE_12288KHZ) {
2556 npoll = 4;
2557 nbounce_wait = 30;
2558 } else if (rate == MCLK_RATE_9600KHZ) {
2559 npoll = 3;
2560 nbounce_wait = 23;
2561 }
2562
2563 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_TIMER_B2_CTL, npoll);
2564 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_TIMER_B3_CTL, nbounce_wait);
2565 pr_debug("%s: leave\n", __func__);
2566}
2567
2568static void wcd9xxx_mbhc_cal(struct wcd9xxx_mbhc *mbhc)
2569{
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07002570 u8 cfilt_mode;
Joonwoo Park7902f4c2013-02-20 15:21:25 -08002571 u16 reg0, reg1;
Joonwoo Parka8890262012-10-15 12:04:27 -07002572 struct snd_soc_codec *codec = mbhc->codec;
2573
2574 pr_debug("%s: enter\n", __func__);
2575 wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
2576 wcd9xxx_turn_onoff_rel_detection(codec, false);
2577
2578 /* t_dce and t_sta are updated by wcd9xxx_update_mbhc_clk_rate() */
2579 WARN_ON(!mbhc->mbhc_data.t_dce);
2580 WARN_ON(!mbhc->mbhc_data.t_sta);
2581
2582 /*
2583 * LDOH and CFILT are already configured during pdata handling.
2584 * Only need to make sure CFILT and bandgap are in Fast mode.
2585 * Need to restore defaults once calculation is done.
2586 */
2587 cfilt_mode = snd_soc_read(codec, mbhc->mbhc_bias_regs.cfilt_ctl);
2588 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40, 0x00);
Joonwoo Parka8890262012-10-15 12:04:27 -07002589
2590 /*
2591 * Micbias, CFILT, LDOH, MBHC MUX mode settings
2592 * to perform ADC calibration
2593 */
2594 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x60,
2595 mbhc->mbhc_cfg->micbias << 5);
2596 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x00);
2597 snd_soc_update_bits(codec, WCD9XXX_A_LDO_H_MODE_1, 0x60, 0x60);
2598 snd_soc_write(codec, WCD9XXX_A_TX_7_MBHC_TEST_CTL, 0x78);
2599 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x04);
2600
Joonwoo Park7902f4c2013-02-20 15:21:25 -08002601 /* Pull down micbias to ground */
2602 reg0 = snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg);
2603 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 1, 1);
2604 /* Disconnect override from micbias */
2605 reg1 = snd_soc_read(codec, WCD9XXX_A_MAD_ANA_CTRL);
2606 snd_soc_update_bits(codec, WCD9XXX_A_MAD_ANA_CTRL, 1 << 4, 1 << 0);
2607 /* Connect the MUX to micbias */
2608 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
2609 usleep_range(WCD9XXX_MUX_SWITCH_READY_WAIT_US,
2610 WCD9XXX_MUX_SWITCH_READY_WAIT_US +
2611 WCD9XXX_USLEEP_RANGE_MARGIN_US);
2612 /* DCE measurement for 0 voltage */
Joonwoo Parka8890262012-10-15 12:04:27 -07002613 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
Joonwoo Parka8890262012-10-15 12:04:27 -07002614 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
Joonwoo Park7902f4c2013-02-20 15:21:25 -08002615 mbhc->mbhc_data.dce_z = __wcd9xxx_codec_sta_dce(mbhc, 1, true, false);
2616 /* STA measurement for 0 voltage */
2617 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
2618 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
2619 mbhc->mbhc_data.sta_z = __wcd9xxx_codec_sta_dce(mbhc, 0, true, false);
2620 /* Restore registers */
2621 snd_soc_write(codec, mbhc->mbhc_bias_regs.ctl_reg, reg0);
2622 snd_soc_write(codec, WCD9XXX_A_MAD_ANA_CTRL, reg1);
Joonwoo Parka8890262012-10-15 12:04:27 -07002623
2624 /* DCE measurment for MB voltage */
2625 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
2626 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
2627 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
2628 usleep_range(100, 100);
2629 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x04);
2630 usleep_range(mbhc->mbhc_data.t_dce, mbhc->mbhc_data.t_dce);
2631 mbhc->mbhc_data.dce_mb = wcd9xxx_read_dce_result(codec);
2632
Joonwoo Park7902f4c2013-02-20 15:21:25 -08002633 /* STA Measurement for MB Voltage */
Joonwoo Parka8890262012-10-15 12:04:27 -07002634 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x0A);
2635 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
2636 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_CLK_CTL, 0x02);
Joonwoo Parka8890262012-10-15 12:04:27 -07002637 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x82);
2638 usleep_range(100, 100);
2639 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_EN_CTL, 0x02);
2640 usleep_range(mbhc->mbhc_data.t_sta, mbhc->mbhc_data.t_sta);
2641 mbhc->mbhc_data.sta_mb = wcd9xxx_read_sta_result(codec);
2642
2643 /* Restore default settings. */
2644 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x04, 0x00);
2645 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl, 0x40,
2646 cfilt_mode);
Joonwoo Parka8890262012-10-15 12:04:27 -07002647
2648 snd_soc_write(codec, WCD9XXX_A_MBHC_SCALING_MUX_1, 0x84);
2649 usleep_range(100, 100);
2650
2651 wcd9xxx_enable_irq(codec->control_data, WCD9XXX_IRQ_MBHC_POTENTIAL);
2652 wcd9xxx_turn_onoff_rel_detection(codec, true);
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07002653
Joonwoo Parka8890262012-10-15 12:04:27 -07002654 pr_debug("%s: leave\n", __func__);
2655}
2656
2657static void wcd9xxx_mbhc_setup(struct wcd9xxx_mbhc *mbhc)
2658{
2659 int n;
2660 u8 *gain;
2661 struct wcd9xxx_mbhc_general_cfg *generic;
2662 struct wcd9xxx_mbhc_btn_detect_cfg *btn_det;
2663 struct snd_soc_codec *codec = mbhc->codec;
2664 const int idx = wcd9xxx_acdb_mclk_index(mbhc->mbhc_cfg->mclk_rate);
2665
2666 pr_debug("%s: enter\n", __func__);
2667 generic = WCD9XXX_MBHC_CAL_GENERAL_PTR(mbhc->mbhc_cfg->calibration);
2668 btn_det = WCD9XXX_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
2669
2670 for (n = 0; n < 8; n++) {
2671 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_FIR_B1_CFG,
2672 0x07, n);
2673 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_FIR_B2_CFG,
2674 btn_det->c[n]);
2675 }
2676
2677 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B2_CTL, 0x07,
2678 btn_det->nc);
2679
2680 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x70,
2681 generic->mbhc_nsa << 4);
2682
2683 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_TIMER_B4_CTL, 0x0F,
2684 btn_det->n_meas);
2685
2686 snd_soc_write(codec, WCD9XXX_A_CDC_MBHC_TIMER_B5_CTL,
2687 generic->mbhc_navg);
2688
2689 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x80, 0x80);
2690
2691 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x78,
2692 btn_det->mbhc_nsc << 3);
2693
2694 snd_soc_update_bits(codec, mbhc->resmgr->reg_addr->micb_4_mbhc, 0x03,
2695 MBHC_MICBIAS2);
2696
2697 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B1_CTL, 0x02, 0x02);
2698
2699 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_SCALING_MUX_2, 0xF0, 0xF0);
2700
2701 gain = wcd9xxx_mbhc_cal_btn_det_mp(btn_det, MBHC_BTN_DET_GAIN);
2702 snd_soc_update_bits(codec, WCD9XXX_A_CDC_MBHC_B2_CTL, 0x78,
2703 gain[idx] << 3);
2704
2705 pr_debug("%s: leave\n", __func__);
2706}
2707
2708static int wcd9xxx_setup_jack_detect_irq(struct wcd9xxx_mbhc *mbhc)
2709{
2710 int ret = 0;
2711 void *core = mbhc->resmgr->core;
2712
2713 if (mbhc->mbhc_cfg->gpio) {
2714 ret = request_threaded_irq(mbhc->mbhc_cfg->gpio_irq, NULL,
2715 wcd9xxx_mech_plug_detect_irq,
2716 (IRQF_TRIGGER_RISING |
2717 IRQF_TRIGGER_FALLING |
2718 IRQF_DISABLED),
2719 "headset detect", mbhc);
2720 if (ret) {
2721 pr_err("%s: Failed to request gpio irq %d\n", __func__,
2722 mbhc->mbhc_cfg->gpio_irq);
2723 } else {
2724 ret = enable_irq_wake(mbhc->mbhc_cfg->gpio_irq);
2725 if (ret)
2726 pr_err("%s: Failed to enable wake up irq %d\n",
2727 __func__, mbhc->mbhc_cfg->gpio_irq);
2728 }
2729 } else if (mbhc->mbhc_cfg->insert_detect) {
2730 /* Enable HPHL_10K_SW */
2731 snd_soc_update_bits(mbhc->codec, WCD9XXX_A_RX_HPH_OCP_CTL,
2732 1 << 1, 1 << 1);
2733 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_JACK_SWITCH,
2734 wcd9xxx_mech_plug_detect_irq,
2735 "Jack Detect",
2736 mbhc);
2737 if (ret)
2738 pr_err("%s: Failed to request insert detect irq %d\n",
2739 __func__, WCD9XXX_IRQ_MBHC_JACK_SWITCH);
2740 }
2741
2742 return ret;
2743}
2744
2745static int wcd9xxx_init_and_calibrate(struct wcd9xxx_mbhc *mbhc)
2746{
2747 int ret = 0;
2748 struct snd_soc_codec *codec = mbhc->codec;
2749
2750 pr_debug("%s: enter\n", __func__);
2751
2752 /* Enable MCLK during calibration */
2753 wcd9xxx_onoff_ext_mclk(mbhc, true);
2754 wcd9xxx_mbhc_setup(mbhc);
2755 wcd9xxx_mbhc_cal(mbhc);
2756 wcd9xxx_mbhc_calc_thres(mbhc);
2757 wcd9xxx_onoff_ext_mclk(mbhc, false);
2758 wcd9xxx_calibrate_hs_polling(mbhc);
2759
2760 /* Enable Mic Bias pull down and HPH Switch to GND */
2761 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.ctl_reg, 0x01, 0x01);
2762 snd_soc_update_bits(codec, WCD9XXX_A_MBHC_HPH, 0x01, 0x01);
2763 INIT_WORK(&mbhc->correct_plug_swch, wcd9xxx_correct_swch_plug);
2764
2765 if (!IS_ERR_VALUE(ret)) {
2766 snd_soc_update_bits(codec, WCD9XXX_A_RX_HPH_OCP_CTL, 0x10,
2767 0x10);
2768 wcd9xxx_enable_irq(codec->control_data,
2769 WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
2770 wcd9xxx_enable_irq(codec->control_data,
2771 WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
2772
2773 /* Initialize mechanical mbhc */
2774 ret = wcd9xxx_setup_jack_detect_irq(mbhc);
2775
2776 if (!ret && mbhc->mbhc_cfg->gpio) {
2777 /* Requested with IRQF_DISABLED */
2778 enable_irq(mbhc->mbhc_cfg->gpio_irq);
2779
2780 /* Bootup time detection */
2781 wcd9xxx_swch_irq_handler(mbhc);
2782 } else if (!ret && mbhc->mbhc_cfg->insert_detect) {
2783 pr_debug("%s: Setting up codec own insert detection\n",
2784 __func__);
2785 /* Setup for insertion detection */
2786 wcd9xxx_insert_detect_setup(mbhc, true);
2787 }
2788 }
2789
2790 pr_debug("%s: leave\n", __func__);
2791
2792 return ret;
2793}
2794
2795static void wcd9xxx_mbhc_fw_read(struct work_struct *work)
2796{
2797 struct delayed_work *dwork;
2798 struct wcd9xxx_mbhc *mbhc;
2799 struct snd_soc_codec *codec;
2800 const struct firmware *fw;
2801 int ret = -1, retry = 0;
2802
2803 dwork = to_delayed_work(work);
2804 mbhc = container_of(dwork, struct wcd9xxx_mbhc, mbhc_firmware_dwork);
2805 codec = mbhc->codec;
2806
2807 while (retry < FW_READ_ATTEMPTS) {
2808 retry++;
2809 pr_info("%s:Attempt %d to request MBHC firmware\n",
2810 __func__, retry);
2811 ret = request_firmware(&fw, "wcd9320/wcd9320_mbhc.bin",
2812 codec->dev);
2813
2814 if (ret != 0) {
2815 usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT);
2816 } else {
2817 pr_info("%s: MBHC Firmware read succesful\n", __func__);
2818 break;
2819 }
2820 }
2821
2822 if (ret != 0) {
2823 pr_err("%s: Cannot load MBHC firmware use default cal\n",
2824 __func__);
2825 } else if (wcd9xxx_mbhc_fw_validate(fw) == false) {
2826 pr_err("%s: Invalid MBHC cal data size use default cal\n",
2827 __func__);
2828 release_firmware(fw);
2829 } else {
2830 mbhc->mbhc_cfg->calibration = (void *)fw->data;
2831 mbhc->mbhc_fw = fw;
2832 }
2833
2834 (void) wcd9xxx_init_and_calibrate(mbhc);
2835}
2836
2837#ifdef CONFIG_DEBUG_FS
2838ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,
2839 size_t count, loff_t *pos)
2840{
2841 const int size = 768;
2842 char buffer[size];
2843 int n = 0;
2844 struct wcd9xxx_mbhc *mbhc = file->private_data;
2845 const struct mbhc_internal_cal_data *p = &mbhc->mbhc_data;
2846 const s16 v_ins_hu_cur = wcd9xxx_get_current_v_ins(mbhc, true);
2847 const s16 v_ins_h_cur = wcd9xxx_get_current_v_ins(mbhc, false);
2848
2849 n = scnprintf(buffer, size - n, "dce_z = %x(%dmv)\n", p->dce_z,
2850 wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_z));
2851 n += scnprintf(buffer + n, size - n, "dce_mb = %x(%dmv)\n",
2852 p->dce_mb, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->dce_mb));
2853 n += scnprintf(buffer + n, size - n, "sta_z = %x(%dmv)\n",
2854 p->sta_z, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_z));
2855 n += scnprintf(buffer + n, size - n, "sta_mb = %x(%dmv)\n",
2856 p->sta_mb, wcd9xxx_codec_sta_dce_v(mbhc, 0, p->sta_mb));
2857 n += scnprintf(buffer + n, size - n, "t_dce = %x\n", p->t_dce);
2858 n += scnprintf(buffer + n, size - n, "t_sta = %x\n", p->t_sta);
2859 n += scnprintf(buffer + n, size - n, "micb_mv = %dmv\n",
2860 p->micb_mv);
2861 n += scnprintf(buffer + n, size - n, "v_ins_hu = %x(%dmv)%s\n",
2862 p->v_ins_hu,
2863 wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_ins_hu),
2864 p->v_ins_hu == v_ins_hu_cur ? "*" : "");
2865 n += scnprintf(buffer + n, size - n, "v_ins_h = %x(%dmv)%s\n",
2866 p->v_ins_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_ins_h),
2867 p->v_ins_h == v_ins_h_cur ? "*" : "");
2868 n += scnprintf(buffer + n, size - n, "adj_v_ins_hu = %x(%dmv)%s\n",
2869 p->adj_v_ins_hu,
2870 wcd9xxx_codec_sta_dce_v(mbhc, 0, p->adj_v_ins_hu),
2871 p->adj_v_ins_hu == v_ins_hu_cur ? "*" : "");
2872 n += scnprintf(buffer + n, size - n, "adj_v_ins_h = %x(%dmv)%s\n",
2873 p->adj_v_ins_h,
2874 wcd9xxx_codec_sta_dce_v(mbhc, 1, p->adj_v_ins_h),
2875 p->adj_v_ins_h == v_ins_h_cur ? "*" : "");
2876 n += scnprintf(buffer + n, size - n, "v_b1_hu = %x(%dmv)\n",
2877 p->v_b1_hu,
2878 wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_b1_hu));
2879 n += scnprintf(buffer + n, size - n, "v_b1_h = %x(%dmv)\n",
2880 p->v_b1_h, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_b1_h));
2881 n += scnprintf(buffer + n, size - n, "v_b1_huc = %x(%dmv)\n",
2882 p->v_b1_huc,
2883 wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_b1_huc));
2884 n += scnprintf(buffer + n, size - n, "v_brh = %x(%dmv)\n",
2885 p->v_brh, wcd9xxx_codec_sta_dce_v(mbhc, 1, p->v_brh));
2886 n += scnprintf(buffer + n, size - n, "v_brl = %x(%dmv)\n", p->v_brl,
2887 wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_brl));
2888 n += scnprintf(buffer + n, size - n, "v_no_mic = %x(%dmv)\n",
2889 p->v_no_mic,
2890 wcd9xxx_codec_sta_dce_v(mbhc, 0, p->v_no_mic));
2891 n += scnprintf(buffer + n, size - n, "v_inval_ins_low = %d\n",
2892 p->v_inval_ins_low);
2893 n += scnprintf(buffer + n, size - n, "v_inval_ins_high = %d\n",
2894 p->v_inval_ins_high);
2895 n += scnprintf(buffer + n, size - n, "Insert detect insert = %d\n",
2896 !wcd9xxx_swch_level_remove(mbhc));
2897 buffer[n] = 0;
2898
2899 return simple_read_from_buffer(buf, count, pos, buffer, n);
2900}
2901
2902static int codec_debug_open(struct inode *inode, struct file *file)
2903{
2904 file->private_data = inode->i_private;
2905 return 0;
2906}
2907
2908static ssize_t codec_debug_write(struct file *filp,
2909 const char __user *ubuf, size_t cnt,
2910 loff_t *ppos)
2911{
2912 char lbuf[32];
2913 char *buf;
2914 int rc;
2915 struct wcd9xxx_mbhc *mbhc = filp->private_data;
2916
2917 if (cnt > sizeof(lbuf) - 1)
2918 return -EINVAL;
2919
2920 rc = copy_from_user(lbuf, ubuf, cnt);
2921 if (rc)
2922 return -EFAULT;
2923
2924 lbuf[cnt] = '\0';
2925 buf = (char *)lbuf;
2926 mbhc->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
2927 false : true;
2928 return rc;
2929}
2930
2931static const struct file_operations mbhc_trrs_debug_ops = {
2932 .open = codec_debug_open,
2933 .write = codec_debug_write,
2934};
2935
2936static const struct file_operations mbhc_debug_ops = {
2937 .open = codec_debug_open,
2938 .read = codec_mbhc_debug_read,
2939};
2940
2941static void wcd9xxx_init_debugfs(struct wcd9xxx_mbhc *mbhc)
2942{
2943 mbhc->debugfs_poke =
2944 debugfs_create_file("TRRS", S_IFREG | S_IRUGO, NULL, mbhc,
2945 &mbhc_trrs_debug_ops);
2946 mbhc->debugfs_mbhc =
2947 debugfs_create_file("wcd9xxx_mbhc", S_IFREG | S_IRUGO,
2948 NULL, mbhc, &mbhc_debug_ops);
2949}
2950
2951static void wcd9xxx_cleanup_debugfs(struct wcd9xxx_mbhc *mbhc)
2952{
2953 debugfs_remove(mbhc->debugfs_poke);
2954 debugfs_remove(mbhc->debugfs_mbhc);
2955}
2956#else
2957static void wcd9xxx_init_debugfs(struct wcd9xxx_mbhc *mbhc)
2958{
2959}
2960
2961static void wcd9xxx_cleanup_debugfs(struct wcd9xxx_mbhc *mbhc)
2962{
2963}
2964#endif
2965
2966int wcd9xxx_mbhc_start(struct wcd9xxx_mbhc *mbhc,
2967 struct wcd9xxx_mbhc_config *mbhc_cfg)
2968{
2969 int rc = 0;
2970 struct snd_soc_codec *codec = mbhc->codec;
2971
2972 pr_debug("%s: enter\n", __func__);
2973
2974 if (!codec) {
2975 pr_err("%s: no codec\n", __func__);
2976 return -EINVAL;
2977 }
2978
2979 if (mbhc_cfg->mclk_rate != MCLK_RATE_12288KHZ &&
2980 mbhc_cfg->mclk_rate != MCLK_RATE_9600KHZ) {
2981 pr_err("Error: unsupported clock rate %d\n",
2982 mbhc_cfg->mclk_rate);
2983 return -EINVAL;
2984 }
2985
2986 /* Save mbhc config */
2987 mbhc->mbhc_cfg = mbhc_cfg;
2988
2989 /* Get HW specific mbhc registers' address */
2990 wcd9xxx_get_mbhc_micbias_regs(mbhc, &mbhc->mbhc_bias_regs);
2991
2992 /* Put CFILT in fast mode by default */
2993 snd_soc_update_bits(codec, mbhc->mbhc_bias_regs.cfilt_ctl,
2994 0x40, WCD9XXX_CFILT_FAST_MODE);
2995
2996 if (!mbhc->mbhc_cfg->read_fw_bin)
2997 rc = wcd9xxx_init_and_calibrate(mbhc);
2998 else
2999 schedule_delayed_work(&mbhc->mbhc_firmware_dwork,
3000 usecs_to_jiffies(FW_READ_TIMEOUT));
3001
3002 pr_debug("%s: leave %d\n", __func__, rc);
3003 return rc;
3004}
3005EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_start);
3006
3007static enum wcd9xxx_micbias_num
3008wcd9xxx_event_to_micbias(const enum wcd9xxx_notify_event event)
3009{
3010 enum wcd9xxx_micbias_num ret;
3011 switch (event) {
3012 case WCD9XXX_EVENT_PRE_MICBIAS_1_ON:
3013 ret = MBHC_MICBIAS1;
3014 case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
3015 ret = MBHC_MICBIAS2;
3016 case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
3017 ret = MBHC_MICBIAS3;
3018 case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
3019 ret = MBHC_MICBIAS4;
3020 default:
3021 ret = MBHC_MICBIAS_INVALID;
3022 }
3023 return ret;
3024}
3025
3026static int wcd9xxx_event_to_cfilt(const enum wcd9xxx_notify_event event)
3027{
3028 int ret;
3029 switch (event) {
3030 case WCD9XXX_EVENT_PRE_CFILT_1_OFF:
3031 case WCD9XXX_EVENT_POST_CFILT_1_OFF:
3032 case WCD9XXX_EVENT_PRE_CFILT_1_ON:
3033 case WCD9XXX_EVENT_POST_CFILT_1_ON:
3034 ret = WCD9XXX_CFILT1_SEL;
3035 break;
3036 case WCD9XXX_EVENT_PRE_CFILT_2_OFF:
3037 case WCD9XXX_EVENT_POST_CFILT_2_OFF:
3038 case WCD9XXX_EVENT_PRE_CFILT_2_ON:
3039 case WCD9XXX_EVENT_POST_CFILT_2_ON:
3040 ret = WCD9XXX_CFILT2_SEL;
3041 break;
3042 case WCD9XXX_EVENT_PRE_CFILT_3_OFF:
3043 case WCD9XXX_EVENT_POST_CFILT_3_OFF:
3044 case WCD9XXX_EVENT_PRE_CFILT_3_ON:
3045 case WCD9XXX_EVENT_POST_CFILT_3_ON:
3046 ret = WCD9XXX_CFILT3_SEL;
3047 break;
3048 default:
3049 ret = -1;
3050 }
3051 return ret;
3052}
3053
3054static int wcd9xxx_get_mbhc_cfilt_sel(struct wcd9xxx_mbhc *mbhc)
3055{
3056 int cfilt;
3057 const struct wcd9xxx_pdata *pdata = mbhc->resmgr->pdata;
3058
3059 switch (mbhc->mbhc_cfg->micbias) {
3060 case MBHC_MICBIAS1:
3061 cfilt = pdata->micbias.bias1_cfilt_sel;
3062 break;
3063 case MBHC_MICBIAS2:
3064 cfilt = pdata->micbias.bias2_cfilt_sel;
3065 break;
3066 case MBHC_MICBIAS3:
3067 cfilt = pdata->micbias.bias3_cfilt_sel;
3068 break;
3069 case MBHC_MICBIAS4:
3070 cfilt = pdata->micbias.bias4_cfilt_sel;
3071 break;
3072 default:
3073 cfilt = MBHC_MICBIAS_INVALID;
3074 break;
3075 }
3076 return cfilt;
3077}
3078
3079static int wcd9xxx_event_notify(struct notifier_block *self, unsigned long val,
3080 void *data)
3081{
3082 int ret = 0;
3083 struct wcd9xxx_mbhc *mbhc = ((struct wcd9xxx_resmgr *)data)->mbhc;
3084 struct snd_soc_codec *codec = mbhc->codec;
3085 enum wcd9xxx_notify_event event = (enum wcd9xxx_notify_event)val;
3086
3087 pr_debug("%s: enter event %s(%d)\n", __func__,
3088 wcd9xxx_get_event_string(event), event);
3089
3090 switch (event) {
3091 /* MICBIAS usage change */
3092 case WCD9XXX_EVENT_PRE_MICBIAS_1_ON:
3093 case WCD9XXX_EVENT_PRE_MICBIAS_2_ON:
3094 case WCD9XXX_EVENT_PRE_MICBIAS_3_ON:
3095 case WCD9XXX_EVENT_PRE_MICBIAS_4_ON:
3096 if (mbhc->mbhc_cfg->micbias == wcd9xxx_event_to_micbias(event))
3097 wcd9xxx_switch_micbias(mbhc, 0);
3098 break;
3099 case WCD9XXX_EVENT_POST_MICBIAS_1_ON:
3100 case WCD9XXX_EVENT_POST_MICBIAS_2_ON:
3101 case WCD9XXX_EVENT_POST_MICBIAS_3_ON:
3102 case WCD9XXX_EVENT_POST_MICBIAS_4_ON:
3103 if (mbhc->mbhc_cfg->micbias ==
3104 wcd9xxx_event_to_micbias(event) &&
3105 wcd9xxx_mbhc_polling(mbhc)) {
3106 /* if polling is on, restart it */
3107 wcd9xxx_pause_hs_polling(mbhc);
3108 wcd9xxx_start_hs_polling(mbhc);
3109 }
3110 break;
3111 case WCD9XXX_EVENT_POST_MICBIAS_1_OFF:
3112 case WCD9XXX_EVENT_POST_MICBIAS_2_OFF:
3113 case WCD9XXX_EVENT_POST_MICBIAS_3_OFF:
3114 case WCD9XXX_EVENT_POST_MICBIAS_4_OFF:
3115 if (mbhc->mbhc_cfg->micbias ==
3116 wcd9xxx_event_to_micbias(event) &&
3117 wcd9xxx_is_hph_pa_on(codec))
3118 wcd9xxx_switch_micbias(mbhc, 1);
3119 break;
3120 /* PA usage change */
3121 case WCD9XXX_EVENT_PRE_HPHL_PA_ON:
Joonwoo Parkd87ec4c2012-10-30 15:44:18 -07003122 if (!(snd_soc_read(codec, mbhc->mbhc_bias_regs.ctl_reg) & 0x80))
Joonwoo Parka8890262012-10-15 12:04:27 -07003123 /* if micbias is enabled, switch to vddio */
3124 wcd9xxx_switch_micbias(mbhc, 1);
3125 break;
3126 case WCD9XXX_EVENT_PRE_HPHR_PA_ON:
3127 /* Not used now */
3128 break;
3129 case WCD9XXX_EVENT_POST_HPHL_PA_OFF:
3130 /* if HPH PAs are off, report OCP and switch back to CFILT */
3131 clear_bit(WCD9XXX_HPHL_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
3132 clear_bit(WCD9XXX_HPHL_DAC_OFF_ACK, &mbhc->hph_pa_dac_state);
3133 if (mbhc->hph_status & SND_JACK_OC_HPHL)
3134 hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
3135 wcd9xxx_switch_micbias(mbhc, 0);
3136 break;
3137 case WCD9XXX_EVENT_POST_HPHR_PA_OFF:
3138 /* if HPH PAs are off, report OCP and switch back to CFILT */
3139 clear_bit(WCD9XXX_HPHR_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
3140 clear_bit(WCD9XXX_HPHR_DAC_OFF_ACK, &mbhc->hph_pa_dac_state);
3141 if (mbhc->hph_status & SND_JACK_OC_HPHR)
3142 hphrocp_off_report(mbhc, SND_JACK_OC_HPHL);
3143 wcd9xxx_switch_micbias(mbhc, 0);
3144 break;
3145 /* Clock usage change */
3146 case WCD9XXX_EVENT_PRE_MCLK_ON:
3147 break;
3148 case WCD9XXX_EVENT_POST_MCLK_ON:
3149 /* Change to lower TxAAF frequency */
3150 snd_soc_update_bits(codec, WCD9XXX_A_TX_COM_BIAS, 1 << 4,
3151 1 << 4);
3152 /* Re-calibrate clock rate dependent values */
3153 wcd9xxx_update_mbhc_clk_rate(mbhc, mbhc->mbhc_cfg->mclk_rate);
3154 /* If clock source changes, stop and restart polling */
3155 if (wcd9xxx_mbhc_polling(mbhc)) {
3156 wcd9xxx_calibrate_hs_polling(mbhc);
3157 wcd9xxx_start_hs_polling(mbhc);
3158 }
3159 break;
3160 case WCD9XXX_EVENT_PRE_MCLK_OFF:
3161 /* If clock source changes, stop and restart polling */
3162 if (wcd9xxx_mbhc_polling(mbhc))
3163 wcd9xxx_pause_hs_polling(mbhc);
3164 break;
3165 case WCD9XXX_EVENT_POST_MCLK_OFF:
3166 break;
3167 case WCD9XXX_EVENT_PRE_RCO_ON:
3168 break;
3169 case WCD9XXX_EVENT_POST_RCO_ON:
3170 /* Change to higher TxAAF frequency */
3171 snd_soc_update_bits(codec, WCD9XXX_A_TX_COM_BIAS, 1 << 4,
3172 0 << 4);
3173 /* Re-calibrate clock rate dependent values */
3174 wcd9xxx_update_mbhc_clk_rate(mbhc, WCD9XXX_RCO_CLK_RATE);
3175 /* If clock source changes, stop and restart polling */
3176 if (wcd9xxx_mbhc_polling(mbhc)) {
3177 wcd9xxx_calibrate_hs_polling(mbhc);
3178 wcd9xxx_start_hs_polling(mbhc);
3179 }
3180 break;
3181 case WCD9XXX_EVENT_PRE_RCO_OFF:
3182 /* If clock source changes, stop and restart polling */
3183 if (wcd9xxx_mbhc_polling(mbhc))
3184 wcd9xxx_pause_hs_polling(mbhc);
3185 break;
3186 case WCD9XXX_EVENT_POST_RCO_OFF:
3187 break;
3188 /* CFILT usage change */
3189 case WCD9XXX_EVENT_PRE_CFILT_1_ON:
3190 case WCD9XXX_EVENT_PRE_CFILT_2_ON:
3191 case WCD9XXX_EVENT_PRE_CFILT_3_ON:
3192 if (wcd9xxx_get_mbhc_cfilt_sel(mbhc) ==
3193 wcd9xxx_event_to_cfilt(event))
3194 /*
3195 * Switch CFILT to slow mode if MBHC CFILT is being
3196 * used.
3197 */
3198 wcd9xxx_codec_switch_cfilt_mode(mbhc, false);
3199 break;
3200 case WCD9XXX_EVENT_POST_CFILT_1_OFF:
3201 case WCD9XXX_EVENT_POST_CFILT_2_OFF:
3202 case WCD9XXX_EVENT_POST_CFILT_3_OFF:
3203 if (wcd9xxx_get_mbhc_cfilt_sel(mbhc) ==
3204 wcd9xxx_event_to_cfilt(event))
3205 /*
3206 * Switch CFILT to fast mode if MBHC CFILT is not
3207 * used anymore.
3208 */
3209 wcd9xxx_codec_switch_cfilt_mode(mbhc, true);
3210 break;
3211 /* System resume */
3212 case WCD9XXX_EVENT_POST_RESUME:
3213 mbhc->mbhc_last_resume = jiffies;
3214 break;
3215 /* BG mode chage */
3216 case WCD9XXX_EVENT_PRE_BG_OFF:
3217 case WCD9XXX_EVENT_POST_BG_OFF:
3218 case WCD9XXX_EVENT_PRE_BG_AUDIO_ON:
3219 case WCD9XXX_EVENT_POST_BG_AUDIO_ON:
3220 case WCD9XXX_EVENT_PRE_BG_MBHC_ON:
3221 case WCD9XXX_EVENT_POST_BG_MBHC_ON:
3222 /* Not used for now */
3223 break;
3224 default:
3225 WARN(1, "Unknown event %d\n", event);
3226 ret = -EINVAL;
3227 }
3228
3229 pr_debug("%s: leave\n", __func__);
3230
3231 return 0;
3232}
3233
3234/*
3235 * wcd9xxx_mbhc_init : initialize MBHC internal structures.
3236 *
3237 * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
3238 */
3239int wcd9xxx_mbhc_init(struct wcd9xxx_mbhc *mbhc, struct wcd9xxx_resmgr *resmgr,
3240 struct snd_soc_codec *codec)
3241{
3242 int ret;
3243 void *core;
3244
3245 pr_debug("%s: enter\n", __func__);
3246 memset(&mbhc->mbhc_bias_regs, 0, sizeof(struct mbhc_micbias_regs));
3247 memset(&mbhc->mbhc_data, 0, sizeof(struct mbhc_internal_cal_data));
3248
3249 mbhc->mbhc_data.t_sta_dce = DEFAULT_DCE_STA_WAIT;
3250 mbhc->mbhc_data.t_dce = DEFAULT_DCE_WAIT;
3251 mbhc->mbhc_data.t_sta = DEFAULT_STA_WAIT;
3252 mbhc->mbhc_micbias_switched = false;
3253 mbhc->polling_active = false;
3254 mbhc->mbhc_state = MBHC_STATE_NONE;
3255 mbhc->in_swch_irq_handler = false;
3256 mbhc->current_plug = PLUG_TYPE_NONE;
3257 mbhc->lpi_enabled = false;
3258 mbhc->no_mic_headset_override = false;
3259 mbhc->mbhc_last_resume = 0;
3260 mbhc->codec = codec;
3261 mbhc->resmgr = resmgr;
3262 mbhc->resmgr->mbhc = mbhc;
3263
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08003264 if (mbhc->headset_jack.jack == NULL) {
3265 ret = snd_soc_jack_new(codec, "Headset Jack", WCD9XXX_JACK_MASK,
3266 &mbhc->headset_jack);
3267 if (ret) {
3268 pr_err("%s: Failed to create new jack\n", __func__);
3269 return ret;
3270 }
Joonwoo Parka8890262012-10-15 12:04:27 -07003271
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08003272 ret = snd_soc_jack_new(codec, "Button Jack",
3273 WCD9XXX_JACK_BUTTON_MASK,
3274 &mbhc->button_jack);
3275 if (ret) {
3276 pr_err("Failed to create new jack\n");
3277 return ret;
3278 }
Joonwoo Parka8890262012-10-15 12:04:27 -07003279
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08003280 INIT_DELAYED_WORK(&mbhc->mbhc_firmware_dwork,
3281 wcd9xxx_mbhc_fw_read);
3282 INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd9xxx_btn_lpress_fn);
3283 INIT_DELAYED_WORK(&mbhc->mbhc_insert_dwork,
3284 wcd9xxx_mbhc_insert_work);
3285 }
Joonwoo Parka8890262012-10-15 12:04:27 -07003286
3287 /* Register event notifier */
3288 mbhc->nblock.notifier_call = wcd9xxx_event_notify;
3289 ret = wcd9xxx_resmgr_register_notifier(mbhc->resmgr, &mbhc->nblock);
3290 if (ret) {
3291 pr_err("%s: Failed to register notifier %d\n", __func__, ret);
3292 return ret;
3293 }
3294
3295 wcd9xxx_init_debugfs(mbhc);
3296
3297 core = mbhc->resmgr->core;
3298 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_INSERTION,
3299 wcd9xxx_hs_insert_irq,
3300 "Headset insert detect", mbhc);
3301 if (ret) {
3302 pr_err("%s: Failed to request irq %d\n", __func__,
3303 WCD9XXX_IRQ_MBHC_INSERTION);
3304 goto err_insert_irq;
3305 }
3306 wcd9xxx_disable_irq(core, WCD9XXX_IRQ_MBHC_INSERTION);
3307
3308 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_REMOVAL,
3309 wcd9xxx_hs_remove_irq,
3310 "Headset remove detect", mbhc);
3311 if (ret) {
3312 pr_err("%s: Failed to request irq %d\n", __func__,
3313 WCD9XXX_IRQ_MBHC_REMOVAL);
3314 goto err_remove_irq;
3315 }
3316
3317 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_POTENTIAL,
3318 wcd9xxx_dce_handler, "DC Estimation detect",
3319 mbhc);
3320 if (ret) {
3321 pr_err("%s: Failed to request irq %d\n", __func__,
3322 WCD9XXX_IRQ_MBHC_POTENTIAL);
3323 goto err_potential_irq;
3324 }
3325
3326 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_MBHC_RELEASE,
3327 wcd9xxx_release_handler,
3328 "Button Release detect", mbhc);
3329 if (ret) {
3330 pr_err("%s: Failed to request irq %d\n", __func__,
3331 WCD9XXX_IRQ_MBHC_RELEASE);
3332 goto err_release_irq;
3333 }
3334
3335 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT,
3336 wcd9xxx_hphl_ocp_irq, "HPH_L OCP detect",
3337 mbhc);
3338 if (ret) {
3339 pr_err("%s: Failed to request irq %d\n", __func__,
3340 WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
3341 goto err_hphl_ocp_irq;
3342 }
3343 wcd9xxx_disable_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT);
3344
3345 ret = wcd9xxx_request_irq(core, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT,
3346 wcd9xxx_hphr_ocp_irq, "HPH_R OCP detect",
3347 mbhc);
3348 if (ret) {
3349 pr_err("%s: Failed to request irq %d\n", __func__,
3350 WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
3351 goto err_hphr_ocp_irq;
3352 }
3353 wcd9xxx_disable_irq(codec->control_data, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT);
3354
3355 pr_debug("%s: leave ret %d\n", __func__, ret);
3356 return ret;
3357
3358err_hphr_ocp_irq:
3359 wcd9xxx_free_irq(core, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
3360err_hphl_ocp_irq:
3361 wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
3362err_release_irq:
3363 wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
3364err_potential_irq:
3365 wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
3366err_remove_irq:
3367 wcd9xxx_free_irq(core, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
3368err_insert_irq:
3369 wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
3370
3371 pr_debug("%s: leave ret %d\n", __func__, ret);
3372 return ret;
3373}
3374EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_init);
3375
3376void wcd9xxx_mbhc_deinit(struct wcd9xxx_mbhc *mbhc)
3377{
3378 void *cdata = mbhc->codec->control_data;
3379
3380 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_SLIMBUS, mbhc);
3381 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
3382 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_POTENTIAL, mbhc);
3383 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_REMOVAL, mbhc);
3384 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_INSERTION, mbhc);
3385
Ravishankar Sarawadi2293efe2013-01-11 16:37:23 -08003386 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_JACK_SWITCH, mbhc);
3387 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPL_FAULT, mbhc);
3388 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_HPH_PA_OCPR_FAULT, mbhc);
3389 wcd9xxx_free_irq(cdata, WCD9XXX_IRQ_MBHC_RELEASE, mbhc);
3390
Joonwoo Parka8890262012-10-15 12:04:27 -07003391 if (mbhc->mbhc_fw)
3392 release_firmware(mbhc->mbhc_fw);
3393
3394 wcd9xxx_resmgr_unregister_notifier(mbhc->resmgr, &mbhc->nblock);
3395
3396 wcd9xxx_cleanup_debugfs(mbhc);
Joonwoo Parka8890262012-10-15 12:04:27 -07003397}
3398EXPORT_SYMBOL_GPL(wcd9xxx_mbhc_deinit);
3399
3400MODULE_DESCRIPTION("wcd9xxx MBHC module");
3401MODULE_LICENSE("GPL v2");