ASoC: codecs: MBHC: Add support for special headset
[platform/kernel/linux-starfive.git] / sound / soc / codecs / wcd-mbhc-v2.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
3
4 #include <linux/module.h>
5 #include <linux/init.h>
6 #include <linux/slab.h>
7 #include <linux/device.h>
8 #include <linux/printk.h>
9 #include <linux/delay.h>
10 #include <linux/kernel.h>
11 #include <sound/soc.h>
12 #include <sound/jack.h>
13 #include "wcd-mbhc-v2.h"
14
15 #define HS_DETECT_PLUG_TIME_MS          (3 * 1000)
16 #define MBHC_BUTTON_PRESS_THRESHOLD_MIN 250
17 #define GND_MIC_SWAP_THRESHOLD          4
18 #define WCD_FAKE_REMOVAL_MIN_PERIOD_MS  100
19 #define HPHL_CROSS_CONN_THRESHOLD       100
20 #define HS_VREF_MIN_VAL                 1400
21 #define FAKE_REM_RETRY_ATTEMPTS         3
22 #define WCD_MBHC_ADC_HS_THRESHOLD_MV    1700
23 #define WCD_MBHC_ADC_HPH_THRESHOLD_MV   75
24 #define WCD_MBHC_ADC_MICBIAS_MV         1800
25 #define WCD_MBHC_FAKE_INS_RETRY         4
26
27 #define WCD_MBHC_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | \
28                            SND_JACK_MECHANICAL)
29
30 #define WCD_MBHC_JACK_BUTTON_MASK (SND_JACK_BTN_0 | SND_JACK_BTN_1 | \
31                                   SND_JACK_BTN_2 | SND_JACK_BTN_3 | \
32                                   SND_JACK_BTN_4 | SND_JACK_BTN_5)
33
34 enum wcd_mbhc_adc_mux_ctl {
35         MUX_CTL_AUTO = 0,
36         MUX_CTL_IN2P,
37         MUX_CTL_IN3P,
38         MUX_CTL_IN4P,
39         MUX_CTL_HPH_L,
40         MUX_CTL_HPH_R,
41         MUX_CTL_NONE,
42 };
43
44 struct wcd_mbhc {
45         struct device *dev;
46         struct snd_soc_component *component;
47         struct snd_soc_jack *jack;
48         struct wcd_mbhc_config *cfg;
49         const struct wcd_mbhc_cb *mbhc_cb;
50         const struct wcd_mbhc_intr *intr_ids;
51         struct wcd_mbhc_field *fields;
52         /* Delayed work to report long button press */
53         struct delayed_work mbhc_btn_dwork;
54         /* Work to correct accessory type */
55         struct work_struct correct_plug_swch;
56         struct mutex lock;
57         int buttons_pressed;
58         u32 hph_status; /* track headhpone status */
59         u8 current_plug;
60         bool is_btn_press;
61         bool in_swch_irq_handler;
62         bool hs_detect_work_stop;
63         bool is_hs_recording;
64         bool extn_cable_hph_rem;
65         bool force_linein;
66         bool impedance_detect;
67         unsigned long event_state;
68         unsigned long jiffies_atreport;
69         /* impedance of hphl and hphr */
70         uint32_t zl, zr;
71         /* Holds type of Headset - Mono/Stereo */
72         enum wcd_mbhc_hph_type hph_type;
73         /* Holds mbhc detection method - ADC/Legacy */
74         int mbhc_detection_logic;
75 };
76
77 static inline int wcd_mbhc_write_field(const struct wcd_mbhc *mbhc,
78                                        int field, int val)
79 {
80         if (!mbhc->fields[field].reg)
81                 return 0;
82
83         return snd_soc_component_write_field(mbhc->component,
84                                              mbhc->fields[field].reg,
85                                              mbhc->fields[field].mask, val);
86 }
87
88 static inline int wcd_mbhc_read_field(const struct wcd_mbhc *mbhc, int field)
89 {
90         if (!mbhc->fields[field].reg)
91                 return 0;
92
93         return snd_soc_component_read_field(mbhc->component,
94                                             mbhc->fields[field].reg,
95                                             mbhc->fields[field].mask);
96 }
97
98 static void wcd_program_hs_vref(struct wcd_mbhc *mbhc)
99 {
100         u32 reg_val = ((mbhc->cfg->v_hs_max - HS_VREF_MIN_VAL) / 100);
101
102         wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_VREF, reg_val);
103 }
104
105 static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias)
106 {
107         struct snd_soc_component *component = mbhc->component;
108
109         mbhc->mbhc_cb->set_btn_thr(component, mbhc->cfg->btn_low,
110                                    mbhc->cfg->btn_high,
111                                    mbhc->cfg->num_btn, micbias);
112 }
113
114 static void wcd_mbhc_curr_micbias_control(const struct wcd_mbhc *mbhc,
115                                           const enum wcd_mbhc_cs_mb_en_flag cs_mb_en)
116 {
117
118         /*
119          * Some codecs handle micbias/pullup enablement in codec
120          * drivers itself and micbias is not needed for regular
121          * plug type detection. So if micbias_control callback function
122          * is defined, just return.
123          */
124         if (mbhc->mbhc_cb->mbhc_micbias_control)
125                 return;
126
127         switch (cs_mb_en) {
128         case WCD_MBHC_EN_CS:
129                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
130                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
131                 /* Program Button threshold registers as per CS */
132                 wcd_program_btn_threshold(mbhc, false);
133                 break;
134         case WCD_MBHC_EN_MB:
135                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
136                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
137                 /* Disable PULL_UP_EN & enable MICBIAS */
138                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 2);
139                 /* Program Button threshold registers as per MICBIAS */
140                 wcd_program_btn_threshold(mbhc, true);
141                 break;
142         case WCD_MBHC_EN_PULLUP:
143                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
144                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
145                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 1);
146                 /* Program Button threshold registers as per MICBIAS */
147                 wcd_program_btn_threshold(mbhc, true);
148                 break;
149         case WCD_MBHC_EN_NONE:
150                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
151                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
152                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
153                 break;
154         default:
155                 dev_err(mbhc->dev, "%s: Invalid parameter", __func__);
156                 break;
157         }
158 }
159
160 int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event)
161 {
162
163         struct snd_soc_component *component;
164         bool micbias2 = false;
165
166         if (!mbhc)
167                 return 0;
168
169         component = mbhc->component;
170
171         if (mbhc->mbhc_cb->micbias_enable_status)
172                 micbias2 = mbhc->mbhc_cb->micbias_enable_status(component, MIC_BIAS_2);
173
174         switch (event) {
175         /* MICBIAS usage change */
176         case WCD_EVENT_POST_DAPM_MICBIAS_2_ON:
177                 mbhc->is_hs_recording = true;
178                 break;
179         case WCD_EVENT_POST_MICBIAS_2_ON:
180                 /* Disable current source if micbias2 enabled */
181                 if (mbhc->mbhc_cb->mbhc_micbias_control) {
182                         if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
183                                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
184                 } else {
185                         mbhc->is_hs_recording = true;
186                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
187                 }
188                 break;
189         case WCD_EVENT_PRE_MICBIAS_2_OFF:
190                 /*
191                  * Before MICBIAS_2 is turned off, if FSM is enabled,
192                  * make sure current source is enabled so as to detect
193                  * button press/release events
194                  */
195                 if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) {
196                         if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN))
197                                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
198                 }
199                 break;
200         /* MICBIAS usage change */
201         case WCD_EVENT_POST_DAPM_MICBIAS_2_OFF:
202                 mbhc->is_hs_recording = false;
203                 break;
204         case WCD_EVENT_POST_MICBIAS_2_OFF:
205                 if (!mbhc->mbhc_cb->mbhc_micbias_control)
206                         mbhc->is_hs_recording = false;
207
208                 /* Enable PULL UP if PA's are enabled */
209                 if ((test_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state)) ||
210                     (test_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state)))
211                         /* enable pullup and cs, disable mb */
212                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
213                 else
214                         /* enable current source and disable mb, pullup*/
215                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
216
217                 break;
218         case WCD_EVENT_POST_HPHL_PA_OFF:
219                 clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
220
221                 /* check if micbias is enabled */
222                 if (micbias2)
223                         /* Disable cs, pullup & enable micbias */
224                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
225                 else
226                         /* Disable micbias, pullup & enable cs */
227                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
228                 break;
229         case WCD_EVENT_POST_HPHR_PA_OFF:
230                 clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
231                 /* check if micbias is enabled */
232                 if (micbias2)
233                         /* Disable cs, pullup & enable micbias */
234                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
235                 else
236                         /* Disable micbias, pullup & enable cs */
237                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS);
238                 break;
239         case WCD_EVENT_PRE_HPHL_PA_ON:
240                 set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state);
241                 /* check if micbias is enabled */
242                 if (micbias2)
243                         /* Disable cs, pullup & enable micbias */
244                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
245                 else
246                         /* Disable micbias, enable pullup & cs */
247                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
248                 break;
249         case WCD_EVENT_PRE_HPHR_PA_ON:
250                 set_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state);
251                 /* check if micbias is enabled */
252                 if (micbias2)
253                         /* Disable cs, pullup & enable micbias */
254                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB);
255                 else
256                         /* Disable micbias, enable pullup & cs */
257                         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP);
258                 break;
259         default:
260                 break;
261         }
262         return 0;
263 }
264 EXPORT_SYMBOL_GPL(wcd_mbhc_event_notify);
265
266 static int wcd_cancel_btn_work(struct wcd_mbhc *mbhc)
267 {
268         return cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork);
269 }
270
271 static void wcd_micbias_disable(struct wcd_mbhc *mbhc)
272 {
273         struct snd_soc_component *component = mbhc->component;
274
275         if (mbhc->mbhc_cb->mbhc_micbias_control)
276                 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
277
278         if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
279                 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false);
280
281         if (mbhc->mbhc_cb->set_micbias_value) {
282                 mbhc->mbhc_cb->set_micbias_value(component);
283                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0);
284         }
285 }
286
287 static void wcd_mbhc_report_plug_removal(struct wcd_mbhc *mbhc,
288                                          enum snd_jack_types jack_type)
289 {
290         mbhc->hph_status &= ~jack_type;
291         /*
292          * cancel possibly scheduled btn work and
293          * report release if we reported button press
294          */
295         if (!wcd_cancel_btn_work(mbhc) && mbhc->buttons_pressed) {
296                 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
297                 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
298         }
299
300         wcd_micbias_disable(mbhc);
301         mbhc->hph_type = WCD_MBHC_HPH_NONE;
302         mbhc->zl = mbhc->zr = 0;
303         snd_soc_jack_report(mbhc->jack, mbhc->hph_status, WCD_MBHC_JACK_MASK);
304         mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
305         mbhc->force_linein = false;
306 }
307
308 static void wcd_mbhc_compute_impedance(struct wcd_mbhc *mbhc)
309 {
310
311         if (!mbhc->impedance_detect)
312                 return;
313
314         if (mbhc->cfg->linein_th != 0) {
315                 u8 fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN);
316                 /* Set MUX_CTL to AUTO for Z-det */
317
318                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
319                 wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
320                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
321                 mbhc->mbhc_cb->compute_impedance(mbhc->component, &mbhc->zl, &mbhc->zr);
322                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en);
323         }
324 }
325
326 static void wcd_mbhc_report_plug_insertion(struct wcd_mbhc *mbhc,
327                                            enum snd_jack_types jack_type)
328 {
329         bool is_pa_on;
330         /*
331          * Report removal of current jack type.
332          * Headphone to headset shouldn't report headphone
333          * removal.
334          */
335         if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET &&
336             jack_type == SND_JACK_HEADPHONE)
337                 mbhc->hph_status &= ~SND_JACK_HEADSET;
338
339         /* Report insertion */
340         switch (jack_type) {
341         case SND_JACK_HEADPHONE:
342                 mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE;
343                 break;
344         case SND_JACK_HEADSET:
345                 mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET;
346                 mbhc->jiffies_atreport = jiffies;
347                 break;
348         case SND_JACK_LINEOUT:
349                 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
350                 break;
351         default:
352                 break;
353         }
354
355
356         is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
357
358         if (!is_pa_on) {
359                 wcd_mbhc_compute_impedance(mbhc);
360                 if ((mbhc->zl > mbhc->cfg->linein_th) &&
361                     (mbhc->zr > mbhc->cfg->linein_th) &&
362                     (jack_type == SND_JACK_HEADPHONE)) {
363                         jack_type = SND_JACK_LINEOUT;
364                         mbhc->force_linein = true;
365                         mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
366                         if (mbhc->hph_status) {
367                                 mbhc->hph_status &= ~(SND_JACK_HEADSET |
368                                                       SND_JACK_LINEOUT);
369                                 snd_soc_jack_report(mbhc->jack, mbhc->hph_status,
370                                                     WCD_MBHC_JACK_MASK);
371                         }
372                 }
373         }
374
375         /* Do not calculate impedance again for lineout
376          * as during playback pa is on and impedance values
377          * will not be correct resulting in lineout detected
378          * as headphone.
379          */
380         if (is_pa_on && mbhc->force_linein) {
381                 jack_type = SND_JACK_LINEOUT;
382                 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH;
383                 if (mbhc->hph_status) {
384                         mbhc->hph_status &= ~(SND_JACK_HEADSET |
385                                               SND_JACK_LINEOUT);
386                         snd_soc_jack_report(mbhc->jack, mbhc->hph_status,
387                                             WCD_MBHC_JACK_MASK);
388                 }
389         }
390
391         mbhc->hph_status |= jack_type;
392
393         if (jack_type == SND_JACK_HEADPHONE && mbhc->mbhc_cb->mbhc_micb_ramp_control)
394                 mbhc->mbhc_cb->mbhc_micb_ramp_control(mbhc->component, false);
395
396         snd_soc_jack_report(mbhc->jack, (mbhc->hph_status | SND_JACK_MECHANICAL),
397                             WCD_MBHC_JACK_MASK);
398 }
399
400 static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion,
401                                  enum snd_jack_types jack_type)
402 {
403
404         WARN_ON(!mutex_is_locked(&mbhc->lock));
405
406         if (!insertion) /* Report removal */
407                 wcd_mbhc_report_plug_removal(mbhc, jack_type);
408         else
409                 wcd_mbhc_report_plug_insertion(mbhc, jack_type);
410
411 }
412
413 static void wcd_cancel_hs_detect_plug(struct wcd_mbhc *mbhc,
414                                       struct work_struct *work)
415 {
416         mbhc->hs_detect_work_stop = true;
417         mutex_unlock(&mbhc->lock);
418         cancel_work_sync(work);
419         mutex_lock(&mbhc->lock);
420 }
421
422 static void wcd_mbhc_cancel_pending_work(struct wcd_mbhc *mbhc)
423 {
424         /* cancel pending button press */
425         wcd_cancel_btn_work(mbhc);
426         /* cancel correct work function */
427         wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
428 }
429
430 static void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc)
431 {
432         wcd_mbhc_cancel_pending_work(mbhc);
433         /* Report extension cable */
434         wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
435         /*
436          * Disable HPHL trigger and MIC Schmitt triggers.
437          * Setup for insertion detection.
438          */
439         disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
440         wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_NONE);
441         /* Disable HW FSM */
442         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
443         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 3);
444
445         /* Set the detection type appropriately */
446         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1);
447         enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr);
448 }
449
450 static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc,
451                                    enum wcd_mbhc_plug_type plug_type)
452 {
453         if (mbhc->current_plug == plug_type)
454                 return;
455
456         mutex_lock(&mbhc->lock);
457
458         switch (plug_type) {
459         case MBHC_PLUG_TYPE_HEADPHONE:
460                 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADPHONE);
461                 break;
462         case MBHC_PLUG_TYPE_HEADSET:
463                 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET);
464                 break;
465         case MBHC_PLUG_TYPE_HIGH_HPH:
466                 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT);
467                 break;
468         case MBHC_PLUG_TYPE_GND_MIC_SWAP:
469                 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
470                         wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE);
471                 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
472                         wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET);
473                 break;
474         default:
475                 WARN(1, "Unexpected current plug_type %d, plug_type %d\n",
476                      mbhc->current_plug, plug_type);
477                 break;
478         }
479         mutex_unlock(&mbhc->lock);
480 }
481
482 static void wcd_schedule_hs_detect_plug(struct wcd_mbhc *mbhc,
483                                             struct work_struct *work)
484 {
485         WARN_ON(!mutex_is_locked(&mbhc->lock));
486         mbhc->hs_detect_work_stop = false;
487         schedule_work(work);
488 }
489
490 static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc)
491 {
492         struct snd_soc_component *component = mbhc->component;
493
494         WARN_ON(!mutex_is_locked(&mbhc->lock));
495
496         if (mbhc->mbhc_cb->hph_pull_down_ctrl)
497                 mbhc->mbhc_cb->hph_pull_down_ctrl(component, false);
498
499         wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
500
501         if (mbhc->mbhc_cb->mbhc_micbias_control) {
502                 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2,
503                                                     MICB_ENABLE);
504                 wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
505         }
506 }
507
508 static irqreturn_t wcd_mbhc_mech_plug_detect_irq(int irq, void *data)
509 {
510         struct snd_soc_component *component;
511         enum snd_jack_types jack_type;
512         struct wcd_mbhc *mbhc = data;
513         bool detection_type;
514
515         component = mbhc->component;
516         mutex_lock(&mbhc->lock);
517
518         mbhc->in_swch_irq_handler = true;
519
520         wcd_mbhc_cancel_pending_work(mbhc);
521
522         detection_type = wcd_mbhc_read_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE);
523
524         /* Set the detection type appropriately */
525         wcd_mbhc_write_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE, !detection_type);
526
527         /* Enable micbias ramp */
528         if (mbhc->mbhc_cb->mbhc_micb_ramp_control)
529                 mbhc->mbhc_cb->mbhc_micb_ramp_control(component, true);
530
531         if (detection_type) {
532                 if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE)
533                         goto exit;
534                 /* Make sure MASTER_BIAS_CTL is enabled */
535                 mbhc->mbhc_cb->mbhc_bias(component, true);
536                 mbhc->is_btn_press = false;
537                 wcd_mbhc_adc_detect_plug_type(mbhc);
538         } else {
539                 /* Disable HW FSM */
540                 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
541                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
542                 mbhc->extn_cable_hph_rem = false;
543
544                 if (mbhc->current_plug == MBHC_PLUG_TYPE_NONE)
545                         goto exit;
546
547                 mbhc->is_btn_press = false;
548                 switch (mbhc->current_plug) {
549                 case MBHC_PLUG_TYPE_HEADPHONE:
550                         jack_type = SND_JACK_HEADPHONE;
551                         break;
552                 case MBHC_PLUG_TYPE_HEADSET:
553                         jack_type = SND_JACK_HEADSET;
554                         break;
555                 case MBHC_PLUG_TYPE_HIGH_HPH:
556                         if (mbhc->mbhc_detection_logic == WCD_DETECTION_ADC)
557                                 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 0);
558                         jack_type = SND_JACK_LINEOUT;
559                         break;
560                 case MBHC_PLUG_TYPE_GND_MIC_SWAP:
561                         dev_err(mbhc->dev, "Ground and Mic Swapped on plug\n");
562                         goto exit;
563                 default:
564                         dev_err(mbhc->dev, "Invalid current plug: %d\n",
565                                 mbhc->current_plug);
566                         goto exit;
567                 }
568                 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
569                 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
570                 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1);
571                 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0);
572                 wcd_mbhc_report_plug(mbhc, 0, jack_type);
573         }
574
575 exit:
576         mbhc->in_swch_irq_handler = false;
577         mutex_unlock(&mbhc->lock);
578         return IRQ_HANDLED;
579 }
580
581 static int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc)
582 {
583         int mask = 0;
584         int btn;
585
586         btn = wcd_mbhc_read_field(mbhc, WCD_MBHC_BTN_RESULT);
587
588         switch (btn) {
589         case 0:
590                 mask = SND_JACK_BTN_0;
591                 break;
592         case 1:
593                 mask = SND_JACK_BTN_1;
594                 break;
595         case 2:
596                 mask = SND_JACK_BTN_2;
597                 break;
598         case 3:
599                 mask = SND_JACK_BTN_3;
600                 break;
601         case 4:
602                 mask = SND_JACK_BTN_4;
603                 break;
604         case 5:
605                 mask = SND_JACK_BTN_5;
606                 break;
607         default:
608                 break;
609         }
610
611         return mask;
612 }
613
614 static void wcd_btn_long_press_fn(struct work_struct *work)
615 {
616         struct delayed_work *dwork = to_delayed_work(work);
617         struct wcd_mbhc *mbhc = container_of(dwork, struct wcd_mbhc, mbhc_btn_dwork);
618
619         if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET)
620                 snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed,
621                                     mbhc->buttons_pressed);
622 }
623
624 static irqreturn_t wcd_mbhc_btn_press_handler(int irq, void *data)
625 {
626         struct wcd_mbhc *mbhc = data;
627         int mask;
628         unsigned long msec_val;
629
630         mutex_lock(&mbhc->lock);
631         wcd_cancel_btn_work(mbhc);
632         mbhc->is_btn_press = true;
633         msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport);
634
635         /* Too short, ignore button press */
636         if (msec_val < MBHC_BUTTON_PRESS_THRESHOLD_MIN)
637                 goto done;
638
639         /* If switch interrupt already kicked in, ignore button press */
640         if (mbhc->in_swch_irq_handler)
641                 goto done;
642
643         /* Plug isn't headset, ignore button press */
644         if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET)
645                 goto done;
646
647         mask = wcd_mbhc_get_button_mask(mbhc);
648         mbhc->buttons_pressed |= mask;
649         if (schedule_delayed_work(&mbhc->mbhc_btn_dwork, msecs_to_jiffies(400)) == 0)
650                 WARN(1, "Button pressed twice without release event\n");
651 done:
652         mutex_unlock(&mbhc->lock);
653         return IRQ_HANDLED;
654 }
655
656 static irqreturn_t wcd_mbhc_btn_release_handler(int irq, void *data)
657 {
658         struct wcd_mbhc *mbhc = data;
659         int ret;
660
661         mutex_lock(&mbhc->lock);
662         if (mbhc->is_btn_press)
663                 mbhc->is_btn_press = false;
664         else /* fake btn press */
665                 goto exit;
666
667         if (!(mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK))
668                 goto exit;
669
670         ret = wcd_cancel_btn_work(mbhc);
671         if (ret == 0) { /* Reporting long button release event */
672                 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
673         } else {
674                 if (!mbhc->in_swch_irq_handler) {
675                         /* Reporting btn press n Release */
676                         snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed,
677                                             mbhc->buttons_pressed);
678                         snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed);
679                 }
680         }
681         mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK;
682 exit:
683         mutex_unlock(&mbhc->lock);
684
685         return IRQ_HANDLED;
686 }
687
688 static irqreturn_t wcd_mbhc_hph_ocp_irq(struct wcd_mbhc *mbhc, bool hphr)
689 {
690
691         /* TODO Find a better way to report this to Userspace */
692         dev_err(mbhc->dev, "MBHC Over Current on %s detected\n",
693                 hphr ? "HPHR" : "HPHL");
694
695         wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 0);
696         wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 1);
697
698         return IRQ_HANDLED;
699 }
700
701 static irqreturn_t wcd_mbhc_hphl_ocp_irq(int irq, void *data)
702 {
703         return wcd_mbhc_hph_ocp_irq(data, false);
704 }
705
706 static irqreturn_t wcd_mbhc_hphr_ocp_irq(int irq, void *data)
707 {
708         return wcd_mbhc_hph_ocp_irq(data, true);
709 }
710
711 static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc)
712 {
713         struct snd_soc_component *component = mbhc->component;
714
715         mutex_lock(&mbhc->lock);
716
717         /* enable HS detection */
718         if (mbhc->mbhc_cb->hph_pull_up_control_v2)
719                 mbhc->mbhc_cb->hph_pull_up_control_v2(component,
720                                                       HS_PULLUP_I_DEFAULT);
721         else if (mbhc->mbhc_cb->hph_pull_up_control)
722                 mbhc->mbhc_cb->hph_pull_up_control(component, I_DEFAULT);
723         else
724                 wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3);
725
726         wcd_mbhc_write_field(mbhc, WCD_MBHC_HPHL_PLUG_TYPE, mbhc->cfg->hphl_swh);
727         wcd_mbhc_write_field(mbhc, WCD_MBHC_GND_PLUG_TYPE, mbhc->cfg->gnd_swh);
728         wcd_mbhc_write_field(mbhc, WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1);
729         if (mbhc->cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl)
730                 mbhc->mbhc_cb->mbhc_gnd_det_ctrl(component, true);
731         wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, 1);
732
733         wcd_mbhc_write_field(mbhc, WCD_MBHC_L_DET_EN, 1);
734
735         /* Insertion debounce set to 96ms */
736         wcd_mbhc_write_field(mbhc, WCD_MBHC_INSREM_DBNC, 6);
737
738         /* Button Debounce set to 16ms */
739         wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_DBNC, 2);
740
741         /* enable bias */
742         mbhc->mbhc_cb->mbhc_bias(component, true);
743         /* enable MBHC clock */
744         if (mbhc->mbhc_cb->clk_setup)
745                 mbhc->mbhc_cb->clk_setup(component, true);
746
747         /* program HS_VREF value */
748         wcd_program_hs_vref(mbhc);
749
750         wcd_program_btn_threshold(mbhc, false);
751
752         mutex_unlock(&mbhc->lock);
753
754         return 0;
755 }
756
757 static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc)
758 {
759         int micbias = 0;
760
761         if (mbhc->mbhc_cb->get_micbias_val) {
762                 mbhc->mbhc_cb->get_micbias_val(mbhc->component, &micbias);
763         } else {
764                 u8 vout_ctl = 0;
765                 /* Read MBHC Micbias (Mic Bias2) voltage */
766                 vout_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_MICB2_VOUT);
767                 /* Formula for getting micbias from vout
768                  * micbias = 1.0V + VOUT_CTL * 50mV
769                  */
770                 micbias = 1000 + (vout_ctl * 50);
771         }
772         return micbias;
773 }
774
775 static int wcd_get_voltage_from_adc(u8 val, int micbias)
776 {
777         /* Formula for calculating voltage from ADC
778          * Voltage = ADC_RESULT*12.5mV*V_MICBIAS/1.8
779          */
780         return ((val * 125 * micbias)/(WCD_MBHC_ADC_MICBIAS_MV * 10));
781 }
782
783 static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc)
784 {
785         u8 adc_result;
786         int output_mv;
787         int retry = 3;
788         u8 adc_en;
789
790         /* Pre-requisites for ADC continuous measurement */
791         /* Read legacy electircal detection and disable */
792         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0x00);
793         /* Set ADC to continuous measurement */
794         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 1);
795         /* Read ADC Enable bit to restore after adc measurement */
796         adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
797         /* Disable ADC_ENABLE bit */
798         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
799         /* Disable MBHC FSM */
800         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
801         /* Set the MUX selection to IN2P */
802         wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_IN2P);
803         /* Enable MBHC FSM */
804         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
805         /* Enable ADC_ENABLE bit */
806         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1);
807
808         while (retry--) {
809                 /* wait for 3 msec before reading ADC result */
810                 usleep_range(3000, 3100);
811                 adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT);
812         }
813
814         /* Restore ADC Enable */
815         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
816         /* Get voltage from ADC result */
817         output_mv = wcd_get_voltage_from_adc(adc_result, wcd_mbhc_get_micbias(mbhc));
818
819         return output_mv;
820 }
821
822 static int wcd_measure_adc_once(struct wcd_mbhc *mbhc, int mux_ctl)
823 {
824         struct device *dev = mbhc->dev;
825         u8 adc_timeout = 0;
826         u8 adc_complete = 0;
827         u8 adc_result;
828         int retry = 6;
829         int ret;
830         int output_mv = 0;
831         u8 adc_en;
832
833         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
834         /* Read ADC Enable bit to restore after adc measurement */
835         adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
836         /* Trigger ADC one time measurement */
837         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
838         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
839         /* Set the appropriate MUX selection */
840         wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, mux_ctl);
841         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
842         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1);
843
844         while (retry--) {
845                 /* wait for 600usec to get adc results */
846                 usleep_range(600, 610);
847
848                 /* check for ADC Timeout */
849                 adc_timeout = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_TIMEOUT);
850                 if (adc_timeout)
851                         continue;
852
853                 /* Read ADC complete bit */
854                 adc_complete = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_COMPLETE);
855                 if (!adc_complete)
856                         continue;
857
858                 /* Read ADC result */
859                 adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT);
860
861                 /* Get voltage from ADC result */
862                 output_mv = wcd_get_voltage_from_adc(adc_result,
863                                                 wcd_mbhc_get_micbias(mbhc));
864                 break;
865         }
866
867         /* Restore ADC Enable */
868         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
869
870         if (retry <= 0) {
871                 dev_err(dev, "%s: adc complete: %d, adc timeout: %d\n",
872                         __func__, adc_complete, adc_timeout);
873                 ret = -EINVAL;
874         } else {
875                 ret = output_mv;
876         }
877
878         return ret;
879 }
880
881 /* To determine if cross connection occurred */
882 static int wcd_check_cross_conn(struct wcd_mbhc *mbhc)
883 {
884         u8 adc_mode, elect_ctl, adc_en, fsm_en;
885         int hphl_adc_res, hphr_adc_res;
886         bool is_cross_conn = false;
887
888         /* If PA is enabled, dont check for cross-connection */
889         if (wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN))
890                 return -EINVAL;
891
892         /* Read legacy electircal detection and disable */
893         elect_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC);
894         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0);
895
896         /* Read and set ADC to single measurement */
897         adc_mode = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_MODE);
898         /* Read ADC Enable bit to restore after adc measurement */
899         adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN);
900         /* Read FSM status */
901         fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN);
902
903         /* Get adc result for HPH L */
904         hphl_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_L);
905         if (hphl_adc_res < 0)
906                 return hphl_adc_res;
907
908         /* Get adc result for HPH R in mV */
909         hphr_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_R);
910         if (hphr_adc_res < 0)
911                 return hphr_adc_res;
912
913         if (hphl_adc_res > HPHL_CROSS_CONN_THRESHOLD ||
914             hphr_adc_res > HPHL_CROSS_CONN_THRESHOLD)
915                 is_cross_conn = true;
916
917         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0);
918         /* Set the MUX selection to Auto */
919         wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO);
920         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1);
921         /* Restore ADC Enable */
922         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en);
923         /* Restore ADC mode */
924         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, adc_mode);
925         /* Restore FSM state */
926         wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en);
927         /* Restore electrical detection */
928         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl);
929
930         return is_cross_conn;
931 }
932
933 static int wcd_mbhc_adc_get_hs_thres(struct wcd_mbhc *mbhc)
934 {
935         int hs_threshold, micbias_mv;
936
937         micbias_mv = wcd_mbhc_get_micbias(mbhc);
938         if (mbhc->cfg->hs_thr) {
939                 if (mbhc->cfg->micb_mv == micbias_mv)
940                         hs_threshold = mbhc->cfg->hs_thr;
941                 else
942                         hs_threshold = (mbhc->cfg->hs_thr *
943                                 micbias_mv) / mbhc->cfg->micb_mv;
944         } else {
945                 hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV *
946                         micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
947         }
948         return hs_threshold;
949 }
950
951 static int wcd_mbhc_adc_get_hph_thres(struct wcd_mbhc *mbhc)
952 {
953         int hph_threshold, micbias_mv;
954
955         micbias_mv = wcd_mbhc_get_micbias(mbhc);
956         if (mbhc->cfg->hph_thr) {
957                 if (mbhc->cfg->micb_mv == micbias_mv)
958                         hph_threshold = mbhc->cfg->hph_thr;
959                 else
960                         hph_threshold = (mbhc->cfg->hph_thr *
961                                 micbias_mv) / mbhc->cfg->micb_mv;
962         } else {
963                 hph_threshold = ((WCD_MBHC_ADC_HPH_THRESHOLD_MV *
964                         micbias_mv) / WCD_MBHC_ADC_MICBIAS_MV);
965         }
966         return hph_threshold;
967 }
968
969 static void wcd_mbhc_adc_update_fsm_source(struct wcd_mbhc *mbhc,
970                                            enum wcd_mbhc_plug_type plug_type)
971 {
972         bool micbias2 = false;
973
974         switch (plug_type) {
975         case MBHC_PLUG_TYPE_HEADPHONE:
976                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
977                 break;
978         case MBHC_PLUG_TYPE_HEADSET:
979                 if (mbhc->mbhc_cb->micbias_enable_status)
980                         micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc->component,
981                                                                         MIC_BIAS_2);
982
983                 if (!mbhc->is_hs_recording && !micbias2)
984                         wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3);
985                 break;
986         default:
987                 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
988                 break;
989
990         }
991 }
992
993 static void wcd_mbhc_bcs_enable(struct wcd_mbhc *mbhc, int plug_type, bool enable)
994 {
995         switch (plug_type) {
996         case MBHC_PLUG_TYPE_HEADSET:
997         case MBHC_PLUG_TYPE_HEADPHONE:
998                 if (mbhc->mbhc_cb->bcs_enable)
999                         mbhc->mbhc_cb->bcs_enable(mbhc->component, enable);
1000                 break;
1001         default:
1002                 break;
1003         }
1004 }
1005
1006 static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result)
1007
1008 {
1009         enum wcd_mbhc_plug_type plug_type;
1010         u32 hph_thr, hs_thr;
1011
1012         hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc);
1013         hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc);
1014
1015         if (adc_result < hph_thr)
1016                 plug_type = MBHC_PLUG_TYPE_HEADPHONE;
1017         else if (adc_result > hs_thr)
1018                 plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
1019         else
1020                 plug_type = MBHC_PLUG_TYPE_HEADSET;
1021
1022         return plug_type;
1023 }
1024
1025 static int wcd_mbhc_get_spl_hs_thres(struct wcd_mbhc *mbhc)
1026 {
1027         int hs_threshold, micbias_mv;
1028
1029         micbias_mv = wcd_mbhc_get_micbias(mbhc);
1030         if (mbhc->cfg->hs_thr && mbhc->cfg->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) {
1031                 if (mbhc->cfg->micb_mv == micbias_mv)
1032                         hs_threshold = mbhc->cfg->hs_thr;
1033                 else
1034                         hs_threshold = (mbhc->cfg->hs_thr * micbias_mv) / mbhc->cfg->micb_mv;
1035         } else {
1036                 hs_threshold = ((WCD_MBHC_ADC_HS_THRESHOLD_MV * micbias_mv) /
1037                                                         WCD_MBHC_ADC_MICBIAS_MV);
1038         }
1039         return hs_threshold;
1040 }
1041
1042 static bool wcd_mbhc_check_for_spl_headset(struct wcd_mbhc *mbhc)
1043 {
1044         bool is_spl_hs = false;
1045         int output_mv, hs_threshold, hph_threshold;
1046
1047         if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic)
1048                 return false;
1049
1050         /* Bump up MIC_BIAS2 to 2.7V */
1051         mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, true);
1052         usleep_range(10000, 10100);
1053
1054         output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
1055         hs_threshold = wcd_mbhc_get_spl_hs_thres(mbhc);
1056         hph_threshold = wcd_mbhc_adc_get_hph_thres(mbhc);
1057
1058         if (output_mv > hs_threshold || output_mv < hph_threshold) {
1059                 if (mbhc->force_linein == true)
1060                         is_spl_hs = false;
1061         } else {
1062                 is_spl_hs = true;
1063         }
1064
1065         /* Back MIC_BIAS2 to 1.8v if the type is not special headset */
1066         if (!is_spl_hs) {
1067                 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, false);
1068                 /* Add 10ms delay for micbias to settle */
1069                 usleep_range(10000, 10100);
1070         }
1071
1072         return is_spl_hs;
1073 }
1074
1075 static void wcd_correct_swch_plug(struct work_struct *work)
1076 {
1077         struct wcd_mbhc *mbhc;
1078         struct snd_soc_component *component;
1079         enum wcd_mbhc_plug_type plug_type = MBHC_PLUG_TYPE_INVALID;
1080         unsigned long timeout;
1081         int pt_gnd_mic_swap_cnt = 0;
1082         int output_mv, cross_conn, hs_threshold, try = 0, micbias_mv;
1083         bool is_spl_hs = false;
1084         bool is_pa_on;
1085
1086         mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch);
1087         component = mbhc->component;
1088
1089         micbias_mv = wcd_mbhc_get_micbias(mbhc);
1090         hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
1091
1092         /* Mask ADC COMPLETE interrupt */
1093         disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
1094
1095         /* Check for cross connection */
1096         do {
1097                 cross_conn = wcd_check_cross_conn(mbhc);
1098                 try++;
1099         } while (try < GND_MIC_SWAP_THRESHOLD);
1100
1101         if (cross_conn > 0) {
1102                 plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
1103                 dev_err(mbhc->dev, "cross connection found, Plug type %d\n",
1104                         plug_type);
1105                 goto correct_plug_type;
1106         }
1107
1108         /* Find plug type */
1109         output_mv = wcd_measure_adc_continuous(mbhc);
1110         plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
1111
1112         /*
1113          * Report plug type if it is either headset or headphone
1114          * else start the 3 sec loop
1115          */
1116         switch (plug_type) {
1117         case MBHC_PLUG_TYPE_HEADPHONE:
1118                 wcd_mbhc_find_plug_and_report(mbhc, plug_type);
1119                 break;
1120         case MBHC_PLUG_TYPE_HEADSET:
1121                 wcd_mbhc_find_plug_and_report(mbhc, plug_type);
1122                 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
1123                 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
1124                 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
1125                 break;
1126         default:
1127                 break;
1128         }
1129
1130 correct_plug_type:
1131
1132         /* Disable BCS slow insertion detection */
1133         wcd_mbhc_bcs_enable(mbhc, plug_type, false);
1134
1135         timeout = jiffies + msecs_to_jiffies(HS_DETECT_PLUG_TIME_MS);
1136
1137         while (!time_after(jiffies, timeout)) {
1138                 if (mbhc->hs_detect_work_stop) {
1139                         wcd_micbias_disable(mbhc);
1140                         goto exit;
1141                 }
1142
1143                 msleep(180);
1144                 /*
1145                  * Use ADC single mode to minimize the chance of missing out
1146                  * btn press/release for HEADSET type during correct work.
1147                  */
1148                 output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
1149                 plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
1150                 is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN);
1151
1152                 if ((output_mv > hs_threshold) && (!is_spl_hs)) {
1153                         is_spl_hs = wcd_mbhc_check_for_spl_headset(mbhc);
1154                         output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
1155
1156                         if (is_spl_hs) {
1157                                 hs_threshold = (hs_threshold * wcd_mbhc_get_micbias(mbhc)) /
1158                                                                         micbias_mv;
1159                         }
1160                 }
1161
1162                 if ((output_mv <= hs_threshold) && !is_pa_on) {
1163                         /* Check for cross connection*/
1164                         cross_conn = wcd_check_cross_conn(mbhc);
1165                         if (cross_conn > 0) { /* cross-connection */
1166                                 pt_gnd_mic_swap_cnt++;
1167                                 if (pt_gnd_mic_swap_cnt < GND_MIC_SWAP_THRESHOLD)
1168                                         continue;
1169                                 else
1170                                         plug_type = MBHC_PLUG_TYPE_GND_MIC_SWAP;
1171                         } else if (!cross_conn) { /* no cross connection */
1172                                 pt_gnd_mic_swap_cnt = 0;
1173                                 plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv);
1174                                 continue;
1175                         } else if (cross_conn < 0) /* Error */
1176                                 continue;
1177
1178                         if (pt_gnd_mic_swap_cnt == GND_MIC_SWAP_THRESHOLD) {
1179                                 /* US_EU gpio present, flip switch */
1180                                 if (mbhc->cfg->swap_gnd_mic) {
1181                                         if (mbhc->cfg->swap_gnd_mic(component, true))
1182                                                 continue;
1183                                 }
1184                         }
1185                 }
1186
1187                 /* cable is extension cable */
1188                 if (output_mv > hs_threshold || mbhc->force_linein == true)
1189                         plug_type = MBHC_PLUG_TYPE_HIGH_HPH;
1190         }
1191
1192         wcd_mbhc_bcs_enable(mbhc, plug_type, true);
1193
1194         if (plug_type == MBHC_PLUG_TYPE_HIGH_HPH) {
1195                 if (is_spl_hs)
1196                         plug_type = MBHC_PLUG_TYPE_HEADSET;
1197                 else
1198                         wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1);
1199         }
1200
1201         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
1202         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
1203         wcd_mbhc_find_plug_and_report(mbhc, plug_type);
1204
1205         /*
1206          * Set DETECTION_DONE bit for HEADSET
1207          * so that btn press/release interrupt can be generated.
1208          * For other plug type, clear the bit.
1209          */
1210         if (plug_type == MBHC_PLUG_TYPE_HEADSET)
1211                 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
1212         else
1213                 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
1214
1215         if (mbhc->mbhc_cb->mbhc_micbias_control)
1216                 wcd_mbhc_adc_update_fsm_source(mbhc, plug_type);
1217
1218 exit:
1219         if (mbhc->mbhc_cb->mbhc_micbias_control/* &&  !mbhc->micbias_enable*/)
1220                 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE);
1221
1222         /*
1223          * If plug type is corrected from special headset to headphone,
1224          * clear the micbias enable flag, set micbias back to 1.8V and
1225          * disable micbias.
1226          */
1227         if (plug_type == MBHC_PLUG_TYPE_HEADPHONE) {
1228                 wcd_micbias_disable(mbhc);
1229                 /*
1230                  * Enable ADC COMPLETE interrupt for HEADPHONE.
1231                  * Btn release may happen after the correct work, ADC COMPLETE
1232                  * interrupt needs to be captured to correct plug type.
1233                  */
1234                 enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr);
1235         }
1236
1237         if (mbhc->mbhc_cb->hph_pull_down_ctrl)
1238                 mbhc->mbhc_cb->hph_pull_down_ctrl(component, true);
1239 }
1240
1241 static irqreturn_t wcd_mbhc_adc_hs_rem_irq(int irq, void *data)
1242 {
1243         struct wcd_mbhc *mbhc = data;
1244         unsigned long timeout;
1245         int adc_threshold, output_mv, retry = 0;
1246
1247         mutex_lock(&mbhc->lock);
1248         timeout = jiffies + msecs_to_jiffies(WCD_FAKE_REMOVAL_MIN_PERIOD_MS);
1249         adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc);
1250
1251         do {
1252                 retry++;
1253                 /*
1254                  * read output_mv every 10ms to look for
1255                  * any change in IN2_P
1256                  */
1257                 usleep_range(10000, 10100);
1258                 output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P);
1259
1260                 /* Check for fake removal */
1261                 if ((output_mv <= adc_threshold) && retry > FAKE_REM_RETRY_ATTEMPTS)
1262                         goto exit;
1263         } while (!time_after(jiffies, timeout));
1264
1265         /*
1266          * ADC COMPLETE and ELEC_REM interrupts are both enabled for
1267          * HEADPHONE, need to reject the ADC COMPLETE interrupt which
1268          * follows ELEC_REM one when HEADPHONE is removed.
1269          */
1270         if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE)
1271                 mbhc->extn_cable_hph_rem = true;
1272
1273         wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0);
1274         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0);
1275         wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0);
1276         wcd_mbhc_elec_hs_report_unplug(mbhc);
1277         wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0);
1278
1279 exit:
1280         mutex_unlock(&mbhc->lock);
1281         return IRQ_HANDLED;
1282 }
1283
1284 static irqreturn_t wcd_mbhc_adc_hs_ins_irq(int irq, void *data)
1285 {
1286         struct wcd_mbhc *mbhc = data;
1287         u8 clamp_state = 0;
1288         u8 clamp_retry = WCD_MBHC_FAKE_INS_RETRY;
1289
1290         /*
1291          * ADC COMPLETE and ELEC_REM interrupts are both enabled for HEADPHONE,
1292          * need to reject the ADC COMPLETE interrupt which follows ELEC_REM one
1293          * when HEADPHONE is removed.
1294          */
1295         if (mbhc->extn_cable_hph_rem == true) {
1296                 mbhc->extn_cable_hph_rem = false;
1297                 return IRQ_HANDLED;
1298         }
1299
1300         do {
1301                 clamp_state = wcd_mbhc_read_field(mbhc, WCD_MBHC_IN2P_CLAMP_STATE);
1302                 if (clamp_state)
1303                         return IRQ_HANDLED;
1304                 /*
1305                  * check clamp for 120ms but at 30ms chunks to leave
1306                  * room for other interrupts to be processed
1307                  */
1308                 usleep_range(30000, 30100);
1309         } while (--clamp_retry);
1310
1311         /*
1312          * If current plug is headphone then there is no chance to
1313          * get ADC complete interrupt, so connected cable should be
1314          * headset not headphone.
1315          */
1316         if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) {
1317                 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
1318                 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1);
1319                 wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET);
1320                 return IRQ_HANDLED;
1321         }
1322
1323         return IRQ_HANDLED;
1324 }
1325
1326 int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, uint32_t *zr)
1327 {
1328         *zl = mbhc->zl;
1329         *zr = mbhc->zr;
1330
1331         if (*zl && *zr)
1332                 return 0;
1333         else
1334                 return -EINVAL;
1335 }
1336 EXPORT_SYMBOL(wcd_mbhc_get_impedance);
1337
1338 void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type)
1339 {
1340         mbhc->hph_type = hph_type;
1341 }
1342 EXPORT_SYMBOL(wcd_mbhc_set_hph_type);
1343
1344 int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc)
1345 {
1346         return mbhc->hph_type;
1347 }
1348 EXPORT_SYMBOL(wcd_mbhc_get_hph_type);
1349
1350 int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *cfg,
1351                    struct snd_soc_jack *jack)
1352 {
1353         if (!mbhc || !cfg || !jack)
1354                 return -EINVAL;
1355
1356         mbhc->cfg = cfg;
1357         mbhc->jack = jack;
1358
1359         return wcd_mbhc_initialise(mbhc);
1360 }
1361 EXPORT_SYMBOL(wcd_mbhc_start);
1362
1363 void wcd_mbhc_stop(struct wcd_mbhc *mbhc)
1364 {
1365         mbhc->current_plug = MBHC_PLUG_TYPE_NONE;
1366         mbhc->hph_status = 0;
1367         disable_irq_nosync(mbhc->intr_ids->hph_left_ocp);
1368         disable_irq_nosync(mbhc->intr_ids->hph_right_ocp);
1369 }
1370 EXPORT_SYMBOL(wcd_mbhc_stop);
1371
1372 int wcd_dt_parse_mbhc_data(struct device *dev, struct wcd_mbhc_config *cfg)
1373 {
1374         struct device_node *np = dev->of_node;
1375         int ret, i, microvolt;
1376
1377         if (of_property_read_bool(np, "qcom,hphl-jack-type-normally-closed"))
1378                 cfg->hphl_swh = false;
1379         else
1380                 cfg->hphl_swh = true;
1381
1382         if (of_property_read_bool(np, "qcom,ground-jack-type-normally-closed"))
1383                 cfg->gnd_swh = false;
1384         else
1385                 cfg->gnd_swh = true;
1386
1387         ret = of_property_read_u32(np, "qcom,mbhc-headset-vthreshold-microvolt",
1388                                    &microvolt);
1389         if (ret)
1390                 dev_dbg(dev, "missing qcom,mbhc-hs-mic-max-vthreshold--microvolt in dt node\n");
1391         else
1392                 cfg->hs_thr = microvolt/1000;
1393
1394         ret = of_property_read_u32(np, "qcom,mbhc-headphone-vthreshold-microvolt",
1395                                    &microvolt);
1396         if (ret)
1397                 dev_dbg(dev, "missing qcom,mbhc-hs-mic-min-vthreshold-microvolt entry\n");
1398         else
1399                 cfg->hph_thr = microvolt/1000;
1400
1401         ret = of_property_read_u32_array(np,
1402                                          "qcom,mbhc-buttons-vthreshold-microvolt",
1403                                          &cfg->btn_high[0],
1404                                          WCD_MBHC_DEF_BUTTONS);
1405         if (ret)
1406                 dev_err(dev, "missing qcom,mbhc-buttons-vthreshold-microvolt entry\n");
1407
1408         for (i = 0; i < WCD_MBHC_DEF_BUTTONS; i++) {
1409                 if (ret) /* default voltage */
1410                         cfg->btn_high[i] = 500000;
1411                 else
1412                         /* Micro to Milli Volts */
1413                         cfg->btn_high[i] = cfg->btn_high[i]/1000;
1414         }
1415
1416         return 0;
1417 }
1418 EXPORT_SYMBOL(wcd_dt_parse_mbhc_data);
1419
1420 struct wcd_mbhc *wcd_mbhc_init(struct snd_soc_component *component,
1421                                const struct wcd_mbhc_cb *mbhc_cb,
1422                                const struct wcd_mbhc_intr *intr_ids,
1423                                struct wcd_mbhc_field *fields,
1424                                bool impedance_det_en)
1425 {
1426         struct device *dev = component->dev;
1427         struct wcd_mbhc *mbhc;
1428         int ret;
1429
1430         if (!intr_ids || !fields || !mbhc_cb || !mbhc_cb->mbhc_bias || !mbhc_cb->set_btn_thr) {
1431                 dev_err(dev, "%s: Insufficient mbhc configuration\n", __func__);
1432                 return ERR_PTR(-EINVAL);
1433         }
1434
1435         mbhc = devm_kzalloc(dev, sizeof(*mbhc), GFP_KERNEL);
1436         if (!mbhc)
1437                 return ERR_PTR(-ENOMEM);
1438
1439         mbhc->component = component;
1440         mbhc->dev = dev;
1441         mbhc->intr_ids = intr_ids;
1442         mbhc->mbhc_cb = mbhc_cb;
1443         mbhc->fields = fields;
1444         mbhc->mbhc_detection_logic = WCD_DETECTION_ADC;
1445
1446         if (mbhc_cb->compute_impedance)
1447                 mbhc->impedance_detect = impedance_det_en;
1448
1449         INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_long_press_fn);
1450
1451         mutex_init(&mbhc->lock);
1452
1453         INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug);
1454
1455         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_sw_intr, NULL,
1456                                         wcd_mbhc_mech_plug_detect_irq,
1457                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1458                                         "mbhc sw intr", mbhc);
1459         if (ret)
1460                 goto err;
1461
1462         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_press_intr, NULL,
1463                                         wcd_mbhc_btn_press_handler,
1464                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1465                                         "Button Press detect", mbhc);
1466         if (ret)
1467                 goto err;
1468
1469         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_release_intr, NULL,
1470                                         wcd_mbhc_btn_release_handler,
1471                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1472                                         "Button Release detect", mbhc);
1473         if (ret)
1474                 goto err;
1475
1476         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_ins_intr, NULL,
1477                                         wcd_mbhc_adc_hs_ins_irq,
1478                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1479                                         "Elect Insert", mbhc);
1480         if (ret)
1481                 goto err;
1482
1483         disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr);
1484
1485         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_rem_intr, NULL,
1486                                         wcd_mbhc_adc_hs_rem_irq,
1487                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1488                                         "Elect Remove", mbhc);
1489         if (ret)
1490                 goto err;
1491
1492         disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr);
1493
1494         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_left_ocp, NULL,
1495                                         wcd_mbhc_hphl_ocp_irq,
1496                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1497                                         "HPH_L OCP detect", mbhc);
1498         if (ret)
1499                 goto err;
1500
1501         ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_right_ocp, NULL,
1502                                         wcd_mbhc_hphr_ocp_irq,
1503                                         IRQF_ONESHOT | IRQF_TRIGGER_RISING,
1504                                         "HPH_R OCP detect", mbhc);
1505         if (ret)
1506                 goto err;
1507
1508         return mbhc;
1509 err:
1510         dev_err(dev, "Failed to request mbhc interrupts %d\n", ret);
1511
1512         return ERR_PTR(ret);
1513 }
1514 EXPORT_SYMBOL(wcd_mbhc_init);
1515
1516 void wcd_mbhc_deinit(struct wcd_mbhc *mbhc)
1517 {
1518         mutex_lock(&mbhc->lock);
1519         wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch);
1520         mutex_unlock(&mbhc->lock);
1521 }
1522 EXPORT_SYMBOL(wcd_mbhc_deinit);
1523
1524 static int __init mbhc_init(void)
1525 {
1526         return 0;
1527 }
1528
1529 static void __exit mbhc_exit(void)
1530 {
1531 }
1532
1533 module_init(mbhc_init);
1534 module_exit(mbhc_exit);
1535
1536 MODULE_DESCRIPTION("wcd MBHC v2 module");
1537 MODULE_LICENSE("GPL");