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