blob: ce40f22d72c7c5582ddec952168a48b975730677 [file] [log] [blame]
Vatsal Bucha79a80992018-05-10 14:20:18 +05301/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/slab.h>
15#include <linux/of_gpio.h>
16#include <linux/platform_device.h>
17#include <linux/device.h>
18#include <linux/printk.h>
19#include <linux/ratelimit.h>
20#include <linux/list.h>
21#include <linux/bitops.h>
22#include <linux/delay.h>
23#include <linux/pm_runtime.h>
24#include <linux/kernel.h>
25#include <linux/input.h>
26#include <linux/firmware.h>
27#include <linux/completion.h>
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053028#include <sound/soc.h>
29#include <sound/jack.h>
Laxminath Kasam605b42f2017-08-01 22:02:15 +053030#include "msm-cdc-pinctrl.h"
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +053031#include "wcdcal-hwdep.h"
32#include "wcd-mbhc-legacy.h"
33#include "wcd-mbhc-adc.h"
34#include "wcd-mbhc-v2-api.h"
35
36void wcd_mbhc_jack_report(struct wcd_mbhc *mbhc,
37 struct snd_soc_jack *jack, int status, int mask)
38{
39 snd_soc_jack_report(jack, status, mask);
40}
41EXPORT_SYMBOL(wcd_mbhc_jack_report);
42
43static void __hphocp_off_report(struct wcd_mbhc *mbhc, u32 jack_status,
44 int irq)
45{
46 struct snd_soc_codec *codec = mbhc->codec;
47
48 dev_dbg(codec->dev, "%s: clear ocp status %x\n",
49 __func__, jack_status);
50
51 if (mbhc->hph_status & jack_status) {
52 mbhc->hph_status &= ~jack_status;
53 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
54 mbhc->hph_status, WCD_MBHC_JACK_MASK);
55 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 0);
56 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 1);
57 /*
58 * reset retry counter as PA is turned off signifying
59 * start of new OCP detection session
60 */
61 if (mbhc->intr_ids->hph_left_ocp)
62 mbhc->hphlocp_cnt = 0;
63 else
64 mbhc->hphrocp_cnt = 0;
65 mbhc->mbhc_cb->irq_control(codec, irq, true);
66 }
67}
68
69static void hphrocp_off_report(struct wcd_mbhc *mbhc, u32 jack_status)
70{
71 __hphocp_off_report(mbhc, SND_JACK_OC_HPHR,
72 mbhc->intr_ids->hph_right_ocp);
73}
74
75static void hphlocp_off_report(struct wcd_mbhc *mbhc, u32 jack_status)
76{
77 __hphocp_off_report(mbhc, SND_JACK_OC_HPHL,
78 mbhc->intr_ids->hph_left_ocp);
79}
80
81static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
82{
83 struct wcd_mbhc_plug_type_cfg *plug_type_cfg;
84 struct snd_soc_codec *codec = mbhc->codec;
85 u32 reg_val;
86
87 plug_type_cfg = WCD_MBHC_CAL_PLUG_TYPE_PTR(mbhc->mbhc_cfg->calibration);
88 reg_val = ((plug_type_cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
89
90 dev_dbg(codec->dev, "%s: reg_val = %x\n", __func__, reg_val);
91 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_VREF, reg_val);
92}
93
94static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
95{
96 struct wcd_mbhc_btn_detect_cfg *btn_det;
97 struct snd_soc_codec *codec = mbhc->codec;
98 struct snd_soc_card *card = codec->component.card;
99 s16 *btn_low, *btn_high;
100
101 if (mbhc->mbhc_cfg->calibration == NULL) {
102 dev_err(card->dev, "%s: calibration data is NULL\n", __func__);
103 return;
104 }
105
106 btn_det = WCD_MBHC_CAL_BTN_DET_PTR(mbhc->mbhc_cfg->calibration);
107 btn_low = btn_det->_v_btn_low;
108 btn_high = ((void *)&btn_det->_v_btn_low) +
109 (sizeof(btn_det->_v_btn_low[0]) * btn_det->num_btn);
110
111 mbhc->mbhc_cb->set_btn_thr(codec, btn_low, btn_high, btn_det->num_btn,
112 micbias);
113}
114
115void wcd_enable_curr_micbias(const struct wcd_mbhc *mbhc,
116 const enum wcd_mbhc_cs_mb_en_flag cs_mb_en)
117{
118
119 /*
120 * Some codecs handle micbias/pullup enablement in codec
121 * drivers itself and micbias is not needed for regular
122 * plug type detection. So if micbias_control callback function
123 * is defined, just return.
124 */
125 if (mbhc->mbhc_cb->mbhc_micbias_control)
126 return;
127
128 pr_debug("%s: enter, cs_mb_en: %d\n", __func__, cs_mb_en);
129
130 switch (cs_mb_en) {
131 case WCD_MBHC_EN_CS:
132 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0);
133 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3);
134 /* Program Button threshold registers as per CS */
135 wcd_program_btn_threshold(mbhc, false);
136 break;
137 case WCD_MBHC_EN_MB:
138 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
139 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
140
141 /* Disable PULL_UP_EN & enable MICBIAS */
142 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 2);
143 /* Program Button threshold registers as per MICBIAS */
144 wcd_program_btn_threshold(mbhc, true);
145 break;
146 case WCD_MBHC_EN_PULLUP:
147 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 3);
148 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
149 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 1);
150 /* Program Button threshold registers as per MICBIAS */
151 wcd_program_btn_threshold(mbhc, true);
152 break;
153 case WCD_MBHC_EN_NONE:
154 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
155 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
156 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0);
157 break;
158 default:
159 pr_debug("%s: Invalid parameter", __func__);
160 break;
161 }
162
163 pr_debug("%s: exit\n", __func__);
164}
165EXPORT_SYMBOL(wcd_enable_curr_micbias);
166
167static const char *wcd_mbhc_get_event_string(int event)
168{
169 switch (event) {
170 case WCD_EVENT_PRE_MICBIAS_2_OFF:
171 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_MICBIAS_2_OFF);
172 case WCD_EVENT_POST_MICBIAS_2_OFF:
173 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_MICBIAS_2_OFF);
174 case WCD_EVENT_PRE_MICBIAS_2_ON:
175 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_MICBIAS_2_ON);
176 case WCD_EVENT_POST_MICBIAS_2_ON:
177 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_MICBIAS_2_ON);
178 case WCD_EVENT_PRE_HPHL_PA_ON:
179 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_HPHL_PA_ON);
180 case WCD_EVENT_POST_HPHL_PA_OFF:
181 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_HPHL_PA_OFF);
182 case WCD_EVENT_PRE_HPHR_PA_ON:
183 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_HPHR_PA_ON);
184 case WCD_EVENT_POST_HPHR_PA_OFF:
185 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_HPHR_PA_OFF);
186 case WCD_EVENT_PRE_HPHR_PA_OFF:
187 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_HPHR_PA_OFF);
188 case WCD_EVENT_PRE_HPHL_PA_OFF:
189 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_HPHL_PA_OFF);
190 case WCD_EVENT_POST_DAPM_MICBIAS_2_ON:
191 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_DAPM_MICBIAS_2_ON);
192 case WCD_EVENT_PRE_DAPM_MICBIAS_2_ON:
193 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_DAPM_MICBIAS_2_ON);
194 case WCD_EVENT_POST_DAPM_MICBIAS_2_OFF:
195 return WCD_MBHC_STRINGIFY(WCD_EVENT_POST_DAPM_MICBIAS_2_OFF);
196 case WCD_EVENT_PRE_DAPM_MICBIAS_2_OFF:
197 return WCD_MBHC_STRINGIFY(WCD_EVENT_PRE_DAPM_MICBIAS_2_OFF);
198 case WCD_EVENT_OCP_OFF:
199 return WCD_MBHC_STRINGIFY(WCD_EVENT_OCP_OFF);
200 case WCD_EVENT_OCP_ON:
201 return WCD_MBHC_STRINGIFY(WCD_EVENT_OCP_ON);
202 case WCD_EVENT_INVALID:
203 default:
204 return WCD_MBHC_STRINGIFY(WCD_EVENT_INVALID);
205 }
206}
207
208static int wcd_event_notify(struct notifier_block *self, unsigned long val,
209 void *data)
210{
211 struct wcd_mbhc *mbhc = (struct wcd_mbhc *)data;
212 enum wcd_notify_event event = (enum wcd_notify_event)val;
213 struct snd_soc_codec *codec = mbhc->codec;
214 bool micbias2 = false;
215 bool micbias1 = false;
216 u8 fsm_en = 0;
217
218 pr_debug("%s: event %s (%d)\n", __func__,
219 wcd_mbhc_get_event_string(event), event);
220 if (mbhc->mbhc_cb->micbias_enable_status) {
221 micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
222 MIC_BIAS_2);
223 micbias1 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
224 MIC_BIAS_1);
225 }
226 switch (event) {
227 /* MICBIAS usage change */
228 case WCD_EVENT_POST_DAPM_MICBIAS_2_ON:
229 mbhc->is_hs_recording = true;
230 pr_debug("%s: is_capture: %d\n", __func__,
231 mbhc->is_hs_recording);
232 break;
233 case WCD_EVENT_POST_MICBIAS_2_ON:
234 if (!mbhc->micbias_enable)
235 goto out_micb_en;
236 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl) {
237 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
238 MBHC_COMMON_MICB_PRECHARGE,
239 true);
240 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
241 MBHC_COMMON_MICB_SET_VAL,
242 true);
243 /*
244 * Special headset needs MICBIAS as 2.7V so wait for
245 * 50 msec for the MICBIAS to reach 2.7 volts.
246 */
247 msleep(50);
248 }
249 if (mbhc->mbhc_cb->set_auto_zeroing)
250 mbhc->mbhc_cb->set_auto_zeroing(codec, true);
251 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl)
252 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
253 MBHC_COMMON_MICB_PRECHARGE,
254 false);
255out_micb_en:
256 /* Disable current source if micbias enabled */
257 if (mbhc->mbhc_cb->mbhc_micbias_control) {
258 WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
259 if (fsm_en)
260 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL,
261 0);
262 } else {
263 mbhc->is_hs_recording = true;
264 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
265 }
266 /* configure cap settings properly when micbias is enabled */
267 if (mbhc->mbhc_cb->set_cap_mode)
268 mbhc->mbhc_cb->set_cap_mode(codec, micbias1, true);
269 break;
270 case WCD_EVENT_PRE_MICBIAS_2_OFF:
271 /*
272 * Before MICBIAS_2 is turned off, if FSM is enabled,
273 * make sure current source is enabled so as to detect
274 * button press/release events
275 */
276 if (mbhc->mbhc_cb->mbhc_micbias_control &&
277 !mbhc->micbias_enable) {
278 WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
279 if (fsm_en)
280 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL,
281 3);
282 }
283 break;
284 /* MICBIAS usage change */
285 case WCD_EVENT_POST_DAPM_MICBIAS_2_OFF:
286 mbhc->is_hs_recording = false;
287 pr_debug("%s: is_capture: %d\n", __func__,
288 mbhc->is_hs_recording);
289 break;
290 case WCD_EVENT_POST_MICBIAS_2_OFF:
291 if (!mbhc->mbhc_cb->mbhc_micbias_control)
292 mbhc->is_hs_recording = false;
293 if (mbhc->micbias_enable) {
294 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
295 break;
296 }
297
298 if (mbhc->mbhc_cb->set_auto_zeroing)
299 mbhc->mbhc_cb->set_auto_zeroing(codec, false);
300 if (mbhc->mbhc_cb->set_micbias_value && !mbhc->micbias_enable)
301 mbhc->mbhc_cb->set_micbias_value(codec);
302 /* Enable PULL UP if PA's are enabled */
303 if ((test_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state)) ||
304 (test_bit(WCD_MBHC_EVENT_PA_HPHR,
305 &mbhc->event_state)))
306 /* enable pullup and cs, disable mb */
307 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_PULLUP);
308 else
309 /* enable current source and disable mb, pullup*/
310 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS);
311
312 /* configure cap settings properly when micbias is disabled */
313 if (mbhc->mbhc_cb->set_cap_mode)
314 mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false);
315 break;
316 case WCD_EVENT_PRE_HPHL_PA_OFF:
317 mutex_lock(&mbhc->hphl_pa_lock);
318 break;
319 case WCD_EVENT_POST_HPHL_PA_OFF:
320 clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
321 if (mbhc->hph_status & SND_JACK_OC_HPHL)
322 hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
323 clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
324 /* check if micbias is enabled */
325 if (micbias2)
326 /* Disable cs, pullup & enable micbias */
327 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
328 else
329 /* Disable micbias, pullup & enable cs */
330 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS);
331 mutex_unlock(&mbhc->hphl_pa_lock);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530332 clear_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530333 break;
334 case WCD_EVENT_PRE_HPHR_PA_OFF:
335 mutex_lock(&mbhc->hphr_pa_lock);
336 break;
337 case WCD_EVENT_POST_HPHR_PA_OFF:
338 clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
339 if (mbhc->hph_status & SND_JACK_OC_HPHR)
340 hphrocp_off_report(mbhc, SND_JACK_OC_HPHR);
341 clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
342 /* check if micbias is enabled */
343 if (micbias2)
344 /* Disable cs, pullup & enable micbias */
345 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
346 else
347 /* Disable micbias, pullup & enable cs */
348 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_CS);
349 mutex_unlock(&mbhc->hphr_pa_lock);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530350 clear_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530351 break;
352 case WCD_EVENT_PRE_HPHL_PA_ON:
353 set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
354 /* check if micbias is enabled */
355 if (micbias2)
356 /* Disable cs, pullup & enable micbias */
357 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
358 else
359 /* Disable micbias, enable pullup & cs */
360 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_PULLUP);
361 break;
362 case WCD_EVENT_PRE_HPHR_PA_ON:
363 set_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
364 /* check if micbias is enabled */
365 if (micbias2)
366 /* Disable cs, pullup & enable micbias */
367 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
368 else
369 /* Disable micbias, enable pullup & cs */
370 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_PULLUP);
371 break;
372 case WCD_EVENT_OCP_OFF:
373 mbhc->mbhc_cb->irq_control(mbhc->codec,
374 mbhc->intr_ids->hph_left_ocp,
375 false);
376 break;
377 case WCD_EVENT_OCP_ON:
378 mbhc->mbhc_cb->irq_control(mbhc->codec,
379 mbhc->intr_ids->hph_left_ocp,
380 true);
381 break;
382 default:
383 break;
384 }
385 return 0;
386}
387
388int wcd_cancel_btn_work(struct wcd_mbhc *mbhc)
389{
390 int r;
391
392 r = cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork);
393 /*
394 * if scheduled mbhc.mbhc_btn_dwork is canceled from here,
395 * we have to unlock from here instead btn_work
396 */
397 if (r)
398 mbhc->mbhc_cb->lock_sleep(mbhc, false);
399 return r;
400}
401EXPORT_SYMBOL(wcd_cancel_btn_work);
402
403bool wcd_swch_level_remove(struct wcd_mbhc *mbhc)
404{
405 u16 result2 = 0;
406
407 WCD_MBHC_REG_READ(WCD_MBHC_SWCH_LEVEL_REMOVE, result2);
408 return (result2) ? true : false;
409}
410EXPORT_SYMBOL(wcd_swch_level_remove);
411
412static void wcd_mbhc_clr_and_turnon_hph_padac(struct wcd_mbhc *mbhc)
413{
414 bool pa_turned_on = false;
415 u8 wg_time = 0;
416
417 WCD_MBHC_REG_READ(WCD_MBHC_HPH_CNP_WG_TIME, wg_time);
418 wg_time += 1;
419
420 mutex_lock(&mbhc->hphr_pa_lock);
421 if (test_and_clear_bit(WCD_MBHC_HPHR_PA_OFF_ACK,
422 &mbhc->hph_pa_dac_state)) {
423 pr_debug("%s: HPHR clear flag and enable PA\n", __func__);
424 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_PA_EN, 1);
425 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_OCP_DET_EN, 1);
426 pa_turned_on = true;
427 }
428 mutex_unlock(&mbhc->hphr_pa_lock);
429 mutex_lock(&mbhc->hphl_pa_lock);
430 if (test_and_clear_bit(WCD_MBHC_HPHL_PA_OFF_ACK,
431 &mbhc->hph_pa_dac_state)) {
432 pr_debug("%s: HPHL clear flag and enable PA\n", __func__);
433 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PA_EN, 1);
434 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_OCP_DET_EN, 1);
435 pa_turned_on = true;
436 }
437 mutex_unlock(&mbhc->hphl_pa_lock);
438
439 if (pa_turned_on) {
440 pr_debug("%s: PA was turned on by MBHC and not by DAPM\n",
441 __func__);
442 usleep_range(wg_time * 1000, wg_time * 1000 + 50);
443 }
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530444
445 if (test_and_clear_bit(WCD_MBHC_ANC0_OFF_ACK,
446 &mbhc->hph_anc_state)) {
447 usleep_range(20000, 20100);
448 pr_debug("%s: HPHL ANC clear flag and enable ANC_EN\n",
449 __func__);
450 if (mbhc->mbhc_cb->update_anc_state)
451 mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 0);
452 }
453
454 if (test_and_clear_bit(WCD_MBHC_ANC1_OFF_ACK,
455 &mbhc->hph_anc_state)) {
456 usleep_range(20000, 20100);
457 pr_debug("%s: HPHR ANC clear flag and enable ANC_EN\n",
458 __func__);
459 if (mbhc->mbhc_cb->update_anc_state)
460 mbhc->mbhc_cb->update_anc_state(mbhc->codec, true, 1);
461 }
462
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530463}
464
465static bool wcd_mbhc_is_hph_pa_on(struct wcd_mbhc *mbhc)
466{
467 bool hph_pa_on = false;
468
469 WCD_MBHC_REG_READ(WCD_MBHC_HPH_PA_EN, hph_pa_on);
470
471 return (hph_pa_on) ? true : false;
472}
473
474static void wcd_mbhc_set_and_turnoff_hph_padac(struct wcd_mbhc *mbhc)
475{
476 u8 wg_time = 0;
477
478 WCD_MBHC_REG_READ(WCD_MBHC_HPH_CNP_WG_TIME, wg_time);
479 wg_time += 1;
480
481 /* If headphone PA is on, check if userspace receives
482 * removal event to sync-up PA's state
483 */
484 if (wcd_mbhc_is_hph_pa_on(mbhc)) {
485 pr_debug("%s PA is on, setting PA_OFF_ACK\n", __func__);
486 set_bit(WCD_MBHC_HPHL_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
487 set_bit(WCD_MBHC_HPHR_PA_OFF_ACK, &mbhc->hph_pa_dac_state);
488 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_OCP_DET_EN, 0);
489 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHR_OCP_DET_EN, 0);
490 } else {
491 pr_debug("%s PA is off\n", __func__);
492 }
493 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPH_PA_EN, 0);
494 usleep_range(wg_time * 1000, wg_time * 1000 + 50);
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530495
496
497 if (mbhc->mbhc_cb->is_anc_on && mbhc->mbhc_cb->is_anc_on(mbhc)) {
498 usleep_range(20000, 20100);
499 pr_debug("%s ANC is on, setting ANC_OFF_ACK\n", __func__);
500 set_bit(WCD_MBHC_ANC0_OFF_ACK, &mbhc->hph_anc_state);
501 set_bit(WCD_MBHC_ANC1_OFF_ACK, &mbhc->hph_anc_state);
502 if (mbhc->mbhc_cb->update_anc_state) {
503 mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 0);
504 mbhc->mbhc_cb->update_anc_state(mbhc->codec, false, 1);
505 } else {
506 pr_debug("%s ANC is off\n", __func__);
507 }
508 }
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530509}
510
511int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl,
512 uint32_t *zr)
513{
514 *zl = mbhc->zl;
515 *zr = mbhc->zr;
516
517 if (*zl && *zr)
518 return 0;
519 else
520 return -EINVAL;
521}
522EXPORT_SYMBOL(wcd_mbhc_get_impedance);
523
524void wcd_mbhc_hs_elec_irq(struct wcd_mbhc *mbhc, int irq_type,
525 bool enable)
526{
527 int irq;
528
529 WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
530
531 if (irq_type == WCD_MBHC_ELEC_HS_INS)
532 irq = mbhc->intr_ids->mbhc_hs_ins_intr;
533 else if (irq_type == WCD_MBHC_ELEC_HS_REM)
534 irq = mbhc->intr_ids->mbhc_hs_rem_intr;
535 else {
536 pr_debug("%s: irq_type: %d, enable: %d\n",
537 __func__, irq_type, enable);
538 return;
539 }
540
541 pr_debug("%s: irq: %d, enable: %d, intr_status:%lu\n",
542 __func__, irq, enable, mbhc->intr_status);
543 if ((test_bit(irq_type, &mbhc->intr_status)) != enable) {
544 mbhc->mbhc_cb->irq_control(mbhc->codec, irq, enable);
545 if (enable)
546 set_bit(irq_type, &mbhc->intr_status);
547 else
548 clear_bit(irq_type, &mbhc->intr_status);
549 }
550}
551EXPORT_SYMBOL(wcd_mbhc_hs_elec_irq);
552
Meng Wang6f901622017-09-19 10:21:57 +0800553void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530554 enum snd_jack_types jack_type)
555{
556 struct snd_soc_codec *codec = mbhc->codec;
557 bool is_pa_on = false;
558 u8 fsm_en = 0;
559
560 WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
561
562 pr_debug("%s: enter insertion %d hph_status %x\n",
563 __func__, insertion, mbhc->hph_status);
564 if (!insertion) {
565 /* Report removal */
566 mbhc->hph_status &= ~jack_type;
567 /*
568 * cancel possibly scheduled btn work and
569 * report release if we reported button press
570 */
571 if (wcd_cancel_btn_work(mbhc)) {
572 pr_debug("%s: button press is canceled\n", __func__);
573 } else if (mbhc->buttons_pressed) {
574 pr_debug("%s: release of button press%d\n",
575 __func__, jack_type);
576 wcd_mbhc_jack_report(mbhc, &mbhc->button_jack, 0,
577 mbhc->buttons_pressed);
578 mbhc->buttons_pressed &=
579 ~WCD_MBHC_JACK_BUTTON_MASK;
580 }
581
582 if (mbhc->micbias_enable) {
583 if (mbhc->mbhc_cb->mbhc_micbias_control)
584 mbhc->mbhc_cb->mbhc_micbias_control(
585 codec, MIC_BIAS_2,
586 MICB_DISABLE);
587 if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
588 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(
589 codec,
590 MIC_BIAS_2, false);
591 if (mbhc->mbhc_cb->set_micbias_value) {
592 mbhc->mbhc_cb->set_micbias_value(codec);
593 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MICB_CTRL, 0);
594 }
595 mbhc->micbias_enable = false;
596 }
597
598 mbhc->hph_type = WCD_MBHC_HPH_NONE;
599 mbhc->zl = mbhc->zr = 0;
600 pr_debug("%s: Reporting removal %d(%x)\n", __func__,
601 jack_type, mbhc->hph_status);
602 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
603 mbhc->hph_status, WCD_MBHC_JACK_MASK);
604 wcd_mbhc_set_and_turnoff_hph_padac(mbhc);
605 hphrocp_off_report(mbhc, SND_JACK_OC_HPHR);
606 hphlocp_off_report(mbhc, SND_JACK_OC_HPHL);
607 mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
Vatsal Buchad6d62b82017-12-12 14:22:31 +0530608 mbhc->force_linein = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530609 } else {
610 /*
611 * Report removal of current jack type.
612 * Headphone to headset shouldn't report headphone
613 * removal.
614 */
615 if (mbhc->mbhc_cfg->detect_extn_cable &&
616 (mbhc->current_plug == MBHC_PLUG_TYPE_HIGH_HPH ||
617 jack_type == SND_JACK_LINEOUT) &&
618 (mbhc->hph_status && mbhc->hph_status != jack_type)) {
619
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530620 if (mbhc->micbias_enable &&
621 mbhc->hph_status == SND_JACK_HEADSET) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530622 if (mbhc->mbhc_cb->mbhc_micbias_control)
623 mbhc->mbhc_cb->mbhc_micbias_control(
624 codec, MIC_BIAS_2,
625 MICB_DISABLE);
626 if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
627 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(
628 codec,
629 MIC_BIAS_2, false);
630 if (mbhc->mbhc_cb->set_micbias_value) {
631 mbhc->mbhc_cb->set_micbias_value(
632 codec);
633 WCD_MBHC_REG_UPDATE_BITS(
634 WCD_MBHC_MICB_CTRL, 0);
635 }
636 mbhc->micbias_enable = false;
637 }
638 mbhc->hph_type = WCD_MBHC_HPH_NONE;
639 mbhc->zl = mbhc->zr = 0;
640 pr_debug("%s: Reporting removal (%x)\n",
641 __func__, mbhc->hph_status);
642 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
643 0, WCD_MBHC_JACK_MASK);
644
645 if (mbhc->hph_status == SND_JACK_LINEOUT) {
646
647 pr_debug("%s: Enable micbias\n", __func__);
648 /* Disable current source and enable micbias */
649 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
650 pr_debug("%s: set up elec removal detection\n",
651 __func__);
652 usleep_range(200, 210);
653 wcd_mbhc_hs_elec_irq(mbhc,
654 WCD_MBHC_ELEC_HS_REM,
655 true);
656 }
657 mbhc->hph_status &= ~(SND_JACK_HEADSET |
658 SND_JACK_LINEOUT |
659 SND_JACK_ANC_HEADPHONE |
660 SND_JACK_UNSUPPORTED);
Vatsal Buchad6d62b82017-12-12 14:22:31 +0530661 mbhc->force_linein = false;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530662 }
663
664 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
665 jack_type == SND_JACK_HEADPHONE)
666 mbhc->hph_status &= ~SND_JACK_HEADSET;
667
668 /* Report insertion */
669 if (jack_type == SND_JACK_HEADPHONE)
670 mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE;
671 else if (jack_type == SND_JACK_UNSUPPORTED)
672 mbhc->current_plug = MBHC_PLUG_TYPE_GND_MIC_SWAP;
673 else if (jack_type == SND_JACK_HEADSET) {
674 mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET;
675 mbhc->jiffies_atreport = jiffies;
676 } else if (jack_type == SND_JACK_LINEOUT) {
677 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
678 } else if (jack_type == SND_JACK_ANC_HEADPHONE)
679 mbhc->current_plug = MBHC_PLUG_TYPE_ANC_HEADPHONE;
680
681 if (mbhc->mbhc_cb->hph_pa_on_status)
682 is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(codec);
683
684 if (mbhc->impedance_detect &&
685 mbhc->mbhc_cb->compute_impedance &&
686 (mbhc->mbhc_cfg->linein_th != 0) &&
687 (!is_pa_on)) {
688 /* Set MUX_CTL to AUTO for Z-det */
689 WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
690 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
691 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL,
692 MUX_CTL_AUTO);
693 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
694 mbhc->mbhc_cb->compute_impedance(mbhc,
695 &mbhc->zl, &mbhc->zr);
696 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN,
697 fsm_en);
698 if ((mbhc->zl > mbhc->mbhc_cfg->linein_th &&
699 mbhc->zl < MAX_IMPED) &&
700 (mbhc->zr > mbhc->mbhc_cfg->linein_th &&
701 mbhc->zr < MAX_IMPED) &&
702 (jack_type == SND_JACK_HEADPHONE)) {
703 jack_type = SND_JACK_LINEOUT;
Vatsal Buchad6d62b82017-12-12 14:22:31 +0530704 mbhc->force_linein = true;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530705 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
706 if (mbhc->hph_status) {
707 mbhc->hph_status &= ~(SND_JACK_HEADSET |
708 SND_JACK_LINEOUT |
709 SND_JACK_UNSUPPORTED);
710 wcd_mbhc_jack_report(mbhc,
711 &mbhc->headset_jack,
712 mbhc->hph_status,
713 WCD_MBHC_JACK_MASK);
714 }
715 pr_debug("%s: Marking jack type as SND_JACK_LINEOUT\n",
716 __func__);
717 }
718 }
719
720 mbhc->hph_status |= jack_type;
721
722 pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
723 jack_type, mbhc->hph_status);
724 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
725 (mbhc->hph_status | SND_JACK_MECHANICAL),
726 WCD_MBHC_JACK_MASK);
727 wcd_mbhc_clr_and_turnon_hph_padac(mbhc);
728 }
729 pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status);
730}
Meng Wang6f901622017-09-19 10:21:57 +0800731EXPORT_SYMBOL(wcd_mbhc_report_plug);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530732
733void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc)
734{
735 /* cancel pending button press */
736 if (wcd_cancel_btn_work(mbhc))
737 pr_debug("%s: button press is canceled\n", __func__);
738 /* cancel correct work function */
739 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug)
740 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
741 &mbhc->correct_plug_swch);
742 else
743 pr_info("%s: hs_detect_plug work not cancelled\n", __func__);
744
745 pr_debug("%s: Report extension cable\n", __func__);
746 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
747 /*
748 * If PA is enabled HPHL schmitt trigger can
749 * be unreliable, make sure to disable it
750 */
751 if (test_bit(WCD_MBHC_EVENT_PA_HPHL,
752 &mbhc->event_state))
753 wcd_mbhc_set_and_turnoff_hph_padac(mbhc);
754 /*
755 * Disable HPHL trigger and MIC Schmitt triggers.
756 * Setup for insertion detection.
757 */
758 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM,
759 false);
760 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE);
761 /* Disable HW FSM */
762 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
763 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 3);
764
765 /* Set the detection type appropriately */
766 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 1);
767 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS,
768 true);
769}
770EXPORT_SYMBOL(wcd_mbhc_elec_hs_report_unplug);
771
772void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc,
773 enum wcd_mbhc_plug_type plug_type)
774{
775 bool anc_mic_found = false;
776 enum snd_jack_types jack_type;
777
778 pr_debug("%s: enter current_plug(%d) new_plug(%d)\n",
779 __func__, mbhc->current_plug, plug_type);
780
781 WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
782
783 if (mbhc->current_plug == plug_type) {
784 pr_debug("%s: cable already reported, exit\n", __func__);
785 goto exit;
786 }
787
788 if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
789 /*
790 * Nothing was reported previously
791 * report a headphone or unsupported
792 */
793 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
794 } else if (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP) {
795 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
796 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
797 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
798 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
799 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_UNSUPPORTED);
800 } else if (plug_type == MBHC_PLUG_TYPE_HEADSET) {
801 if (mbhc->mbhc_cfg->enable_anc_mic_detect &&
802 mbhc->mbhc_fn->wcd_mbhc_detect_anc_plug_type)
803 anc_mic_found =
804 mbhc->mbhc_fn->wcd_mbhc_detect_anc_plug_type(mbhc);
805 jack_type = SND_JACK_HEADSET;
806 if (anc_mic_found)
807 jack_type = SND_JACK_ANC_HEADPHONE;
808
809 /*
810 * If Headphone was reported previously, this will
811 * only report the mic line
812 */
813 wcd_mbhc_report_plug(mbhc, 1, jack_type);
814 } else if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
815 if (mbhc->mbhc_cfg->detect_extn_cable) {
816 /* High impedance device found. Report as LINEOUT */
817 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
818 pr_debug("%s: setup mic trigger for further detection\n",
819 __func__);
820
821 /* Disable HW FSM and current source */
822 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
823 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
824 /* Setup for insertion detection */
825 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE,
826 1);
827 /*
828 * Enable HPHL trigger and MIC Schmitt triggers
829 * and request for elec insertion interrupts
830 */
831 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC,
832 3);
833 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS,
834 true);
835 } else {
836 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
837 }
838 } else {
839 WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
840 mbhc->current_plug, plug_type);
841 }
842exit:
843 pr_debug("%s: leave\n", __func__);
844}
845EXPORT_SYMBOL(wcd_mbhc_find_plug_and_report);
846
847static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
848{
849 bool detection_type = 0;
850 bool micbias1 = false;
851 struct snd_soc_codec *codec = mbhc->codec;
852 enum snd_jack_types jack_type;
853
854 dev_dbg(codec->dev, "%s: enter\n", __func__);
855 WCD_MBHC_RSC_LOCK(mbhc);
856 mbhc->in_swch_irq_handler = true;
857
858 /* cancel pending button press */
859 if (wcd_cancel_btn_work(mbhc))
860 pr_debug("%s: button press is canceled\n", __func__);
861
862 WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type);
863
864 /* Set the detection type appropriately */
865 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
866 !detection_type);
867
868 pr_debug("%s: mbhc->current_plug: %d detection_type: %d\n", __func__,
869 mbhc->current_plug, detection_type);
870 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug)
871 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
872 &mbhc->correct_plug_swch);
873 else
874 pr_info("%s: hs_detect_plug work not cancelled\n", __func__);
875
876 if (mbhc->mbhc_cb->micbias_enable_status)
877 micbias1 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
878 MIC_BIAS_1);
879
880 if ((mbhc->current_plug == MBHC_PLUG_TYPE_NONE) &&
881 detection_type) {
882 /* Make sure MASTER_BIAS_CTL is enabled */
883 mbhc->mbhc_cb->mbhc_bias(codec, true);
884
885 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl)
886 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
887 MBHC_COMMON_MICB_TAIL_CURR, true);
888
889 if (!mbhc->mbhc_cfg->hs_ext_micbias &&
890 mbhc->mbhc_cb->micb_internal)
891 /*
892 * Enable Tx2 RBias if the headset
893 * is using internal micbias
894 */
895 mbhc->mbhc_cb->micb_internal(codec, 1, true);
896
897 /* Remove micbias pulldown */
898 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_PULLDOWN_CTRL, 0);
899 /* Apply trim if needed on the device */
900 if (mbhc->mbhc_cb->trim_btn_reg)
901 mbhc->mbhc_cb->trim_btn_reg(codec);
902 /* Enable external voltage source to micbias if present */
903 if (mbhc->mbhc_cb->enable_mb_source)
904 mbhc->mbhc_cb->enable_mb_source(mbhc, true);
905 mbhc->btn_press_intr = false;
906 mbhc->is_btn_press = false;
907 if (mbhc->mbhc_fn)
908 mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc);
909 } else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
910 && !detection_type) {
911 /* Disable external voltage source to micbias if present */
912 if (mbhc->mbhc_cb->enable_mb_source)
913 mbhc->mbhc_cb->enable_mb_source(mbhc, false);
914 /* Disable HW FSM */
915 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
916 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
917 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl)
918 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
919 MBHC_COMMON_MICB_TAIL_CURR, false);
920
921 if (mbhc->mbhc_cb->set_cap_mode)
922 mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false);
923
924 mbhc->btn_press_intr = false;
925 mbhc->is_btn_press = false;
926 switch (mbhc->current_plug) {
927 case MBHC_PLUG_TYPE_HEADPHONE:
928 jack_type = SND_JACK_HEADPHONE;
929 break;
930 case MBHC_PLUG_TYPE_GND_MIC_SWAP:
931 jack_type = SND_JACK_UNSUPPORTED;
932 break;
933 case MBHC_PLUG_TYPE_HEADSET:
934 /* make sure to turn off Rbias */
935 if (mbhc->mbhc_cb->micb_internal)
936 mbhc->mbhc_cb->micb_internal(codec, 1, false);
937 /* Pulldown micbias */
938 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_PULLDOWN_CTRL, 1);
939 jack_type = SND_JACK_HEADSET;
940 break;
941 case MBHC_PLUG_TYPE_HIGH_HPH:
Vatsal Bucha79a80992018-05-10 14:20:18 +0530942 if (mbhc->mbhc_detection_logic == WCD_DETECTION_ADC)
943 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_ISRC_EN, 0);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530944 mbhc->is_extn_cable = false;
945 jack_type = SND_JACK_LINEOUT;
946 break;
947 case MBHC_PLUG_TYPE_ANC_HEADPHONE:
948 jack_type = SND_JACK_ANC_HEADPHONE;
949 break;
950 default:
951 pr_info("%s: Invalid current plug: %d\n",
952 __func__, mbhc->current_plug);
953 jack_type = SND_JACK_UNSUPPORTED;
954 break;
955 }
956 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM, false);
957 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
958 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 1);
959 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0);
960 mbhc->extn_cable_hph_rem = false;
961 wcd_mbhc_report_plug(mbhc, 0, jack_type);
962
963 } else if (!detection_type) {
964 /* Disable external voltage source to micbias if present */
965 if (mbhc->mbhc_cb->enable_mb_source)
966 mbhc->mbhc_cb->enable_mb_source(mbhc, false);
967 /* Disable HW FSM */
968 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
969 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
970 mbhc->extn_cable_hph_rem = false;
971 }
972
973 mbhc->in_swch_irq_handler = false;
974 WCD_MBHC_RSC_UNLOCK(mbhc);
975 pr_debug("%s: leave\n", __func__);
976}
977
978static irqreturn_t wcd_mbhc_mech_plug_detect_irq(int irq, void *data)
979{
980 int r = IRQ_HANDLED;
981 struct wcd_mbhc *mbhc = data;
982
983 pr_debug("%s: enter\n", __func__);
984 if (unlikely((mbhc->mbhc_cb->lock_sleep(mbhc, true)) == false)) {
985 pr_warn("%s: failed to hold suspend\n", __func__);
986 r = IRQ_NONE;
987 } else {
988 /* Call handler */
989 wcd_mbhc_swch_irq_handler(mbhc);
990 mbhc->mbhc_cb->lock_sleep(mbhc, false);
991 }
992 pr_debug("%s: leave %d\n", __func__, r);
993 return r;
994}
995
996int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc)
997{
998 int mask = 0;
999 int btn;
1000
1001 btn = mbhc->mbhc_cb->map_btn_code_to_num(mbhc->codec);
1002
1003 switch (btn) {
1004 case 0:
1005 mask = SND_JACK_BTN_0;
1006 break;
1007 case 1:
1008 mask = SND_JACK_BTN_1;
1009 break;
1010 case 2:
1011 mask = SND_JACK_BTN_2;
1012 break;
1013 case 3:
1014 mask = SND_JACK_BTN_3;
1015 break;
1016 case 4:
1017 mask = SND_JACK_BTN_4;
1018 break;
1019 case 5:
1020 mask = SND_JACK_BTN_5;
1021 break;
1022 default:
1023 break;
1024 }
1025
1026 return mask;
1027}
1028EXPORT_SYMBOL(wcd_mbhc_get_button_mask);
1029
1030static void wcd_btn_lpress_fn(struct work_struct *work)
1031{
1032 struct delayed_work *dwork;
1033 struct wcd_mbhc *mbhc;
1034 s16 btn_result = 0;
1035
1036 pr_debug("%s: Enter\n", __func__);
1037
1038 dwork = to_delayed_work(work);
1039 mbhc = container_of(dwork, struct wcd_mbhc, mbhc_btn_dwork);
1040
1041 WCD_MBHC_REG_READ(WCD_MBHC_BTN_RESULT, btn_result);
1042 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) {
1043 pr_debug("%s: Reporting long button press event, btn_result: %d\n",
1044 __func__, btn_result);
1045 wcd_mbhc_jack_report(mbhc, &mbhc->button_jack,
1046 mbhc->buttons_pressed, mbhc->buttons_pressed);
1047 }
1048 pr_debug("%s: leave\n", __func__);
1049 mbhc->mbhc_cb->lock_sleep(mbhc, false);
1050}
1051
1052static bool wcd_mbhc_fw_validate(const void *data, size_t size)
1053{
1054 u32 cfg_offset;
1055 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
1056 struct firmware_cal fw;
1057
1058 fw.data = (void *)data;
1059 fw.size = size;
1060
1061 if (fw.size < WCD_MBHC_CAL_MIN_SIZE)
1062 return false;
1063
1064 /*
1065 * Previous check guarantees that there is enough fw data up
1066 * to num_btn
1067 */
1068 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(fw.data);
1069 cfg_offset = (u32) ((void *) btn_cfg - (void *) fw.data);
1070 if (fw.size < (cfg_offset + WCD_MBHC_CAL_BTN_SZ(btn_cfg)))
1071 return false;
1072
1073 return true;
1074}
1075
1076static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
1077{
1078 struct wcd_mbhc *mbhc = data;
1079 int mask;
1080 unsigned long msec_val;
1081
1082 pr_debug("%s: enter\n", __func__);
1083 complete(&mbhc->btn_press_compl);
1084 WCD_MBHC_RSC_LOCK(mbhc);
1085 wcd_cancel_btn_work(mbhc);
1086 if (wcd_swch_level_remove(mbhc)) {
1087 pr_debug("%s: Switch level is low ", __func__);
1088 goto done;
1089 }
1090
1091 mbhc->is_btn_press = true;
1092 msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
1093 pr_debug("%s: msec_val = %ld\n", __func__, msec_val);
1094 if (msec_val < MBHC_BUTTON_PRESS_THRESHOLD_MIN) {
1095 pr_debug("%s: Too short, ignore button press\n", __func__);
1096 goto done;
1097 }
1098
1099 /* If switch interrupt already kicked in, ignore button press */
1100 if (mbhc->in_swch_irq_handler) {
1101 pr_debug("%s: Swtich level changed, ignore button press\n",
1102 __func__);
1103 goto done;
1104 }
1105 mask = wcd_mbhc_get_button_mask(mbhc);
1106 if (mask == SND_JACK_BTN_0)
1107 mbhc->btn_press_intr = true;
1108
1109 if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) {
1110 pr_debug("%s: Plug isn't headset, ignore button press\n",
1111 __func__);
1112 goto done;
1113 }
1114 mbhc->buttons_pressed |= mask;
1115 mbhc->mbhc_cb->lock_sleep(mbhc, true);
1116 if (schedule_delayed_work(&mbhc->mbhc_btn_dwork,
1117 msecs_to_jiffies(400)) == 0) {
1118 WARN(1, "Button pressed twice without release event\n");
1119 mbhc->mbhc_cb->lock_sleep(mbhc, false);
1120 }
1121done:
1122 pr_debug("%s: leave\n", __func__);
1123 WCD_MBHC_RSC_UNLOCK(mbhc);
1124 return IRQ_HANDLED;
1125}
1126
1127static irqreturn_t wcd_mbhc_release_handler(int irq, void *data)
1128{
1129 struct wcd_mbhc *mbhc = data;
1130 int ret;
1131
1132 pr_debug("%s: enter\n", __func__);
1133 WCD_MBHC_RSC_LOCK(mbhc);
1134 if (wcd_swch_level_remove(mbhc)) {
1135 pr_debug("%s: Switch level is low ", __func__);
1136 goto exit;
1137 }
1138
1139 if (mbhc->is_btn_press) {
1140 mbhc->is_btn_press = false;
1141 } else {
1142 pr_debug("%s: This release is for fake btn press\n", __func__);
1143 goto exit;
1144 }
1145
1146 /*
1147 * If current plug is headphone then there is no chance to
1148 * get btn release interrupt, so connected cable should be
1149 * headset not headphone.
1150 * For ADC MBHC, ADC_COMPLETE interrupt will be generated
1151 * in this case. So skip the check here.
1152 */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301153 if (mbhc->mbhc_detection_logic == WCD_DETECTION_LEGACY &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301154 mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
1155 wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
1156 goto exit;
1157
1158 }
1159 if (mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK) {
1160 ret = wcd_cancel_btn_work(mbhc);
1161 if (ret == 0) {
1162 pr_debug("%s: Reporting long button release event\n",
1163 __func__);
1164 wcd_mbhc_jack_report(mbhc, &mbhc->button_jack,
1165 0, mbhc->buttons_pressed);
1166 } else {
1167 if (mbhc->in_swch_irq_handler) {
1168 pr_debug("%s: Switch irq kicked in, ignore\n",
1169 __func__);
1170 } else {
1171 pr_debug("%s: Reporting btn press\n",
1172 __func__);
1173 wcd_mbhc_jack_report(mbhc,
1174 &mbhc->button_jack,
1175 mbhc->buttons_pressed,
1176 mbhc->buttons_pressed);
1177 pr_debug("%s: Reporting btn release\n",
1178 __func__);
1179 wcd_mbhc_jack_report(mbhc,
1180 &mbhc->button_jack,
1181 0, mbhc->buttons_pressed);
1182 }
1183 }
1184 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
1185 }
1186exit:
1187 pr_debug("%s: leave\n", __func__);
1188 WCD_MBHC_RSC_UNLOCK(mbhc);
1189 return IRQ_HANDLED;
1190}
1191
1192static irqreturn_t wcd_mbhc_hphl_ocp_irq(int irq, void *data)
1193{
1194 struct wcd_mbhc *mbhc = data;
1195 int val;
1196
1197 pr_debug("%s: received HPHL OCP irq\n", __func__);
1198 if (mbhc) {
1199 if (mbhc->mbhc_cb->hph_register_recovery) {
1200 if (mbhc->mbhc_cb->hph_register_recovery(mbhc)) {
1201 WCD_MBHC_REG_READ(WCD_MBHC_HPHR_OCP_STATUS,
1202 val);
1203 if ((val != -EINVAL) && val)
1204 mbhc->is_hph_ocp_pending = true;
1205 goto done;
1206 }
1207 }
1208
1209 if (mbhc->hphlocp_cnt < OCP_ATTEMPT) {
1210 mbhc->hphlocp_cnt++;
1211 pr_debug("%s: retry, hphlocp_cnt: %d\n", __func__,
1212 mbhc->hphlocp_cnt);
1213 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 0);
1214 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 1);
1215 } else {
1216 mbhc->mbhc_cb->irq_control(mbhc->codec,
1217 mbhc->intr_ids->hph_left_ocp,
1218 false);
1219 mbhc->hph_status |= SND_JACK_OC_HPHL;
1220 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
1221 mbhc->hph_status,
1222 WCD_MBHC_JACK_MASK);
1223 }
1224 } else {
1225 pr_err("%s: Bad wcd9xxx_spmi private data\n", __func__);
1226 }
1227done:
1228 return IRQ_HANDLED;
1229}
1230
1231static irqreturn_t wcd_mbhc_hphr_ocp_irq(int irq, void *data)
1232{
1233 struct wcd_mbhc *mbhc = data;
1234
1235 pr_debug("%s: received HPHR OCP irq\n", __func__);
1236
1237 if (!mbhc) {
1238 pr_err("%s: Bad mbhc private data\n", __func__);
1239 goto done;
1240 }
1241
1242 if (mbhc->is_hph_ocp_pending) {
1243 mbhc->is_hph_ocp_pending = false;
1244 goto done;
1245 }
1246
1247 if (mbhc->mbhc_cb->hph_register_recovery) {
1248 if (mbhc->mbhc_cb->hph_register_recovery(mbhc))
1249 /* register corruption, hence reset registers */
1250 goto done;
1251 }
1252 if (mbhc->hphrocp_cnt < OCP_ATTEMPT) {
1253 mbhc->hphrocp_cnt++;
1254 pr_debug("%s: retry, hphrocp_cnt: %d\n", __func__,
1255 mbhc->hphrocp_cnt);
1256 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 0);
1257 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 1);
1258 } else {
1259 mbhc->mbhc_cb->irq_control(mbhc->codec,
1260 mbhc->intr_ids->hph_right_ocp,
1261 false);
1262 mbhc->hph_status |= SND_JACK_OC_HPHR;
1263 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
1264 mbhc->hph_status, WCD_MBHC_JACK_MASK);
1265 }
1266done:
1267 return IRQ_HANDLED;
1268}
1269
1270static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
1271{
1272 int ret = 0;
1273 struct snd_soc_codec *codec = mbhc->codec;
1274
1275 pr_debug("%s: enter\n", __func__);
1276 WCD_MBHC_RSC_LOCK(mbhc);
1277
1278 /* enable HS detection */
1279 if (mbhc->mbhc_cb->hph_pull_up_control)
1280 mbhc->mbhc_cb->hph_pull_up_control(codec, I_DEFAULT);
1281 else
1282 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
1283
1284 if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config)
1285 mbhc->mbhc_cb->mbhc_moisture_config(mbhc);
1286
1287 /*
1288 * For USB analog we need to override the switch configuration.
1289 * Also, disable hph_l pull-up current source as HS_DET_L is driven
1290 * by an external source
1291 */
1292 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1293 mbhc->hphl_swh = 1;
1294 mbhc->gnd_swh = 1;
1295
1296 if (mbhc->mbhc_cb->hph_pull_up_control)
1297 mbhc->mbhc_cb->hph_pull_up_control(codec, I_OFF);
1298 else
1299 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL,
1300 0);
1301 }
1302
1303 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PLUG_TYPE, mbhc->hphl_swh);
1304 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_PLUG_TYPE, mbhc->gnd_swh);
1305 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1);
1306 if (mbhc->mbhc_cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl)
1307 mbhc->mbhc_cb->mbhc_gnd_det_ctrl(codec, true);
1308 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, 1);
1309 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
1310
1311 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1312 /* Insertion debounce set to 48ms */
1313 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_INSREM_DBNC, 4);
1314 } else {
1315 /* Insertion debounce set to 96ms */
1316 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_INSREM_DBNC, 6);
1317 }
1318
1319 /* Button Debounce set to 16ms */
1320 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_DBNC, 2);
1321
1322 /* Enable micbias ramp */
1323 if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
1324 mbhc->mbhc_cb->mbhc_micb_ramp_control(codec, true);
1325 /* enable bias */
1326 mbhc->mbhc_cb->mbhc_bias(codec, true);
1327 /* enable MBHC clock */
1328 if (mbhc->mbhc_cb->clk_setup)
1329 mbhc->mbhc_cb->clk_setup(codec, true);
1330
1331 /* program HS_VREF value */
1332 wcd_program_hs_vref(mbhc);
1333
1334 wcd_program_btn_threshold(mbhc, false);
1335
1336
1337 reinit_completion(&mbhc->btn_press_compl);
1338
1339 WCD_MBHC_RSC_UNLOCK(mbhc);
1340 pr_debug("%s: leave\n", __func__);
1341 return ret;
1342}
1343
1344static void wcd_mbhc_fw_read(struct work_struct *work)
1345{
1346 struct delayed_work *dwork;
1347 struct wcd_mbhc *mbhc;
1348 struct snd_soc_codec *codec;
1349 const struct firmware *fw;
1350 struct firmware_cal *fw_data = NULL;
1351 int ret = -1, retry = 0;
1352 bool use_default_cal = false;
1353
1354 dwork = to_delayed_work(work);
1355 mbhc = container_of(dwork, struct wcd_mbhc, mbhc_firmware_dwork);
1356 codec = mbhc->codec;
1357
1358 while (retry < FW_READ_ATTEMPTS) {
1359 retry++;
1360 pr_debug("%s:Attempt %d to request MBHC firmware\n",
1361 __func__, retry);
1362 if (mbhc->mbhc_cb->get_hwdep_fw_cal)
1363 fw_data = mbhc->mbhc_cb->get_hwdep_fw_cal(mbhc,
1364 WCD9XXX_MBHC_CAL);
1365 if (!fw_data)
1366 ret = request_firmware(&fw, "wcd9320/wcd9320_mbhc.bin",
1367 codec->dev);
1368 /*
1369 * if request_firmware and hwdep cal both fail then
1370 * sleep for 4sec for the userspace to send data to kernel
1371 * retry for few times before bailing out
1372 */
1373 if ((ret != 0) && !fw_data) {
1374 usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT +
1375 WCD_MBHC_USLEEP_RANGE_MARGIN_US);
1376 } else {
1377 pr_debug("%s: MBHC Firmware read successful\n",
1378 __func__);
1379 break;
1380 }
1381 }
1382 if (!fw_data)
1383 pr_debug("%s: using request_firmware\n", __func__);
1384 else
1385 pr_debug("%s: using hwdep cal\n", __func__);
1386
1387 if (ret != 0 && !fw_data) {
1388 pr_err("%s: Cannot load MBHC firmware use default cal\n",
1389 __func__);
1390 use_default_cal = true;
1391 }
1392 if (!use_default_cal) {
1393 const void *data;
1394 size_t size;
1395
1396 if (fw_data) {
1397 data = fw_data->data;
1398 size = fw_data->size;
1399 } else {
1400 data = fw->data;
1401 size = fw->size;
1402 }
1403 if (wcd_mbhc_fw_validate(data, size) == false) {
1404 pr_err("%s: Invalid MBHC cal data size use default cal\n",
1405 __func__);
1406 if (!fw_data)
1407 release_firmware(fw);
1408 } else {
1409 if (fw_data) {
1410 mbhc->mbhc_cfg->calibration =
1411 (void *)fw_data->data;
1412 mbhc->mbhc_cal = fw_data;
1413 } else {
1414 mbhc->mbhc_cfg->calibration =
1415 (void *)fw->data;
1416 mbhc->mbhc_fw = fw;
1417 }
1418 }
1419
1420 }
1421
1422 (void) wcd_mbhc_initialise(mbhc);
1423}
1424
1425static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc)
1426{
1427 enum snd_jack_types type;
1428 int i, ret, result = 0;
1429 int *btn_key_code;
1430
1431 btn_key_code = mbhc->mbhc_cfg->key_code;
1432
1433 for (i = 0 ; i < WCD_MBHC_KEYCODE_NUM ; i++) {
1434 if (btn_key_code[i] != 0) {
1435 switch (i) {
1436 case 0:
1437 type = SND_JACK_BTN_0;
1438 break;
1439 case 1:
1440 type = SND_JACK_BTN_1;
1441 break;
1442 case 2:
1443 type = SND_JACK_BTN_2;
1444 break;
1445 case 3:
1446 type = SND_JACK_BTN_3;
1447 break;
1448 case 4:
1449 type = SND_JACK_BTN_4;
1450 break;
1451 case 5:
1452 type = SND_JACK_BTN_5;
1453 break;
1454 default:
1455 WARN_ONCE(1, "Wrong button number:%d\n", i);
1456 result = -1;
1457 return result;
1458 }
1459 ret = snd_jack_set_key(mbhc->button_jack.jack,
1460 type,
1461 btn_key_code[i]);
1462 if (ret) {
1463 pr_err("%s: Failed to set code for %d\n",
1464 __func__, btn_key_code[i]);
1465 result = -1;
1466 return result;
1467 }
1468 input_set_capability(
1469 mbhc->button_jack.jack->input_dev,
1470 EV_KEY, btn_key_code[i]);
1471 pr_debug("%s: set btn%d key code:%d\n", __func__,
1472 i, btn_key_code[i]);
1473 }
1474 }
1475 if (btn_key_code[0])
1476 mbhc->is_btn_already_regd = true;
1477 return result;
1478}
1479
1480static int wcd_mbhc_usb_c_analog_setup_gpios(struct wcd_mbhc *mbhc,
1481 bool active)
1482{
1483 int rc = 0;
1484 struct usbc_ana_audio_config *config =
1485 &mbhc->mbhc_cfg->usbc_analog_cfg;
1486 union power_supply_propval pval;
1487
1488 dev_dbg(mbhc->codec->dev, "%s: setting GPIOs active = %d\n",
1489 __func__, active);
1490
1491 memset(&pval, 0, sizeof(pval));
1492
1493 if (active) {
1494 pval.intval = POWER_SUPPLY_TYPEC_PR_SOURCE;
1495 if (power_supply_set_property(mbhc->usb_psy,
1496 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &pval))
1497 dev_info(mbhc->codec->dev, "%s: force PR_SOURCE mode unsuccessful\n",
1498 __func__);
1499 else
1500 mbhc->usbc_force_pr_mode = true;
1501
1502 if (config->usbc_en1_gpio_p)
1503 rc = msm_cdc_pinctrl_select_active_state(
1504 config->usbc_en1_gpio_p);
1505 if (rc == 0 && config->usbc_force_gpio_p)
1506 rc = msm_cdc_pinctrl_select_active_state(
1507 config->usbc_force_gpio_p);
1508 mbhc->usbc_mode = POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
1509 } else {
1510 /* no delay is required when disabling GPIOs */
1511 if (config->usbc_en1_gpio_p)
1512 msm_cdc_pinctrl_select_sleep_state(
1513 config->usbc_en1_gpio_p);
1514 if (config->usbc_force_gpio_p)
1515 msm_cdc_pinctrl_select_sleep_state(
1516 config->usbc_force_gpio_p);
1517
1518 if (mbhc->usbc_force_pr_mode) {
1519 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
1520 if (power_supply_set_property(mbhc->usb_psy,
1521 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &pval))
1522 dev_info(mbhc->codec->dev, "%s: force PR_DUAL mode unsuccessful\n",
1523 __func__);
1524
1525 mbhc->usbc_force_pr_mode = false;
1526 }
1527
1528 mbhc->usbc_mode = POWER_SUPPLY_TYPEC_NONE;
1529 if (mbhc->mbhc_cfg->swap_gnd_mic)
1530 mbhc->mbhc_cfg->swap_gnd_mic(mbhc->codec, false);
1531 }
1532
1533 return rc;
1534}
1535
1536/* workqueue */
1537static void wcd_mbhc_usbc_analog_work_fn(struct work_struct *work)
1538{
1539 struct wcd_mbhc *mbhc =
1540 container_of(work, struct wcd_mbhc, usbc_analog_work);
1541
1542 wcd_mbhc_usb_c_analog_setup_gpios(mbhc,
1543 mbhc->usbc_mode != POWER_SUPPLY_TYPEC_NONE);
1544}
1545
1546/* this callback function is used to process PMI notification */
1547static int wcd_mbhc_usb_c_event_changed(struct notifier_block *nb,
1548 unsigned long evt, void *ptr)
1549{
1550 int ret;
1551 union power_supply_propval mode;
1552 struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, psy_nb);
1553 struct snd_soc_codec *codec = mbhc->codec;
1554
1555 if (ptr != mbhc->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
1556 return 0;
1557
1558 ret = power_supply_get_property(mbhc->usb_psy,
1559 POWER_SUPPLY_PROP_TYPEC_MODE, &mode);
1560 if (ret) {
1561 dev_err(codec->dev, "%s: Unable to read USB TYPEC_MODE: %d\n",
1562 __func__, ret);
1563 return ret;
1564 }
1565
1566 dev_dbg(codec->dev, "%s: USB change event received\n",
1567 __func__);
1568 dev_dbg(codec->dev, "%s: supply mode %d, expected %d\n", __func__,
1569 mode.intval, POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER);
1570
1571 switch (mode.intval) {
1572 case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
1573 case POWER_SUPPLY_TYPEC_NONE:
1574 dev_dbg(codec->dev, "%s: usbc_mode: %d; mode.intval: %d\n",
1575 __func__, mbhc->usbc_mode, mode.intval);
1576
1577 if (mbhc->usbc_mode == mode.intval)
1578 break; /* filter notifications received before */
1579 mbhc->usbc_mode = mode.intval;
1580
1581 dev_dbg(codec->dev, "%s: queueing usbc_analog_work\n",
1582 __func__);
1583 schedule_work(&mbhc->usbc_analog_work);
1584 break;
1585 default:
1586 break;
1587 }
1588 return ret;
1589}
1590
1591/* PMI registration code */
1592static int wcd_mbhc_usb_c_analog_init(struct wcd_mbhc *mbhc)
1593{
1594 int ret = 0;
1595 struct snd_soc_codec *codec = mbhc->codec;
1596
1597 dev_dbg(mbhc->codec->dev, "%s: usb-c analog setup start\n", __func__);
1598 INIT_WORK(&mbhc->usbc_analog_work, wcd_mbhc_usbc_analog_work_fn);
1599
1600 mbhc->usb_psy = power_supply_get_by_name("usb");
1601 if (IS_ERR_OR_NULL(mbhc->usb_psy)) {
1602 dev_err(codec->dev, "%s: could not get USB psy info\n",
1603 __func__);
1604 ret = -EPROBE_DEFER;
1605 if (IS_ERR(mbhc->usb_psy))
1606 ret = PTR_ERR(mbhc->usb_psy);
1607 mbhc->usb_psy = NULL;
1608 goto err;
1609 }
1610
1611 ret = wcd_mbhc_usb_c_analog_setup_gpios(mbhc, false);
1612 if (ret) {
1613 dev_err(codec->dev, "%s: error while setting USBC ana gpios\n",
1614 __func__);
1615 goto err;
1616 }
1617
1618 mbhc->psy_nb.notifier_call = wcd_mbhc_usb_c_event_changed;
1619 mbhc->psy_nb.priority = 0;
1620 ret = power_supply_reg_notifier(&mbhc->psy_nb);
1621 if (ret) {
1622 dev_err(codec->dev, "%s: power supply registration failed\n",
1623 __func__);
1624 goto err;
1625 }
1626
1627 /*
1628 * as part of the init sequence check if there is a connected
1629 * USB C analog adapter
1630 */
1631 dev_dbg(mbhc->codec->dev, "%s: verify if USB adapter is already inserted\n",
1632 __func__);
1633 ret = wcd_mbhc_usb_c_event_changed(&mbhc->psy_nb,
1634 PSY_EVENT_PROP_CHANGED,
1635 mbhc->usb_psy);
1636
1637err:
1638 return ret;
1639}
1640
1641static int wcd_mbhc_usb_c_analog_deinit(struct wcd_mbhc *mbhc)
1642{
1643 wcd_mbhc_usb_c_analog_setup_gpios(mbhc, false);
1644
1645 /* deregister from PMI */
1646 power_supply_unreg_notifier(&mbhc->psy_nb);
1647
1648 return 0;
1649}
1650
1651static int wcd_mbhc_init_gpio(struct wcd_mbhc *mbhc,
1652 struct wcd_mbhc_config *mbhc_cfg,
1653 const char *gpio_dt_str,
1654 int *gpio, struct device_node **gpio_dn)
1655{
1656 int rc = 0;
1657 struct snd_soc_codec *codec = mbhc->codec;
1658 struct snd_soc_card *card = codec->component.card;
1659
1660 dev_dbg(mbhc->codec->dev, "%s: gpio %s\n", __func__, gpio_dt_str);
1661
1662 *gpio_dn = of_parse_phandle(card->dev->of_node, gpio_dt_str, 0);
1663
1664 if (!(*gpio_dn)) {
1665 *gpio = of_get_named_gpio(card->dev->of_node, gpio_dt_str, 0);
1666 if (!gpio_is_valid(*gpio)) {
1667 dev_err(card->dev, "%s, property %s not in node %s",
1668 __func__, gpio_dt_str,
1669 card->dev->of_node->full_name);
1670 rc = -EINVAL;
1671 }
1672 }
1673
1674 return rc;
1675}
1676
1677int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg)
1678{
1679 int rc = 0;
1680 struct usbc_ana_audio_config *config;
1681 struct snd_soc_codec *codec;
1682 struct snd_soc_card *card;
1683 const char *usb_c_dt = "qcom,msm-mbhc-usbc-audio-supported";
1684
1685 if (!mbhc || !mbhc_cfg)
1686 return -EINVAL;
1687
1688 config = &mbhc_cfg->usbc_analog_cfg;
1689 codec = mbhc->codec;
1690 card = codec->component.card;
1691
1692 /* update the mbhc config */
1693 mbhc->mbhc_cfg = mbhc_cfg;
1694
1695 dev_dbg(mbhc->codec->dev, "%s: enter\n", __func__);
1696
1697 /* check if USB C analog is defined on device tree */
1698 mbhc_cfg->enable_usbc_analog = 0;
1699 if (of_find_property(card->dev->of_node, usb_c_dt, NULL)) {
1700 rc = of_property_read_u32(card->dev->of_node, usb_c_dt,
1701 &mbhc_cfg->enable_usbc_analog);
1702 }
1703 if (mbhc_cfg->enable_usbc_analog == 0 || rc != 0) {
1704 dev_info(card->dev,
1705 "%s: %s in dt node is missing or false\n",
1706 __func__, usb_c_dt);
1707 dev_info(card->dev,
1708 "%s: skipping USB c analog configuration\n", __func__);
1709 }
1710
1711 /* initialize GPIOs */
1712 if (mbhc_cfg->enable_usbc_analog) {
1713 dev_dbg(mbhc->codec->dev, "%s: usbc analog enabled\n",
1714 __func__);
Karthikeyan Mani5392d802017-11-08 20:32:38 -08001715 mbhc->swap_thr = GND_MIC_USBC_SWAP_THRESHOLD;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301716 rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
1717 "qcom,usbc-analog-en1-gpio",
1718 &config->usbc_en1_gpio,
1719 &config->usbc_en1_gpio_p);
1720 if (rc)
1721 goto err;
1722
1723 if (of_find_property(card->dev->of_node,
1724 "qcom,usbc-analog-force_detect_gpio",
1725 NULL)) {
1726 rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
1727 "qcom,usbc-analog-force_detect_gpio",
1728 &config->usbc_force_gpio,
1729 &config->usbc_force_gpio_p);
1730 if (rc)
1731 goto err;
1732 }
1733
1734 dev_dbg(mbhc->codec->dev, "%s: calling usb_c_analog_init\n",
1735 __func__);
1736 /* init PMI notifier */
1737 rc = wcd_mbhc_usb_c_analog_init(mbhc);
1738 if (rc) {
1739 rc = EPROBE_DEFER;
1740 goto err;
1741 }
1742 }
1743
1744 /* Set btn key code */
1745 if ((!mbhc->is_btn_already_regd) && wcd_mbhc_set_keycode(mbhc))
1746 pr_err("Set btn key code error!!!\n");
1747
1748 if (!mbhc->mbhc_cfg->read_fw_bin ||
1749 (mbhc->mbhc_cfg->read_fw_bin && mbhc->mbhc_fw) ||
1750 (mbhc->mbhc_cfg->read_fw_bin && mbhc->mbhc_cal)) {
1751 rc = wcd_mbhc_initialise(mbhc);
1752 } else {
1753 if (!mbhc->mbhc_fw || !mbhc->mbhc_cal)
1754 schedule_delayed_work(&mbhc->mbhc_firmware_dwork,
1755 usecs_to_jiffies(FW_READ_TIMEOUT));
1756 else
1757 pr_err("%s: Skipping to read mbhc fw, 0x%pK %pK\n",
1758 __func__, mbhc->mbhc_fw, mbhc->mbhc_cal);
1759 }
1760
1761 return rc;
1762err:
1763 if (config->usbc_en1_gpio > 0) {
1764 dev_dbg(card->dev, "%s free usb en1 gpio %d\n",
1765 __func__, config->usbc_en1_gpio);
1766 gpio_free(config->usbc_en1_gpio);
1767 config->usbc_en1_gpio = 0;
1768 }
1769 if (config->usbc_force_gpio > 0) {
1770 dev_dbg(card->dev, "%s free usb_force gpio %d\n",
1771 __func__, config->usbc_force_gpio);
1772 gpio_free(config->usbc_force_gpio);
1773 config->usbc_force_gpio = 0;
1774 }
1775 if (config->usbc_en1_gpio_p)
1776 of_node_put(config->usbc_en1_gpio_p);
1777 if (config->usbc_force_gpio_p)
1778 of_node_put(config->usbc_force_gpio_p);
1779 dev_dbg(mbhc->codec->dev, "%s: leave %d\n", __func__, rc);
1780 return rc;
1781}
1782EXPORT_SYMBOL(wcd_mbhc_start);
1783
1784void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
1785{
1786 struct usbc_ana_audio_config *config = &mbhc->mbhc_cfg->usbc_analog_cfg;
1787
1788 pr_debug("%s: enter\n", __func__);
1789
1790 if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE) {
1791 if (mbhc->mbhc_cb && mbhc->mbhc_cb->skip_imped_detect)
1792 mbhc->mbhc_cb->skip_imped_detect(mbhc->codec);
1793 }
1794 mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
1795 mbhc->hph_status = 0;
1796 if (mbhc->mbhc_cb && mbhc->mbhc_cb->irq_control) {
1797 mbhc->mbhc_cb->irq_control(mbhc->codec,
1798 mbhc->intr_ids->hph_left_ocp,
1799 false);
1800 mbhc->mbhc_cb->irq_control(mbhc->codec,
1801 mbhc->intr_ids->hph_right_ocp,
1802 false);
1803 }
1804 if (mbhc->mbhc_fw || mbhc->mbhc_cal) {
1805 cancel_delayed_work_sync(&mbhc->mbhc_firmware_dwork);
1806 if (!mbhc->mbhc_cal)
1807 release_firmware(mbhc->mbhc_fw);
1808 mbhc->mbhc_fw = NULL;
1809 mbhc->mbhc_cal = NULL;
1810 }
1811
1812 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1813 wcd_mbhc_usb_c_analog_deinit(mbhc);
1814 /* free GPIOs */
1815 if (config->usbc_en1_gpio > 0)
1816 gpio_free(config->usbc_en1_gpio);
1817 if (config->usbc_force_gpio)
1818 gpio_free(config->usbc_force_gpio);
1819
1820 if (config->usbc_en1_gpio_p)
1821 of_node_put(config->usbc_en1_gpio_p);
1822 if (config->usbc_force_gpio_p)
1823 of_node_put(config->usbc_force_gpio_p);
1824 }
1825
1826 pr_debug("%s: leave\n", __func__);
1827}
1828EXPORT_SYMBOL(wcd_mbhc_stop);
1829
1830/*
1831 * wcd_mbhc_init : initialize MBHC internal structures.
1832 *
1833 * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
1834 */
1835int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
1836 const struct wcd_mbhc_cb *mbhc_cb,
1837 const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
1838 struct wcd_mbhc_register *wcd_mbhc_regs,
1839 bool impedance_det_en)
1840{
1841 int ret = 0;
1842 int hph_swh = 0;
1843 int gnd_swh = 0;
1844 u32 hph_moist_config[3];
1845 struct snd_soc_card *card = codec->component.card;
1846 const char *hph_switch = "qcom,msm-mbhc-hphl-swh";
1847 const char *gnd_switch = "qcom,msm-mbhc-gnd-swh";
Meng Wang4d6a6be2017-09-15 10:35:44 +08001848 const char *hs_thre = "qcom,msm-mbhc-hs-mic-max-threshold-mv";
1849 const char *hph_thre = "qcom,msm-mbhc-hs-mic-min-threshold-mv";
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301850
1851 pr_debug("%s: enter\n", __func__);
1852
1853 ret = of_property_read_u32(card->dev->of_node, hph_switch, &hph_swh);
1854 if (ret) {
1855 dev_err(card->dev,
1856 "%s: missing %s in dt node\n", __func__, hph_switch);
1857 goto err;
1858 }
1859
1860 ret = of_property_read_u32(card->dev->of_node, gnd_switch, &gnd_swh);
1861 if (ret) {
1862 dev_err(card->dev,
1863 "%s: missing %s in dt node\n", __func__, gnd_switch);
1864 goto err;
1865 }
1866
Meng Wang4d6a6be2017-09-15 10:35:44 +08001867 ret = of_property_read_u32(card->dev->of_node, hs_thre,
1868 &(mbhc->hs_thr));
1869 if (ret)
1870 dev_dbg(card->dev,
1871 "%s: missing %s in dt node\n", __func__, hs_thre);
1872
1873 ret = of_property_read_u32(card->dev->of_node, hph_thre,
1874 &(mbhc->hph_thr));
1875 if (ret)
1876 dev_dbg(card->dev,
1877 "%s: missing %s in dt node\n", __func__, hph_thre);
1878
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301879 ret = of_property_read_u32_array(card->dev->of_node,
1880 "qcom,msm-mbhc-moist-cfg",
1881 hph_moist_config, 3);
1882 if (ret) {
1883 dev_dbg(card->dev, "%s: no qcom,msm-mbhc-moist-cfg in DT\n",
1884 __func__);
1885 mbhc->moist_vref = V_45_MV;
1886 mbhc->moist_iref = I_3P0_UA;
1887 mbhc->moist_rref = R_24_KOHM;
1888 } else {
1889 mbhc->moist_vref = hph_moist_config[0];
1890 mbhc->moist_iref = hph_moist_config[1];
1891 mbhc->moist_rref = hph_moist_config[2];
1892 }
1893
1894 mbhc->in_swch_irq_handler = false;
1895 mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
1896 mbhc->is_btn_press = false;
1897 mbhc->codec = codec;
1898 mbhc->intr_ids = mbhc_cdc_intr_ids;
1899 mbhc->impedance_detect = impedance_det_en;
1900 mbhc->hphl_swh = hph_swh;
1901 mbhc->gnd_swh = gnd_swh;
1902 mbhc->micbias_enable = false;
1903 mbhc->mbhc_cb = mbhc_cb;
1904 mbhc->btn_press_intr = false;
1905 mbhc->is_hs_recording = false;
1906 mbhc->is_extn_cable = false;
1907 mbhc->extn_cable_hph_rem = false;
1908 mbhc->hph_type = WCD_MBHC_HPH_NONE;
1909 mbhc->wcd_mbhc_regs = wcd_mbhc_regs;
Karthikeyan Mani5392d802017-11-08 20:32:38 -08001910 mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD;
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301911
1912 if (mbhc->intr_ids == NULL) {
1913 pr_err("%s: Interrupt mapping not provided\n", __func__);
1914 return -EINVAL;
1915 }
1916 if (!mbhc->wcd_mbhc_regs) {
1917 dev_err(codec->dev, "%s: mbhc registers are not defined\n",
1918 __func__);
1919 return -EINVAL;
1920 }
1921
1922 /* Check if IRQ and other required callbacks are defined or not */
1923 if (!mbhc_cb || !mbhc_cb->request_irq || !mbhc_cb->irq_control ||
1924 !mbhc_cb->free_irq || !mbhc_cb->map_btn_code_to_num ||
1925 !mbhc_cb->lock_sleep || !mbhc_cb->mbhc_bias ||
1926 !mbhc_cb->set_btn_thr) {
1927 dev_err(codec->dev, "%s: required mbhc callbacks are not defined\n",
1928 __func__);
1929 return -EINVAL;
1930 }
1931
1932 /* No need to create new sound card jacks if is is already created */
1933 if (mbhc->headset_jack.jack == NULL) {
1934 ret = snd_soc_card_jack_new(codec->component.card,
1935 "Headset Jack", WCD_MBHC_JACK_MASK,
1936 &mbhc->headset_jack, NULL, 0);
1937 if (ret) {
1938 pr_err("%s: Failed to create new jack\n", __func__);
1939 return ret;
1940 }
1941
1942 ret = snd_soc_card_jack_new(codec->component.card,
1943 "Button Jack",
1944 WCD_MBHC_JACK_BUTTON_MASK,
1945 &mbhc->button_jack, NULL, 0);
1946 if (ret) {
1947 pr_err("Failed to create new jack\n");
1948 return ret;
1949 }
1950
1951 ret = snd_jack_set_key(mbhc->button_jack.jack,
1952 SND_JACK_BTN_0,
1953 KEY_MEDIA);
1954 if (ret) {
1955 pr_err("%s: Failed to set code for btn-0\n",
1956 __func__);
1957 return ret;
1958 }
1959
1960 INIT_DELAYED_WORK(&mbhc->mbhc_firmware_dwork,
1961 wcd_mbhc_fw_read);
1962 INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_lpress_fn);
1963 }
1964 mutex_init(&mbhc->hphl_pa_lock);
1965 mutex_init(&mbhc->hphr_pa_lock);
1966 init_completion(&mbhc->btn_press_compl);
1967
1968 /* Register event notifier */
1969 mbhc->nblock.notifier_call = wcd_event_notify;
1970 if (mbhc->mbhc_cb->register_notifier) {
1971 ret = mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock,
1972 true);
1973 if (ret) {
1974 pr_err("%s: Failed to register notifier %d\n",
1975 __func__, ret);
1976 return ret;
1977 }
1978 }
1979
1980 init_waitqueue_head(&mbhc->wait_btn_press);
1981 mutex_init(&mbhc->codec_resource_lock);
1982
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301983 switch (mbhc->mbhc_detection_logic) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301984 case WCD_DETECTION_LEGACY:
1985 wcd_mbhc_legacy_init(mbhc);
1986 break;
1987 case WCD_DETECTION_ADC:
1988 wcd_mbhc_adc_init(mbhc);
1989 break;
1990 default:
1991 pr_err("%s: Unknown detection logic type %d\n",
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301992 __func__, mbhc->mbhc_detection_logic);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301993 break;
1994 }
1995
1996 if (!mbhc->mbhc_fn ||
1997 !mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq ||
1998 !mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq ||
1999 !mbhc->mbhc_fn->wcd_mbhc_detect_plug_type ||
2000 !mbhc->mbhc_fn->wcd_cancel_hs_detect_plug) {
2001 pr_err("%s: mbhc function pointer is NULL\n", __func__);
2002 goto err_mbhc_sw_irq;
2003 }
2004 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->mbhc_sw_intr,
2005 wcd_mbhc_mech_plug_detect_irq,
2006 "mbhc sw intr", mbhc);
2007 if (ret) {
2008 pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
2009 mbhc->intr_ids->mbhc_sw_intr, ret);
2010 goto err_mbhc_sw_irq;
2011 }
2012
2013 ret = mbhc->mbhc_cb->request_irq(codec,
2014 mbhc->intr_ids->mbhc_btn_press_intr,
2015 wcd_mbhc_btn_press_handler,
2016 "Button Press detect", mbhc);
2017 if (ret) {
2018 pr_err("%s: Failed to request irq %d\n", __func__,
2019 mbhc->intr_ids->mbhc_btn_press_intr);
2020 goto err_btn_press_irq;
2021 }
2022
2023 ret = mbhc->mbhc_cb->request_irq(codec,
2024 mbhc->intr_ids->mbhc_btn_release_intr,
2025 wcd_mbhc_release_handler,
2026 "Button Release detect", mbhc);
2027 if (ret) {
2028 pr_err("%s: Failed to request irq %d\n", __func__,
2029 mbhc->intr_ids->mbhc_btn_release_intr);
2030 goto err_btn_release_irq;
2031 }
2032
2033 ret = mbhc->mbhc_cb->request_irq(codec,
2034 mbhc->intr_ids->mbhc_hs_ins_intr,
2035 mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq,
2036 "Elect Insert", mbhc);
2037 if (ret) {
2038 pr_err("%s: Failed to request irq %d\n", __func__,
2039 mbhc->intr_ids->mbhc_hs_ins_intr);
2040 goto err_mbhc_hs_ins_irq;
2041 }
2042 mbhc->mbhc_cb->irq_control(codec, mbhc->intr_ids->mbhc_hs_ins_intr,
2043 false);
2044 clear_bit(WCD_MBHC_ELEC_HS_INS, &mbhc->intr_status);
2045
2046 ret = mbhc->mbhc_cb->request_irq(codec,
2047 mbhc->intr_ids->mbhc_hs_rem_intr,
2048 mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq,
2049 "Elect Remove", mbhc);
2050 if (ret) {
2051 pr_err("%s: Failed to request irq %d\n", __func__,
2052 mbhc->intr_ids->mbhc_hs_rem_intr);
2053 goto err_mbhc_hs_rem_irq;
2054 }
2055 mbhc->mbhc_cb->irq_control(codec, mbhc->intr_ids->mbhc_hs_rem_intr,
2056 false);
2057 clear_bit(WCD_MBHC_ELEC_HS_REM, &mbhc->intr_status);
2058
2059 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->hph_left_ocp,
2060 wcd_mbhc_hphl_ocp_irq, "HPH_L OCP detect",
2061 mbhc);
2062 if (ret) {
2063 pr_err("%s: Failed to request irq %d\n", __func__,
2064 mbhc->intr_ids->hph_left_ocp);
2065 goto err_hphl_ocp_irq;
2066 }
2067
2068 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->hph_right_ocp,
2069 wcd_mbhc_hphr_ocp_irq, "HPH_R OCP detect",
2070 mbhc);
2071 if (ret) {
2072 pr_err("%s: Failed to request irq %d\n", __func__,
2073 mbhc->intr_ids->hph_right_ocp);
2074 goto err_hphr_ocp_irq;
2075 }
2076
2077 pr_debug("%s: leave ret %d\n", __func__, ret);
2078 return ret;
2079
2080err_hphr_ocp_irq:
2081 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_left_ocp, mbhc);
2082err_hphl_ocp_irq:
2083 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
2084err_mbhc_hs_rem_irq:
2085 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
2086err_mbhc_hs_ins_irq:
2087 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_release_intr,
2088 mbhc);
2089err_btn_release_irq:
2090 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_press_intr,
2091 mbhc);
2092err_btn_press_irq:
2093 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_sw_intr, mbhc);
2094err_mbhc_sw_irq:
2095 if (mbhc->mbhc_cb->register_notifier)
2096 mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock, false);
2097 mutex_destroy(&mbhc->codec_resource_lock);
2098err:
2099 pr_debug("%s: leave ret %d\n", __func__, ret);
2100 return ret;
2101}
2102EXPORT_SYMBOL(wcd_mbhc_init);
2103
2104void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
2105{
2106 struct snd_soc_codec *codec = mbhc->codec;
2107
2108 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_sw_intr, mbhc);
2109 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_press_intr,
2110 mbhc);
2111 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_release_intr,
2112 mbhc);
2113 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
2114 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
2115 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_left_ocp, mbhc);
2116 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_right_ocp, mbhc);
2117 if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier)
2118 mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock, false);
2119 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug) {
2120 WCD_MBHC_RSC_LOCK(mbhc);
2121 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
2122 &mbhc->correct_plug_swch);
2123 WCD_MBHC_RSC_UNLOCK(mbhc);
2124 }
2125 mutex_destroy(&mbhc->codec_resource_lock);
2126 mutex_destroy(&mbhc->hphl_pa_lock);
2127 mutex_destroy(&mbhc->hphr_pa_lock);
2128}
2129EXPORT_SYMBOL(wcd_mbhc_deinit);
2130
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302131static int __init mbhc_init(void)
2132{
2133 return 0;
2134}
2135
2136static void __exit mbhc_exit(void)
2137{
2138}
2139
2140module_init(mbhc_init);
2141module_exit(mbhc_exit);
2142
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302143MODULE_DESCRIPTION("wcd MBHC v2 module");
2144MODULE_LICENSE("GPL v2");