blob: 3c501b49008461484203bfdeaa13ca29081a44cd [file] [log] [blame]
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12#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;
608 } else {
609 /*
610 * Report removal of current jack type.
611 * Headphone to headset shouldn't report headphone
612 * removal.
613 */
614 if (mbhc->mbhc_cfg->detect_extn_cable &&
615 (mbhc->current_plug == MBHC_PLUG_TYPE_HIGH_HPH ||
616 jack_type == SND_JACK_LINEOUT) &&
617 (mbhc->hph_status && mbhc->hph_status != jack_type)) {
618
Asish Bhattacharya84f7f732017-07-25 16:29:27 +0530619 if (mbhc->micbias_enable &&
620 mbhc->hph_status == SND_JACK_HEADSET) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530621 if (mbhc->mbhc_cb->mbhc_micbias_control)
622 mbhc->mbhc_cb->mbhc_micbias_control(
623 codec, MIC_BIAS_2,
624 MICB_DISABLE);
625 if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
626 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(
627 codec,
628 MIC_BIAS_2, false);
629 if (mbhc->mbhc_cb->set_micbias_value) {
630 mbhc->mbhc_cb->set_micbias_value(
631 codec);
632 WCD_MBHC_REG_UPDATE_BITS(
633 WCD_MBHC_MICB_CTRL, 0);
634 }
635 mbhc->micbias_enable = false;
636 }
637 mbhc->hph_type = WCD_MBHC_HPH_NONE;
638 mbhc->zl = mbhc->zr = 0;
639 pr_debug("%s: Reporting removal (%x)\n",
640 __func__, mbhc->hph_status);
641 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
642 0, WCD_MBHC_JACK_MASK);
643
644 if (mbhc->hph_status == SND_JACK_LINEOUT) {
645
646 pr_debug("%s: Enable micbias\n", __func__);
647 /* Disable current source and enable micbias */
648 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_MB);
649 pr_debug("%s: set up elec removal detection\n",
650 __func__);
651 usleep_range(200, 210);
652 wcd_mbhc_hs_elec_irq(mbhc,
653 WCD_MBHC_ELEC_HS_REM,
654 true);
655 }
656 mbhc->hph_status &= ~(SND_JACK_HEADSET |
657 SND_JACK_LINEOUT |
658 SND_JACK_ANC_HEADPHONE |
659 SND_JACK_UNSUPPORTED);
660 }
661
662 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
663 jack_type == SND_JACK_HEADPHONE)
664 mbhc->hph_status &= ~SND_JACK_HEADSET;
665
666 /* Report insertion */
667 if (jack_type == SND_JACK_HEADPHONE)
668 mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE;
669 else if (jack_type == SND_JACK_UNSUPPORTED)
670 mbhc->current_plug = MBHC_PLUG_TYPE_GND_MIC_SWAP;
671 else if (jack_type == SND_JACK_HEADSET) {
672 mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET;
673 mbhc->jiffies_atreport = jiffies;
674 } else if (jack_type == SND_JACK_LINEOUT) {
675 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
676 } else if (jack_type == SND_JACK_ANC_HEADPHONE)
677 mbhc->current_plug = MBHC_PLUG_TYPE_ANC_HEADPHONE;
678
679 if (mbhc->mbhc_cb->hph_pa_on_status)
680 is_pa_on = mbhc->mbhc_cb->hph_pa_on_status(codec);
681
682 if (mbhc->impedance_detect &&
683 mbhc->mbhc_cb->compute_impedance &&
684 (mbhc->mbhc_cfg->linein_th != 0) &&
685 (!is_pa_on)) {
686 /* Set MUX_CTL to AUTO for Z-det */
687 WCD_MBHC_REG_READ(WCD_MBHC_FSM_EN, fsm_en);
688 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
689 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MUX_CTL,
690 MUX_CTL_AUTO);
691 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 1);
692 mbhc->mbhc_cb->compute_impedance(mbhc,
693 &mbhc->zl, &mbhc->zr);
694 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN,
695 fsm_en);
696 if ((mbhc->zl > mbhc->mbhc_cfg->linein_th &&
697 mbhc->zl < MAX_IMPED) &&
698 (mbhc->zr > mbhc->mbhc_cfg->linein_th &&
699 mbhc->zr < MAX_IMPED) &&
700 (jack_type == SND_JACK_HEADPHONE)) {
701 jack_type = SND_JACK_LINEOUT;
702 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
703 if (mbhc->hph_status) {
704 mbhc->hph_status &= ~(SND_JACK_HEADSET |
705 SND_JACK_LINEOUT |
706 SND_JACK_UNSUPPORTED);
707 wcd_mbhc_jack_report(mbhc,
708 &mbhc->headset_jack,
709 mbhc->hph_status,
710 WCD_MBHC_JACK_MASK);
711 }
712 pr_debug("%s: Marking jack type as SND_JACK_LINEOUT\n",
713 __func__);
714 }
715 }
716
717 mbhc->hph_status |= jack_type;
718
719 pr_debug("%s: Reporting insertion %d(%x)\n", __func__,
720 jack_type, mbhc->hph_status);
721 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
722 (mbhc->hph_status | SND_JACK_MECHANICAL),
723 WCD_MBHC_JACK_MASK);
724 wcd_mbhc_clr_and_turnon_hph_padac(mbhc);
725 }
726 pr_debug("%s: leave hph_status %x\n", __func__, mbhc->hph_status);
727}
Meng Wang6f901622017-09-19 10:21:57 +0800728EXPORT_SYMBOL(wcd_mbhc_report_plug);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +0530729
730void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc)
731{
732 /* cancel pending button press */
733 if (wcd_cancel_btn_work(mbhc))
734 pr_debug("%s: button press is canceled\n", __func__);
735 /* cancel correct work function */
736 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug)
737 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
738 &mbhc->correct_plug_swch);
739 else
740 pr_info("%s: hs_detect_plug work not cancelled\n", __func__);
741
742 pr_debug("%s: Report extension cable\n", __func__);
743 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
744 /*
745 * If PA is enabled HPHL schmitt trigger can
746 * be unreliable, make sure to disable it
747 */
748 if (test_bit(WCD_MBHC_EVENT_PA_HPHL,
749 &mbhc->event_state))
750 wcd_mbhc_set_and_turnoff_hph_padac(mbhc);
751 /*
752 * Disable HPHL trigger and MIC Schmitt triggers.
753 * Setup for insertion detection.
754 */
755 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM,
756 false);
757 wcd_enable_curr_micbias(mbhc, WCD_MBHC_EN_NONE);
758 /* Disable HW FSM */
759 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
760 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 3);
761
762 /* Set the detection type appropriately */
763 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 1);
764 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS,
765 true);
766}
767EXPORT_SYMBOL(wcd_mbhc_elec_hs_report_unplug);
768
769void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc,
770 enum wcd_mbhc_plug_type plug_type)
771{
772 bool anc_mic_found = false;
773 enum snd_jack_types jack_type;
774
775 pr_debug("%s: enter current_plug(%d) new_plug(%d)\n",
776 __func__, mbhc->current_plug, plug_type);
777
778 WCD_MBHC_RSC_ASSERT_LOCKED(mbhc);
779
780 if (mbhc->current_plug == plug_type) {
781 pr_debug("%s: cable already reported, exit\n", __func__);
782 goto exit;
783 }
784
785 if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
786 /*
787 * Nothing was reported previously
788 * report a headphone or unsupported
789 */
790 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
791 } else if (plug_type == MBHC_PLUG_TYPE_GND_MIC_SWAP) {
792 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
793 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
794 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
795 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
796 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_UNSUPPORTED);
797 } else if (plug_type == MBHC_PLUG_TYPE_HEADSET) {
798 if (mbhc->mbhc_cfg->enable_anc_mic_detect &&
799 mbhc->mbhc_fn->wcd_mbhc_detect_anc_plug_type)
800 anc_mic_found =
801 mbhc->mbhc_fn->wcd_mbhc_detect_anc_plug_type(mbhc);
802 jack_type = SND_JACK_HEADSET;
803 if (anc_mic_found)
804 jack_type = SND_JACK_ANC_HEADPHONE;
805
806 /*
807 * If Headphone was reported previously, this will
808 * only report the mic line
809 */
810 wcd_mbhc_report_plug(mbhc, 1, jack_type);
811 } else if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
812 if (mbhc->mbhc_cfg->detect_extn_cable) {
813 /* High impedance device found. Report as LINEOUT */
814 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
815 pr_debug("%s: setup mic trigger for further detection\n",
816 __func__);
817
818 /* Disable HW FSM and current source */
819 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
820 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
821 /* Setup for insertion detection */
822 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE,
823 1);
824 /*
825 * Enable HPHL trigger and MIC Schmitt triggers
826 * and request for elec insertion interrupts
827 */
828 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC,
829 3);
830 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS,
831 true);
832 } else {
833 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
834 }
835 } else {
836 WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
837 mbhc->current_plug, plug_type);
838 }
839exit:
840 pr_debug("%s: leave\n", __func__);
841}
842EXPORT_SYMBOL(wcd_mbhc_find_plug_and_report);
843
844static void wcd_mbhc_swch_irq_handler(struct wcd_mbhc *mbhc)
845{
846 bool detection_type = 0;
847 bool micbias1 = false;
848 struct snd_soc_codec *codec = mbhc->codec;
849 enum snd_jack_types jack_type;
850
851 dev_dbg(codec->dev, "%s: enter\n", __func__);
852 WCD_MBHC_RSC_LOCK(mbhc);
853 mbhc->in_swch_irq_handler = true;
854
855 /* cancel pending button press */
856 if (wcd_cancel_btn_work(mbhc))
857 pr_debug("%s: button press is canceled\n", __func__);
858
859 WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type);
860
861 /* Set the detection type appropriately */
862 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE,
863 !detection_type);
864
865 pr_debug("%s: mbhc->current_plug: %d detection_type: %d\n", __func__,
866 mbhc->current_plug, detection_type);
867 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug)
868 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
869 &mbhc->correct_plug_swch);
870 else
871 pr_info("%s: hs_detect_plug work not cancelled\n", __func__);
872
873 if (mbhc->mbhc_cb->micbias_enable_status)
874 micbias1 = mbhc->mbhc_cb->micbias_enable_status(mbhc,
875 MIC_BIAS_1);
876
877 if ((mbhc->current_plug == MBHC_PLUG_TYPE_NONE) &&
878 detection_type) {
879 /* Make sure MASTER_BIAS_CTL is enabled */
880 mbhc->mbhc_cb->mbhc_bias(codec, true);
881
882 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl)
883 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
884 MBHC_COMMON_MICB_TAIL_CURR, true);
885
886 if (!mbhc->mbhc_cfg->hs_ext_micbias &&
887 mbhc->mbhc_cb->micb_internal)
888 /*
889 * Enable Tx2 RBias if the headset
890 * is using internal micbias
891 */
892 mbhc->mbhc_cb->micb_internal(codec, 1, true);
893
894 /* Remove micbias pulldown */
895 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_PULLDOWN_CTRL, 0);
896 /* Apply trim if needed on the device */
897 if (mbhc->mbhc_cb->trim_btn_reg)
898 mbhc->mbhc_cb->trim_btn_reg(codec);
899 /* Enable external voltage source to micbias if present */
900 if (mbhc->mbhc_cb->enable_mb_source)
901 mbhc->mbhc_cb->enable_mb_source(mbhc, true);
902 mbhc->btn_press_intr = false;
903 mbhc->is_btn_press = false;
904 if (mbhc->mbhc_fn)
905 mbhc->mbhc_fn->wcd_mbhc_detect_plug_type(mbhc);
906 } else if ((mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
907 && !detection_type) {
908 /* Disable external voltage source to micbias if present */
909 if (mbhc->mbhc_cb->enable_mb_source)
910 mbhc->mbhc_cb->enable_mb_source(mbhc, false);
911 /* Disable HW FSM */
912 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
913 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
914 if (mbhc->mbhc_cb->mbhc_common_micb_ctrl)
915 mbhc->mbhc_cb->mbhc_common_micb_ctrl(codec,
916 MBHC_COMMON_MICB_TAIL_CURR, false);
917
918 if (mbhc->mbhc_cb->set_cap_mode)
919 mbhc->mbhc_cb->set_cap_mode(codec, micbias1, false);
920
921 mbhc->btn_press_intr = false;
922 mbhc->is_btn_press = false;
923 switch (mbhc->current_plug) {
924 case MBHC_PLUG_TYPE_HEADPHONE:
925 jack_type = SND_JACK_HEADPHONE;
926 break;
927 case MBHC_PLUG_TYPE_GND_MIC_SWAP:
928 jack_type = SND_JACK_UNSUPPORTED;
929 break;
930 case MBHC_PLUG_TYPE_HEADSET:
931 /* make sure to turn off Rbias */
932 if (mbhc->mbhc_cb->micb_internal)
933 mbhc->mbhc_cb->micb_internal(codec, 1, false);
934 /* Pulldown micbias */
935 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_PULLDOWN_CTRL, 1);
936 jack_type = SND_JACK_HEADSET;
937 break;
938 case MBHC_PLUG_TYPE_HIGH_HPH:
939 mbhc->is_extn_cable = false;
940 jack_type = SND_JACK_LINEOUT;
941 break;
942 case MBHC_PLUG_TYPE_ANC_HEADPHONE:
943 jack_type = SND_JACK_ANC_HEADPHONE;
944 break;
945 default:
946 pr_info("%s: Invalid current plug: %d\n",
947 __func__, mbhc->current_plug);
948 jack_type = SND_JACK_UNSUPPORTED;
949 break;
950 }
951 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_REM, false);
952 wcd_mbhc_hs_elec_irq(mbhc, WCD_MBHC_ELEC_HS_INS, false);
953 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_DETECTION_TYPE, 1);
954 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_ELECT_SCHMT_ISRC, 0);
955 mbhc->extn_cable_hph_rem = false;
956 wcd_mbhc_report_plug(mbhc, 0, jack_type);
957
958 } else if (!detection_type) {
959 /* Disable external voltage source to micbias if present */
960 if (mbhc->mbhc_cb->enable_mb_source)
961 mbhc->mbhc_cb->enable_mb_source(mbhc, false);
962 /* Disable HW FSM */
963 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_FSM_EN, 0);
964 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_ISRC_CTL, 0);
965 mbhc->extn_cable_hph_rem = false;
966 }
967
968 mbhc->in_swch_irq_handler = false;
969 WCD_MBHC_RSC_UNLOCK(mbhc);
970 pr_debug("%s: leave\n", __func__);
971}
972
973static irqreturn_t wcd_mbhc_mech_plug_detect_irq(int irq, void *data)
974{
975 int r = IRQ_HANDLED;
976 struct wcd_mbhc *mbhc = data;
977
978 pr_debug("%s: enter\n", __func__);
979 if (unlikely((mbhc->mbhc_cb->lock_sleep(mbhc, true)) == false)) {
980 pr_warn("%s: failed to hold suspend\n", __func__);
981 r = IRQ_NONE;
982 } else {
983 /* Call handler */
984 wcd_mbhc_swch_irq_handler(mbhc);
985 mbhc->mbhc_cb->lock_sleep(mbhc, false);
986 }
987 pr_debug("%s: leave %d\n", __func__, r);
988 return r;
989}
990
991int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc)
992{
993 int mask = 0;
994 int btn;
995
996 btn = mbhc->mbhc_cb->map_btn_code_to_num(mbhc->codec);
997
998 switch (btn) {
999 case 0:
1000 mask = SND_JACK_BTN_0;
1001 break;
1002 case 1:
1003 mask = SND_JACK_BTN_1;
1004 break;
1005 case 2:
1006 mask = SND_JACK_BTN_2;
1007 break;
1008 case 3:
1009 mask = SND_JACK_BTN_3;
1010 break;
1011 case 4:
1012 mask = SND_JACK_BTN_4;
1013 break;
1014 case 5:
1015 mask = SND_JACK_BTN_5;
1016 break;
1017 default:
1018 break;
1019 }
1020
1021 return mask;
1022}
1023EXPORT_SYMBOL(wcd_mbhc_get_button_mask);
1024
1025static void wcd_btn_lpress_fn(struct work_struct *work)
1026{
1027 struct delayed_work *dwork;
1028 struct wcd_mbhc *mbhc;
1029 s16 btn_result = 0;
1030
1031 pr_debug("%s: Enter\n", __func__);
1032
1033 dwork = to_delayed_work(work);
1034 mbhc = container_of(dwork, struct wcd_mbhc, mbhc_btn_dwork);
1035
1036 WCD_MBHC_REG_READ(WCD_MBHC_BTN_RESULT, btn_result);
1037 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) {
1038 pr_debug("%s: Reporting long button press event, btn_result: %d\n",
1039 __func__, btn_result);
1040 wcd_mbhc_jack_report(mbhc, &mbhc->button_jack,
1041 mbhc->buttons_pressed, mbhc->buttons_pressed);
1042 }
1043 pr_debug("%s: leave\n", __func__);
1044 mbhc->mbhc_cb->lock_sleep(mbhc, false);
1045}
1046
1047static bool wcd_mbhc_fw_validate(const void *data, size_t size)
1048{
1049 u32 cfg_offset;
1050 struct wcd_mbhc_btn_detect_cfg *btn_cfg;
1051 struct firmware_cal fw;
1052
1053 fw.data = (void *)data;
1054 fw.size = size;
1055
1056 if (fw.size < WCD_MBHC_CAL_MIN_SIZE)
1057 return false;
1058
1059 /*
1060 * Previous check guarantees that there is enough fw data up
1061 * to num_btn
1062 */
1063 btn_cfg = WCD_MBHC_CAL_BTN_DET_PTR(fw.data);
1064 cfg_offset = (u32) ((void *) btn_cfg - (void *) fw.data);
1065 if (fw.size < (cfg_offset + WCD_MBHC_CAL_BTN_SZ(btn_cfg)))
1066 return false;
1067
1068 return true;
1069}
1070
1071static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
1072{
1073 struct wcd_mbhc *mbhc = data;
1074 int mask;
1075 unsigned long msec_val;
1076
1077 pr_debug("%s: enter\n", __func__);
1078 complete(&mbhc->btn_press_compl);
1079 WCD_MBHC_RSC_LOCK(mbhc);
1080 wcd_cancel_btn_work(mbhc);
1081 if (wcd_swch_level_remove(mbhc)) {
1082 pr_debug("%s: Switch level is low ", __func__);
1083 goto done;
1084 }
1085
1086 mbhc->is_btn_press = true;
1087 msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
1088 pr_debug("%s: msec_val = %ld\n", __func__, msec_val);
1089 if (msec_val < MBHC_BUTTON_PRESS_THRESHOLD_MIN) {
1090 pr_debug("%s: Too short, ignore button press\n", __func__);
1091 goto done;
1092 }
1093
1094 /* If switch interrupt already kicked in, ignore button press */
1095 if (mbhc->in_swch_irq_handler) {
1096 pr_debug("%s: Swtich level changed, ignore button press\n",
1097 __func__);
1098 goto done;
1099 }
1100 mask = wcd_mbhc_get_button_mask(mbhc);
1101 if (mask == SND_JACK_BTN_0)
1102 mbhc->btn_press_intr = true;
1103
1104 if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) {
1105 pr_debug("%s: Plug isn't headset, ignore button press\n",
1106 __func__);
1107 goto done;
1108 }
1109 mbhc->buttons_pressed |= mask;
1110 mbhc->mbhc_cb->lock_sleep(mbhc, true);
1111 if (schedule_delayed_work(&mbhc->mbhc_btn_dwork,
1112 msecs_to_jiffies(400)) == 0) {
1113 WARN(1, "Button pressed twice without release event\n");
1114 mbhc->mbhc_cb->lock_sleep(mbhc, false);
1115 }
1116done:
1117 pr_debug("%s: leave\n", __func__);
1118 WCD_MBHC_RSC_UNLOCK(mbhc);
1119 return IRQ_HANDLED;
1120}
1121
1122static irqreturn_t wcd_mbhc_release_handler(int irq, void *data)
1123{
1124 struct wcd_mbhc *mbhc = data;
1125 int ret;
1126
1127 pr_debug("%s: enter\n", __func__);
1128 WCD_MBHC_RSC_LOCK(mbhc);
1129 if (wcd_swch_level_remove(mbhc)) {
1130 pr_debug("%s: Switch level is low ", __func__);
1131 goto exit;
1132 }
1133
1134 if (mbhc->is_btn_press) {
1135 mbhc->is_btn_press = false;
1136 } else {
1137 pr_debug("%s: This release is for fake btn press\n", __func__);
1138 goto exit;
1139 }
1140
1141 /*
1142 * If current plug is headphone then there is no chance to
1143 * get btn release interrupt, so connected cable should be
1144 * headset not headphone.
1145 * For ADC MBHC, ADC_COMPLETE interrupt will be generated
1146 * in this case. So skip the check here.
1147 */
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301148 if (mbhc->mbhc_detection_logic == WCD_DETECTION_LEGACY &&
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301149 mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
1150 wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
1151 goto exit;
1152
1153 }
1154 if (mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK) {
1155 ret = wcd_cancel_btn_work(mbhc);
1156 if (ret == 0) {
1157 pr_debug("%s: Reporting long button release event\n",
1158 __func__);
1159 wcd_mbhc_jack_report(mbhc, &mbhc->button_jack,
1160 0, mbhc->buttons_pressed);
1161 } else {
1162 if (mbhc->in_swch_irq_handler) {
1163 pr_debug("%s: Switch irq kicked in, ignore\n",
1164 __func__);
1165 } else {
1166 pr_debug("%s: Reporting btn press\n",
1167 __func__);
1168 wcd_mbhc_jack_report(mbhc,
1169 &mbhc->button_jack,
1170 mbhc->buttons_pressed,
1171 mbhc->buttons_pressed);
1172 pr_debug("%s: Reporting btn release\n",
1173 __func__);
1174 wcd_mbhc_jack_report(mbhc,
1175 &mbhc->button_jack,
1176 0, mbhc->buttons_pressed);
1177 }
1178 }
1179 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
1180 }
1181exit:
1182 pr_debug("%s: leave\n", __func__);
1183 WCD_MBHC_RSC_UNLOCK(mbhc);
1184 return IRQ_HANDLED;
1185}
1186
1187static irqreturn_t wcd_mbhc_hphl_ocp_irq(int irq, void *data)
1188{
1189 struct wcd_mbhc *mbhc = data;
1190 int val;
1191
1192 pr_debug("%s: received HPHL OCP irq\n", __func__);
1193 if (mbhc) {
1194 if (mbhc->mbhc_cb->hph_register_recovery) {
1195 if (mbhc->mbhc_cb->hph_register_recovery(mbhc)) {
1196 WCD_MBHC_REG_READ(WCD_MBHC_HPHR_OCP_STATUS,
1197 val);
1198 if ((val != -EINVAL) && val)
1199 mbhc->is_hph_ocp_pending = true;
1200 goto done;
1201 }
1202 }
1203
1204 if (mbhc->hphlocp_cnt < OCP_ATTEMPT) {
1205 mbhc->hphlocp_cnt++;
1206 pr_debug("%s: retry, hphlocp_cnt: %d\n", __func__,
1207 mbhc->hphlocp_cnt);
1208 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 0);
1209 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 1);
1210 } else {
1211 mbhc->mbhc_cb->irq_control(mbhc->codec,
1212 mbhc->intr_ids->hph_left_ocp,
1213 false);
1214 mbhc->hph_status |= SND_JACK_OC_HPHL;
1215 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
1216 mbhc->hph_status,
1217 WCD_MBHC_JACK_MASK);
1218 }
1219 } else {
1220 pr_err("%s: Bad wcd9xxx_spmi private data\n", __func__);
1221 }
1222done:
1223 return IRQ_HANDLED;
1224}
1225
1226static irqreturn_t wcd_mbhc_hphr_ocp_irq(int irq, void *data)
1227{
1228 struct wcd_mbhc *mbhc = data;
1229
1230 pr_debug("%s: received HPHR OCP irq\n", __func__);
1231
1232 if (!mbhc) {
1233 pr_err("%s: Bad mbhc private data\n", __func__);
1234 goto done;
1235 }
1236
1237 if (mbhc->is_hph_ocp_pending) {
1238 mbhc->is_hph_ocp_pending = false;
1239 goto done;
1240 }
1241
1242 if (mbhc->mbhc_cb->hph_register_recovery) {
1243 if (mbhc->mbhc_cb->hph_register_recovery(mbhc))
1244 /* register corruption, hence reset registers */
1245 goto done;
1246 }
1247 if (mbhc->hphrocp_cnt < OCP_ATTEMPT) {
1248 mbhc->hphrocp_cnt++;
1249 pr_debug("%s: retry, hphrocp_cnt: %d\n", __func__,
1250 mbhc->hphrocp_cnt);
1251 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 0);
1252 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_OCP_FSM_EN, 1);
1253 } else {
1254 mbhc->mbhc_cb->irq_control(mbhc->codec,
1255 mbhc->intr_ids->hph_right_ocp,
1256 false);
1257 mbhc->hph_status |= SND_JACK_OC_HPHR;
1258 wcd_mbhc_jack_report(mbhc, &mbhc->headset_jack,
1259 mbhc->hph_status, WCD_MBHC_JACK_MASK);
1260 }
1261done:
1262 return IRQ_HANDLED;
1263}
1264
1265static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
1266{
1267 int ret = 0;
1268 struct snd_soc_codec *codec = mbhc->codec;
1269
1270 pr_debug("%s: enter\n", __func__);
1271 WCD_MBHC_RSC_LOCK(mbhc);
1272
1273 /* enable HS detection */
1274 if (mbhc->mbhc_cb->hph_pull_up_control)
1275 mbhc->mbhc_cb->hph_pull_up_control(codec, I_DEFAULT);
1276 else
1277 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
1278
1279 if (mbhc->mbhc_cfg->moisture_en && mbhc->mbhc_cb->mbhc_moisture_config)
1280 mbhc->mbhc_cb->mbhc_moisture_config(mbhc);
1281
1282 /*
1283 * For USB analog we need to override the switch configuration.
1284 * Also, disable hph_l pull-up current source as HS_DET_L is driven
1285 * by an external source
1286 */
1287 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1288 mbhc->hphl_swh = 1;
1289 mbhc->gnd_swh = 1;
1290
1291 if (mbhc->mbhc_cb->hph_pull_up_control)
1292 mbhc->mbhc_cb->hph_pull_up_control(codec, I_OFF);
1293 else
1294 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_CTRL,
1295 0);
1296 }
1297
1298 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HPHL_PLUG_TYPE, mbhc->hphl_swh);
1299 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_GND_PLUG_TYPE, mbhc->gnd_swh);
1300 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1);
1301 if (mbhc->mbhc_cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl)
1302 mbhc->mbhc_cb->mbhc_gnd_det_ctrl(codec, true);
1303 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, 1);
1304 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1);
1305
1306 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1307 /* Insertion debounce set to 48ms */
1308 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_INSREM_DBNC, 4);
1309 } else {
1310 /* Insertion debounce set to 96ms */
1311 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_INSREM_DBNC, 6);
1312 }
1313
1314 /* Button Debounce set to 16ms */
1315 WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_BTN_DBNC, 2);
1316
1317 /* Enable micbias ramp */
1318 if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
1319 mbhc->mbhc_cb->mbhc_micb_ramp_control(codec, true);
1320 /* enable bias */
1321 mbhc->mbhc_cb->mbhc_bias(codec, true);
1322 /* enable MBHC clock */
1323 if (mbhc->mbhc_cb->clk_setup)
1324 mbhc->mbhc_cb->clk_setup(codec, true);
1325
1326 /* program HS_VREF value */
1327 wcd_program_hs_vref(mbhc);
1328
1329 wcd_program_btn_threshold(mbhc, false);
1330
1331
1332 reinit_completion(&mbhc->btn_press_compl);
1333
1334 WCD_MBHC_RSC_UNLOCK(mbhc);
1335 pr_debug("%s: leave\n", __func__);
1336 return ret;
1337}
1338
1339static void wcd_mbhc_fw_read(struct work_struct *work)
1340{
1341 struct delayed_work *dwork;
1342 struct wcd_mbhc *mbhc;
1343 struct snd_soc_codec *codec;
1344 const struct firmware *fw;
1345 struct firmware_cal *fw_data = NULL;
1346 int ret = -1, retry = 0;
1347 bool use_default_cal = false;
1348
1349 dwork = to_delayed_work(work);
1350 mbhc = container_of(dwork, struct wcd_mbhc, mbhc_firmware_dwork);
1351 codec = mbhc->codec;
1352
1353 while (retry < FW_READ_ATTEMPTS) {
1354 retry++;
1355 pr_debug("%s:Attempt %d to request MBHC firmware\n",
1356 __func__, retry);
1357 if (mbhc->mbhc_cb->get_hwdep_fw_cal)
1358 fw_data = mbhc->mbhc_cb->get_hwdep_fw_cal(mbhc,
1359 WCD9XXX_MBHC_CAL);
1360 if (!fw_data)
1361 ret = request_firmware(&fw, "wcd9320/wcd9320_mbhc.bin",
1362 codec->dev);
1363 /*
1364 * if request_firmware and hwdep cal both fail then
1365 * sleep for 4sec for the userspace to send data to kernel
1366 * retry for few times before bailing out
1367 */
1368 if ((ret != 0) && !fw_data) {
1369 usleep_range(FW_READ_TIMEOUT, FW_READ_TIMEOUT +
1370 WCD_MBHC_USLEEP_RANGE_MARGIN_US);
1371 } else {
1372 pr_debug("%s: MBHC Firmware read successful\n",
1373 __func__);
1374 break;
1375 }
1376 }
1377 if (!fw_data)
1378 pr_debug("%s: using request_firmware\n", __func__);
1379 else
1380 pr_debug("%s: using hwdep cal\n", __func__);
1381
1382 if (ret != 0 && !fw_data) {
1383 pr_err("%s: Cannot load MBHC firmware use default cal\n",
1384 __func__);
1385 use_default_cal = true;
1386 }
1387 if (!use_default_cal) {
1388 const void *data;
1389 size_t size;
1390
1391 if (fw_data) {
1392 data = fw_data->data;
1393 size = fw_data->size;
1394 } else {
1395 data = fw->data;
1396 size = fw->size;
1397 }
1398 if (wcd_mbhc_fw_validate(data, size) == false) {
1399 pr_err("%s: Invalid MBHC cal data size use default cal\n",
1400 __func__);
1401 if (!fw_data)
1402 release_firmware(fw);
1403 } else {
1404 if (fw_data) {
1405 mbhc->mbhc_cfg->calibration =
1406 (void *)fw_data->data;
1407 mbhc->mbhc_cal = fw_data;
1408 } else {
1409 mbhc->mbhc_cfg->calibration =
1410 (void *)fw->data;
1411 mbhc->mbhc_fw = fw;
1412 }
1413 }
1414
1415 }
1416
1417 (void) wcd_mbhc_initialise(mbhc);
1418}
1419
1420static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc)
1421{
1422 enum snd_jack_types type;
1423 int i, ret, result = 0;
1424 int *btn_key_code;
1425
1426 btn_key_code = mbhc->mbhc_cfg->key_code;
1427
1428 for (i = 0 ; i < WCD_MBHC_KEYCODE_NUM ; i++) {
1429 if (btn_key_code[i] != 0) {
1430 switch (i) {
1431 case 0:
1432 type = SND_JACK_BTN_0;
1433 break;
1434 case 1:
1435 type = SND_JACK_BTN_1;
1436 break;
1437 case 2:
1438 type = SND_JACK_BTN_2;
1439 break;
1440 case 3:
1441 type = SND_JACK_BTN_3;
1442 break;
1443 case 4:
1444 type = SND_JACK_BTN_4;
1445 break;
1446 case 5:
1447 type = SND_JACK_BTN_5;
1448 break;
1449 default:
1450 WARN_ONCE(1, "Wrong button number:%d\n", i);
1451 result = -1;
1452 return result;
1453 }
1454 ret = snd_jack_set_key(mbhc->button_jack.jack,
1455 type,
1456 btn_key_code[i]);
1457 if (ret) {
1458 pr_err("%s: Failed to set code for %d\n",
1459 __func__, btn_key_code[i]);
1460 result = -1;
1461 return result;
1462 }
1463 input_set_capability(
1464 mbhc->button_jack.jack->input_dev,
1465 EV_KEY, btn_key_code[i]);
1466 pr_debug("%s: set btn%d key code:%d\n", __func__,
1467 i, btn_key_code[i]);
1468 }
1469 }
1470 if (btn_key_code[0])
1471 mbhc->is_btn_already_regd = true;
1472 return result;
1473}
1474
1475static int wcd_mbhc_usb_c_analog_setup_gpios(struct wcd_mbhc *mbhc,
1476 bool active)
1477{
1478 int rc = 0;
1479 struct usbc_ana_audio_config *config =
1480 &mbhc->mbhc_cfg->usbc_analog_cfg;
1481 union power_supply_propval pval;
1482
1483 dev_dbg(mbhc->codec->dev, "%s: setting GPIOs active = %d\n",
1484 __func__, active);
1485
1486 memset(&pval, 0, sizeof(pval));
1487
1488 if (active) {
1489 pval.intval = POWER_SUPPLY_TYPEC_PR_SOURCE;
1490 if (power_supply_set_property(mbhc->usb_psy,
1491 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &pval))
1492 dev_info(mbhc->codec->dev, "%s: force PR_SOURCE mode unsuccessful\n",
1493 __func__);
1494 else
1495 mbhc->usbc_force_pr_mode = true;
1496
1497 if (config->usbc_en1_gpio_p)
1498 rc = msm_cdc_pinctrl_select_active_state(
1499 config->usbc_en1_gpio_p);
1500 if (rc == 0 && config->usbc_force_gpio_p)
1501 rc = msm_cdc_pinctrl_select_active_state(
1502 config->usbc_force_gpio_p);
1503 mbhc->usbc_mode = POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER;
1504 } else {
1505 /* no delay is required when disabling GPIOs */
1506 if (config->usbc_en1_gpio_p)
1507 msm_cdc_pinctrl_select_sleep_state(
1508 config->usbc_en1_gpio_p);
1509 if (config->usbc_force_gpio_p)
1510 msm_cdc_pinctrl_select_sleep_state(
1511 config->usbc_force_gpio_p);
1512
1513 if (mbhc->usbc_force_pr_mode) {
1514 pval.intval = POWER_SUPPLY_TYPEC_PR_DUAL;
1515 if (power_supply_set_property(mbhc->usb_psy,
1516 POWER_SUPPLY_PROP_TYPEC_POWER_ROLE, &pval))
1517 dev_info(mbhc->codec->dev, "%s: force PR_DUAL mode unsuccessful\n",
1518 __func__);
1519
1520 mbhc->usbc_force_pr_mode = false;
1521 }
1522
1523 mbhc->usbc_mode = POWER_SUPPLY_TYPEC_NONE;
1524 if (mbhc->mbhc_cfg->swap_gnd_mic)
1525 mbhc->mbhc_cfg->swap_gnd_mic(mbhc->codec, false);
1526 }
1527
1528 return rc;
1529}
1530
1531/* workqueue */
1532static void wcd_mbhc_usbc_analog_work_fn(struct work_struct *work)
1533{
1534 struct wcd_mbhc *mbhc =
1535 container_of(work, struct wcd_mbhc, usbc_analog_work);
1536
1537 wcd_mbhc_usb_c_analog_setup_gpios(mbhc,
1538 mbhc->usbc_mode != POWER_SUPPLY_TYPEC_NONE);
1539}
1540
1541/* this callback function is used to process PMI notification */
1542static int wcd_mbhc_usb_c_event_changed(struct notifier_block *nb,
1543 unsigned long evt, void *ptr)
1544{
1545 int ret;
1546 union power_supply_propval mode;
1547 struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, psy_nb);
1548 struct snd_soc_codec *codec = mbhc->codec;
1549
1550 if (ptr != mbhc->usb_psy || evt != PSY_EVENT_PROP_CHANGED)
1551 return 0;
1552
1553 ret = power_supply_get_property(mbhc->usb_psy,
1554 POWER_SUPPLY_PROP_TYPEC_MODE, &mode);
1555 if (ret) {
1556 dev_err(codec->dev, "%s: Unable to read USB TYPEC_MODE: %d\n",
1557 __func__, ret);
1558 return ret;
1559 }
1560
1561 dev_dbg(codec->dev, "%s: USB change event received\n",
1562 __func__);
1563 dev_dbg(codec->dev, "%s: supply mode %d, expected %d\n", __func__,
1564 mode.intval, POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER);
1565
1566 switch (mode.intval) {
1567 case POWER_SUPPLY_TYPEC_SINK_AUDIO_ADAPTER:
1568 case POWER_SUPPLY_TYPEC_NONE:
1569 dev_dbg(codec->dev, "%s: usbc_mode: %d; mode.intval: %d\n",
1570 __func__, mbhc->usbc_mode, mode.intval);
1571
1572 if (mbhc->usbc_mode == mode.intval)
1573 break; /* filter notifications received before */
1574 mbhc->usbc_mode = mode.intval;
1575
1576 dev_dbg(codec->dev, "%s: queueing usbc_analog_work\n",
1577 __func__);
1578 schedule_work(&mbhc->usbc_analog_work);
1579 break;
1580 default:
1581 break;
1582 }
1583 return ret;
1584}
1585
1586/* PMI registration code */
1587static int wcd_mbhc_usb_c_analog_init(struct wcd_mbhc *mbhc)
1588{
1589 int ret = 0;
1590 struct snd_soc_codec *codec = mbhc->codec;
1591
1592 dev_dbg(mbhc->codec->dev, "%s: usb-c analog setup start\n", __func__);
1593 INIT_WORK(&mbhc->usbc_analog_work, wcd_mbhc_usbc_analog_work_fn);
1594
1595 mbhc->usb_psy = power_supply_get_by_name("usb");
1596 if (IS_ERR_OR_NULL(mbhc->usb_psy)) {
1597 dev_err(codec->dev, "%s: could not get USB psy info\n",
1598 __func__);
1599 ret = -EPROBE_DEFER;
1600 if (IS_ERR(mbhc->usb_psy))
1601 ret = PTR_ERR(mbhc->usb_psy);
1602 mbhc->usb_psy = NULL;
1603 goto err;
1604 }
1605
1606 ret = wcd_mbhc_usb_c_analog_setup_gpios(mbhc, false);
1607 if (ret) {
1608 dev_err(codec->dev, "%s: error while setting USBC ana gpios\n",
1609 __func__);
1610 goto err;
1611 }
1612
1613 mbhc->psy_nb.notifier_call = wcd_mbhc_usb_c_event_changed;
1614 mbhc->psy_nb.priority = 0;
1615 ret = power_supply_reg_notifier(&mbhc->psy_nb);
1616 if (ret) {
1617 dev_err(codec->dev, "%s: power supply registration failed\n",
1618 __func__);
1619 goto err;
1620 }
1621
1622 /*
1623 * as part of the init sequence check if there is a connected
1624 * USB C analog adapter
1625 */
1626 dev_dbg(mbhc->codec->dev, "%s: verify if USB adapter is already inserted\n",
1627 __func__);
1628 ret = wcd_mbhc_usb_c_event_changed(&mbhc->psy_nb,
1629 PSY_EVENT_PROP_CHANGED,
1630 mbhc->usb_psy);
1631
1632err:
1633 return ret;
1634}
1635
1636static int wcd_mbhc_usb_c_analog_deinit(struct wcd_mbhc *mbhc)
1637{
1638 wcd_mbhc_usb_c_analog_setup_gpios(mbhc, false);
1639
1640 /* deregister from PMI */
1641 power_supply_unreg_notifier(&mbhc->psy_nb);
1642
1643 return 0;
1644}
1645
1646static int wcd_mbhc_init_gpio(struct wcd_mbhc *mbhc,
1647 struct wcd_mbhc_config *mbhc_cfg,
1648 const char *gpio_dt_str,
1649 int *gpio, struct device_node **gpio_dn)
1650{
1651 int rc = 0;
1652 struct snd_soc_codec *codec = mbhc->codec;
1653 struct snd_soc_card *card = codec->component.card;
1654
1655 dev_dbg(mbhc->codec->dev, "%s: gpio %s\n", __func__, gpio_dt_str);
1656
1657 *gpio_dn = of_parse_phandle(card->dev->of_node, gpio_dt_str, 0);
1658
1659 if (!(*gpio_dn)) {
1660 *gpio = of_get_named_gpio(card->dev->of_node, gpio_dt_str, 0);
1661 if (!gpio_is_valid(*gpio)) {
1662 dev_err(card->dev, "%s, property %s not in node %s",
1663 __func__, gpio_dt_str,
1664 card->dev->of_node->full_name);
1665 rc = -EINVAL;
1666 }
1667 }
1668
1669 return rc;
1670}
1671
1672int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *mbhc_cfg)
1673{
1674 int rc = 0;
1675 struct usbc_ana_audio_config *config;
1676 struct snd_soc_codec *codec;
1677 struct snd_soc_card *card;
1678 const char *usb_c_dt = "qcom,msm-mbhc-usbc-audio-supported";
1679
1680 if (!mbhc || !mbhc_cfg)
1681 return -EINVAL;
1682
1683 config = &mbhc_cfg->usbc_analog_cfg;
1684 codec = mbhc->codec;
1685 card = codec->component.card;
1686
1687 /* update the mbhc config */
1688 mbhc->mbhc_cfg = mbhc_cfg;
1689
1690 dev_dbg(mbhc->codec->dev, "%s: enter\n", __func__);
1691
1692 /* check if USB C analog is defined on device tree */
1693 mbhc_cfg->enable_usbc_analog = 0;
1694 if (of_find_property(card->dev->of_node, usb_c_dt, NULL)) {
1695 rc = of_property_read_u32(card->dev->of_node, usb_c_dt,
1696 &mbhc_cfg->enable_usbc_analog);
1697 }
1698 if (mbhc_cfg->enable_usbc_analog == 0 || rc != 0) {
1699 dev_info(card->dev,
1700 "%s: %s in dt node is missing or false\n",
1701 __func__, usb_c_dt);
1702 dev_info(card->dev,
1703 "%s: skipping USB c analog configuration\n", __func__);
1704 }
1705
1706 /* initialize GPIOs */
1707 if (mbhc_cfg->enable_usbc_analog) {
1708 dev_dbg(mbhc->codec->dev, "%s: usbc analog enabled\n",
1709 __func__);
1710 rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
1711 "qcom,usbc-analog-en1-gpio",
1712 &config->usbc_en1_gpio,
1713 &config->usbc_en1_gpio_p);
1714 if (rc)
1715 goto err;
1716
1717 if (of_find_property(card->dev->of_node,
1718 "qcom,usbc-analog-force_detect_gpio",
1719 NULL)) {
1720 rc = wcd_mbhc_init_gpio(mbhc, mbhc_cfg,
1721 "qcom,usbc-analog-force_detect_gpio",
1722 &config->usbc_force_gpio,
1723 &config->usbc_force_gpio_p);
1724 if (rc)
1725 goto err;
1726 }
1727
1728 dev_dbg(mbhc->codec->dev, "%s: calling usb_c_analog_init\n",
1729 __func__);
1730 /* init PMI notifier */
1731 rc = wcd_mbhc_usb_c_analog_init(mbhc);
1732 if (rc) {
1733 rc = EPROBE_DEFER;
1734 goto err;
1735 }
1736 }
1737
1738 /* Set btn key code */
1739 if ((!mbhc->is_btn_already_regd) && wcd_mbhc_set_keycode(mbhc))
1740 pr_err("Set btn key code error!!!\n");
1741
1742 if (!mbhc->mbhc_cfg->read_fw_bin ||
1743 (mbhc->mbhc_cfg->read_fw_bin && mbhc->mbhc_fw) ||
1744 (mbhc->mbhc_cfg->read_fw_bin && mbhc->mbhc_cal)) {
1745 rc = wcd_mbhc_initialise(mbhc);
1746 } else {
1747 if (!mbhc->mbhc_fw || !mbhc->mbhc_cal)
1748 schedule_delayed_work(&mbhc->mbhc_firmware_dwork,
1749 usecs_to_jiffies(FW_READ_TIMEOUT));
1750 else
1751 pr_err("%s: Skipping to read mbhc fw, 0x%pK %pK\n",
1752 __func__, mbhc->mbhc_fw, mbhc->mbhc_cal);
1753 }
1754
1755 return rc;
1756err:
1757 if (config->usbc_en1_gpio > 0) {
1758 dev_dbg(card->dev, "%s free usb en1 gpio %d\n",
1759 __func__, config->usbc_en1_gpio);
1760 gpio_free(config->usbc_en1_gpio);
1761 config->usbc_en1_gpio = 0;
1762 }
1763 if (config->usbc_force_gpio > 0) {
1764 dev_dbg(card->dev, "%s free usb_force gpio %d\n",
1765 __func__, config->usbc_force_gpio);
1766 gpio_free(config->usbc_force_gpio);
1767 config->usbc_force_gpio = 0;
1768 }
1769 if (config->usbc_en1_gpio_p)
1770 of_node_put(config->usbc_en1_gpio_p);
1771 if (config->usbc_force_gpio_p)
1772 of_node_put(config->usbc_force_gpio_p);
1773 dev_dbg(mbhc->codec->dev, "%s: leave %d\n", __func__, rc);
1774 return rc;
1775}
1776EXPORT_SYMBOL(wcd_mbhc_start);
1777
1778void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
1779{
1780 struct usbc_ana_audio_config *config = &mbhc->mbhc_cfg->usbc_analog_cfg;
1781
1782 pr_debug("%s: enter\n", __func__);
1783
1784 if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE) {
1785 if (mbhc->mbhc_cb && mbhc->mbhc_cb->skip_imped_detect)
1786 mbhc->mbhc_cb->skip_imped_detect(mbhc->codec);
1787 }
1788 mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
1789 mbhc->hph_status = 0;
1790 if (mbhc->mbhc_cb && mbhc->mbhc_cb->irq_control) {
1791 mbhc->mbhc_cb->irq_control(mbhc->codec,
1792 mbhc->intr_ids->hph_left_ocp,
1793 false);
1794 mbhc->mbhc_cb->irq_control(mbhc->codec,
1795 mbhc->intr_ids->hph_right_ocp,
1796 false);
1797 }
1798 if (mbhc->mbhc_fw || mbhc->mbhc_cal) {
1799 cancel_delayed_work_sync(&mbhc->mbhc_firmware_dwork);
1800 if (!mbhc->mbhc_cal)
1801 release_firmware(mbhc->mbhc_fw);
1802 mbhc->mbhc_fw = NULL;
1803 mbhc->mbhc_cal = NULL;
1804 }
1805
1806 if (mbhc->mbhc_cfg->enable_usbc_analog) {
1807 wcd_mbhc_usb_c_analog_deinit(mbhc);
1808 /* free GPIOs */
1809 if (config->usbc_en1_gpio > 0)
1810 gpio_free(config->usbc_en1_gpio);
1811 if (config->usbc_force_gpio)
1812 gpio_free(config->usbc_force_gpio);
1813
1814 if (config->usbc_en1_gpio_p)
1815 of_node_put(config->usbc_en1_gpio_p);
1816 if (config->usbc_force_gpio_p)
1817 of_node_put(config->usbc_force_gpio_p);
1818 }
1819
1820 pr_debug("%s: leave\n", __func__);
1821}
1822EXPORT_SYMBOL(wcd_mbhc_stop);
1823
1824/*
1825 * wcd_mbhc_init : initialize MBHC internal structures.
1826 *
1827 * NOTE: mbhc->mbhc_cfg is not YET configure so shouldn't be used
1828 */
1829int wcd_mbhc_init(struct wcd_mbhc *mbhc, struct snd_soc_codec *codec,
1830 const struct wcd_mbhc_cb *mbhc_cb,
1831 const struct wcd_mbhc_intr *mbhc_cdc_intr_ids,
1832 struct wcd_mbhc_register *wcd_mbhc_regs,
1833 bool impedance_det_en)
1834{
1835 int ret = 0;
1836 int hph_swh = 0;
1837 int gnd_swh = 0;
1838 u32 hph_moist_config[3];
1839 struct snd_soc_card *card = codec->component.card;
1840 const char *hph_switch = "qcom,msm-mbhc-hphl-swh";
1841 const char *gnd_switch = "qcom,msm-mbhc-gnd-swh";
Meng Wang4d6a6be2017-09-15 10:35:44 +08001842 const char *hs_thre = "qcom,msm-mbhc-hs-mic-max-threshold-mv";
1843 const char *hph_thre = "qcom,msm-mbhc-hs-mic-min-threshold-mv";
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301844
1845 pr_debug("%s: enter\n", __func__);
1846
1847 ret = of_property_read_u32(card->dev->of_node, hph_switch, &hph_swh);
1848 if (ret) {
1849 dev_err(card->dev,
1850 "%s: missing %s in dt node\n", __func__, hph_switch);
1851 goto err;
1852 }
1853
1854 ret = of_property_read_u32(card->dev->of_node, gnd_switch, &gnd_swh);
1855 if (ret) {
1856 dev_err(card->dev,
1857 "%s: missing %s in dt node\n", __func__, gnd_switch);
1858 goto err;
1859 }
1860
Meng Wang4d6a6be2017-09-15 10:35:44 +08001861 ret = of_property_read_u32(card->dev->of_node, hs_thre,
1862 &(mbhc->hs_thr));
1863 if (ret)
1864 dev_dbg(card->dev,
1865 "%s: missing %s in dt node\n", __func__, hs_thre);
1866
1867 ret = of_property_read_u32(card->dev->of_node, hph_thre,
1868 &(mbhc->hph_thr));
1869 if (ret)
1870 dev_dbg(card->dev,
1871 "%s: missing %s in dt node\n", __func__, hph_thre);
1872
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301873 ret = of_property_read_u32_array(card->dev->of_node,
1874 "qcom,msm-mbhc-moist-cfg",
1875 hph_moist_config, 3);
1876 if (ret) {
1877 dev_dbg(card->dev, "%s: no qcom,msm-mbhc-moist-cfg in DT\n",
1878 __func__);
1879 mbhc->moist_vref = V_45_MV;
1880 mbhc->moist_iref = I_3P0_UA;
1881 mbhc->moist_rref = R_24_KOHM;
1882 } else {
1883 mbhc->moist_vref = hph_moist_config[0];
1884 mbhc->moist_iref = hph_moist_config[1];
1885 mbhc->moist_rref = hph_moist_config[2];
1886 }
1887
1888 mbhc->in_swch_irq_handler = false;
1889 mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
1890 mbhc->is_btn_press = false;
1891 mbhc->codec = codec;
1892 mbhc->intr_ids = mbhc_cdc_intr_ids;
1893 mbhc->impedance_detect = impedance_det_en;
1894 mbhc->hphl_swh = hph_swh;
1895 mbhc->gnd_swh = gnd_swh;
1896 mbhc->micbias_enable = false;
1897 mbhc->mbhc_cb = mbhc_cb;
1898 mbhc->btn_press_intr = false;
1899 mbhc->is_hs_recording = false;
1900 mbhc->is_extn_cable = false;
1901 mbhc->extn_cable_hph_rem = false;
1902 mbhc->hph_type = WCD_MBHC_HPH_NONE;
1903 mbhc->wcd_mbhc_regs = wcd_mbhc_regs;
1904
1905 if (mbhc->intr_ids == NULL) {
1906 pr_err("%s: Interrupt mapping not provided\n", __func__);
1907 return -EINVAL;
1908 }
1909 if (!mbhc->wcd_mbhc_regs) {
1910 dev_err(codec->dev, "%s: mbhc registers are not defined\n",
1911 __func__);
1912 return -EINVAL;
1913 }
1914
1915 /* Check if IRQ and other required callbacks are defined or not */
1916 if (!mbhc_cb || !mbhc_cb->request_irq || !mbhc_cb->irq_control ||
1917 !mbhc_cb->free_irq || !mbhc_cb->map_btn_code_to_num ||
1918 !mbhc_cb->lock_sleep || !mbhc_cb->mbhc_bias ||
1919 !mbhc_cb->set_btn_thr) {
1920 dev_err(codec->dev, "%s: required mbhc callbacks are not defined\n",
1921 __func__);
1922 return -EINVAL;
1923 }
1924
1925 /* No need to create new sound card jacks if is is already created */
1926 if (mbhc->headset_jack.jack == NULL) {
1927 ret = snd_soc_card_jack_new(codec->component.card,
1928 "Headset Jack", WCD_MBHC_JACK_MASK,
1929 &mbhc->headset_jack, NULL, 0);
1930 if (ret) {
1931 pr_err("%s: Failed to create new jack\n", __func__);
1932 return ret;
1933 }
1934
1935 ret = snd_soc_card_jack_new(codec->component.card,
1936 "Button Jack",
1937 WCD_MBHC_JACK_BUTTON_MASK,
1938 &mbhc->button_jack, NULL, 0);
1939 if (ret) {
1940 pr_err("Failed to create new jack\n");
1941 return ret;
1942 }
1943
1944 ret = snd_jack_set_key(mbhc->button_jack.jack,
1945 SND_JACK_BTN_0,
1946 KEY_MEDIA);
1947 if (ret) {
1948 pr_err("%s: Failed to set code for btn-0\n",
1949 __func__);
1950 return ret;
1951 }
1952
1953 INIT_DELAYED_WORK(&mbhc->mbhc_firmware_dwork,
1954 wcd_mbhc_fw_read);
1955 INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_lpress_fn);
1956 }
1957 mutex_init(&mbhc->hphl_pa_lock);
1958 mutex_init(&mbhc->hphr_pa_lock);
1959 init_completion(&mbhc->btn_press_compl);
1960
1961 /* Register event notifier */
1962 mbhc->nblock.notifier_call = wcd_event_notify;
1963 if (mbhc->mbhc_cb->register_notifier) {
1964 ret = mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock,
1965 true);
1966 if (ret) {
1967 pr_err("%s: Failed to register notifier %d\n",
1968 __func__, ret);
1969 return ret;
1970 }
1971 }
1972
1973 init_waitqueue_head(&mbhc->wait_btn_press);
1974 mutex_init(&mbhc->codec_resource_lock);
1975
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301976 switch (mbhc->mbhc_detection_logic) {
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301977 case WCD_DETECTION_LEGACY:
1978 wcd_mbhc_legacy_init(mbhc);
1979 break;
1980 case WCD_DETECTION_ADC:
1981 wcd_mbhc_adc_init(mbhc);
1982 break;
1983 default:
1984 pr_err("%s: Unknown detection logic type %d\n",
Asish Bhattacharya84f7f732017-07-25 16:29:27 +05301985 __func__, mbhc->mbhc_detection_logic);
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05301986 break;
1987 }
1988
1989 if (!mbhc->mbhc_fn ||
1990 !mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq ||
1991 !mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq ||
1992 !mbhc->mbhc_fn->wcd_mbhc_detect_plug_type ||
1993 !mbhc->mbhc_fn->wcd_cancel_hs_detect_plug) {
1994 pr_err("%s: mbhc function pointer is NULL\n", __func__);
1995 goto err_mbhc_sw_irq;
1996 }
1997 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->mbhc_sw_intr,
1998 wcd_mbhc_mech_plug_detect_irq,
1999 "mbhc sw intr", mbhc);
2000 if (ret) {
2001 pr_err("%s: Failed to request irq %d, ret = %d\n", __func__,
2002 mbhc->intr_ids->mbhc_sw_intr, ret);
2003 goto err_mbhc_sw_irq;
2004 }
2005
2006 ret = mbhc->mbhc_cb->request_irq(codec,
2007 mbhc->intr_ids->mbhc_btn_press_intr,
2008 wcd_mbhc_btn_press_handler,
2009 "Button Press detect", mbhc);
2010 if (ret) {
2011 pr_err("%s: Failed to request irq %d\n", __func__,
2012 mbhc->intr_ids->mbhc_btn_press_intr);
2013 goto err_btn_press_irq;
2014 }
2015
2016 ret = mbhc->mbhc_cb->request_irq(codec,
2017 mbhc->intr_ids->mbhc_btn_release_intr,
2018 wcd_mbhc_release_handler,
2019 "Button Release detect", mbhc);
2020 if (ret) {
2021 pr_err("%s: Failed to request irq %d\n", __func__,
2022 mbhc->intr_ids->mbhc_btn_release_intr);
2023 goto err_btn_release_irq;
2024 }
2025
2026 ret = mbhc->mbhc_cb->request_irq(codec,
2027 mbhc->intr_ids->mbhc_hs_ins_intr,
2028 mbhc->mbhc_fn->wcd_mbhc_hs_ins_irq,
2029 "Elect Insert", mbhc);
2030 if (ret) {
2031 pr_err("%s: Failed to request irq %d\n", __func__,
2032 mbhc->intr_ids->mbhc_hs_ins_intr);
2033 goto err_mbhc_hs_ins_irq;
2034 }
2035 mbhc->mbhc_cb->irq_control(codec, mbhc->intr_ids->mbhc_hs_ins_intr,
2036 false);
2037 clear_bit(WCD_MBHC_ELEC_HS_INS, &mbhc->intr_status);
2038
2039 ret = mbhc->mbhc_cb->request_irq(codec,
2040 mbhc->intr_ids->mbhc_hs_rem_intr,
2041 mbhc->mbhc_fn->wcd_mbhc_hs_rem_irq,
2042 "Elect Remove", mbhc);
2043 if (ret) {
2044 pr_err("%s: Failed to request irq %d\n", __func__,
2045 mbhc->intr_ids->mbhc_hs_rem_intr);
2046 goto err_mbhc_hs_rem_irq;
2047 }
2048 mbhc->mbhc_cb->irq_control(codec, mbhc->intr_ids->mbhc_hs_rem_intr,
2049 false);
2050 clear_bit(WCD_MBHC_ELEC_HS_REM, &mbhc->intr_status);
2051
2052 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->hph_left_ocp,
2053 wcd_mbhc_hphl_ocp_irq, "HPH_L OCP detect",
2054 mbhc);
2055 if (ret) {
2056 pr_err("%s: Failed to request irq %d\n", __func__,
2057 mbhc->intr_ids->hph_left_ocp);
2058 goto err_hphl_ocp_irq;
2059 }
2060
2061 ret = mbhc->mbhc_cb->request_irq(codec, mbhc->intr_ids->hph_right_ocp,
2062 wcd_mbhc_hphr_ocp_irq, "HPH_R OCP detect",
2063 mbhc);
2064 if (ret) {
2065 pr_err("%s: Failed to request irq %d\n", __func__,
2066 mbhc->intr_ids->hph_right_ocp);
2067 goto err_hphr_ocp_irq;
2068 }
2069
2070 pr_debug("%s: leave ret %d\n", __func__, ret);
2071 return ret;
2072
2073err_hphr_ocp_irq:
2074 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_left_ocp, mbhc);
2075err_hphl_ocp_irq:
2076 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
2077err_mbhc_hs_rem_irq:
2078 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
2079err_mbhc_hs_ins_irq:
2080 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_release_intr,
2081 mbhc);
2082err_btn_release_irq:
2083 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_press_intr,
2084 mbhc);
2085err_btn_press_irq:
2086 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_sw_intr, mbhc);
2087err_mbhc_sw_irq:
2088 if (mbhc->mbhc_cb->register_notifier)
2089 mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock, false);
2090 mutex_destroy(&mbhc->codec_resource_lock);
2091err:
2092 pr_debug("%s: leave ret %d\n", __func__, ret);
2093 return ret;
2094}
2095EXPORT_SYMBOL(wcd_mbhc_init);
2096
2097void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
2098{
2099 struct snd_soc_codec *codec = mbhc->codec;
2100
2101 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_sw_intr, mbhc);
2102 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_press_intr,
2103 mbhc);
2104 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_btn_release_intr,
2105 mbhc);
2106 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_ins_intr, mbhc);
2107 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->mbhc_hs_rem_intr, mbhc);
2108 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_left_ocp, mbhc);
2109 mbhc->mbhc_cb->free_irq(codec, mbhc->intr_ids->hph_right_ocp, mbhc);
2110 if (mbhc->mbhc_cb && mbhc->mbhc_cb->register_notifier)
2111 mbhc->mbhc_cb->register_notifier(mbhc, &mbhc->nblock, false);
2112 if (mbhc->mbhc_fn->wcd_cancel_hs_detect_plug) {
2113 WCD_MBHC_RSC_LOCK(mbhc);
2114 mbhc->mbhc_fn->wcd_cancel_hs_detect_plug(mbhc,
2115 &mbhc->correct_plug_swch);
2116 WCD_MBHC_RSC_UNLOCK(mbhc);
2117 }
2118 mutex_destroy(&mbhc->codec_resource_lock);
2119 mutex_destroy(&mbhc->hphl_pa_lock);
2120 mutex_destroy(&mbhc->hphr_pa_lock);
2121}
2122EXPORT_SYMBOL(wcd_mbhc_deinit);
2123
Laxminath Kasam8b1366a2017-10-05 01:44:16 +05302124static int __init mbhc_init(void)
2125{
2126 return 0;
2127}
2128
2129static void __exit mbhc_exit(void)
2130{
2131}
2132
2133module_init(mbhc_init);
2134module_exit(mbhc_exit);
2135
Asish Bhattacharya8e2277f2017-07-20 18:31:55 +05302136MODULE_DESCRIPTION("wcd MBHC v2 module");
2137MODULE_LICENSE("GPL v2");