Lines Matching refs:mbhc

77 static inline int wcd_mbhc_write_field(const struct wcd_mbhc *mbhc,  in wcd_mbhc_write_field()  argument
80 if (!mbhc->fields[field].reg) in wcd_mbhc_write_field()
83 return snd_soc_component_write_field(mbhc->component, in wcd_mbhc_write_field()
84 mbhc->fields[field].reg, in wcd_mbhc_write_field()
85 mbhc->fields[field].mask, val); in wcd_mbhc_write_field()
88 static inline int wcd_mbhc_read_field(const struct wcd_mbhc *mbhc, int field) in wcd_mbhc_read_field() argument
90 if (!mbhc->fields[field].reg) in wcd_mbhc_read_field()
93 return snd_soc_component_read_field(mbhc->component, in wcd_mbhc_read_field()
94 mbhc->fields[field].reg, in wcd_mbhc_read_field()
95 mbhc->fields[field].mask); in wcd_mbhc_read_field()
98 static void wcd_program_hs_vref(struct wcd_mbhc *mbhc) in wcd_program_hs_vref() argument
100 u32 reg_val = ((mbhc->cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); in wcd_program_hs_vref()
102 wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_VREF, reg_val); in wcd_program_hs_vref()
105 static void wcd_program_btn_threshold(const struct wcd_mbhc *mbhc, bool micbias) in wcd_program_btn_threshold() argument
107 struct snd_soc_component *component = mbhc->component; in wcd_program_btn_threshold()
109 mbhc->mbhc_cb->set_btn_thr(component, mbhc->cfg->btn_low, in wcd_program_btn_threshold()
110 mbhc->cfg->btn_high, in wcd_program_btn_threshold()
111 mbhc->cfg->num_btn, micbias); in wcd_program_btn_threshold()
114 static void wcd_mbhc_curr_micbias_control(const struct wcd_mbhc *mbhc, in wcd_mbhc_curr_micbias_control() argument
124 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_mbhc_curr_micbias_control()
129 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0); in wcd_mbhc_curr_micbias_control()
130 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3); in wcd_mbhc_curr_micbias_control()
132 wcd_program_btn_threshold(mbhc, false); in wcd_mbhc_curr_micbias_control()
135 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_curr_micbias_control()
136 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_mbhc_curr_micbias_control()
138 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 2); in wcd_mbhc_curr_micbias_control()
140 wcd_program_btn_threshold(mbhc, true); in wcd_mbhc_curr_micbias_control()
143 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3); in wcd_mbhc_curr_micbias_control()
144 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_mbhc_curr_micbias_control()
145 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 1); in wcd_mbhc_curr_micbias_control()
147 wcd_program_btn_threshold(mbhc, true); in wcd_mbhc_curr_micbias_control()
150 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_curr_micbias_control()
151 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_mbhc_curr_micbias_control()
152 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0); in wcd_mbhc_curr_micbias_control()
155 dev_err(mbhc->dev, "%s: Invalid parameter", __func__); in wcd_mbhc_curr_micbias_control()
160 int wcd_mbhc_event_notify(struct wcd_mbhc *mbhc, unsigned long event) in wcd_mbhc_event_notify() argument
166 if (!mbhc) in wcd_mbhc_event_notify()
169 component = mbhc->component; in wcd_mbhc_event_notify()
171 if (mbhc->mbhc_cb->micbias_enable_status) in wcd_mbhc_event_notify()
172 micbias2 = mbhc->mbhc_cb->micbias_enable_status(component, MIC_BIAS_2); in wcd_mbhc_event_notify()
177 mbhc->is_hs_recording = true; in wcd_mbhc_event_notify()
181 if (mbhc->mbhc_cb->mbhc_micbias_control) { in wcd_mbhc_event_notify()
182 if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN)) in wcd_mbhc_event_notify()
183 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_event_notify()
185 mbhc->is_hs_recording = true; in wcd_mbhc_event_notify()
186 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB); in wcd_mbhc_event_notify()
195 if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) { in wcd_mbhc_event_notify()
196 if (wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN)) in wcd_mbhc_event_notify()
197 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3); in wcd_mbhc_event_notify()
202 mbhc->is_hs_recording = false; in wcd_mbhc_event_notify()
205 if (!mbhc->mbhc_cb->mbhc_micbias_control) in wcd_mbhc_event_notify()
206 mbhc->is_hs_recording = false; in wcd_mbhc_event_notify()
209 if ((test_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state)) || in wcd_mbhc_event_notify()
210 (test_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state))) in wcd_mbhc_event_notify()
212 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP); in wcd_mbhc_event_notify()
215 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS); in wcd_mbhc_event_notify()
219 clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); in wcd_mbhc_event_notify()
224 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB); in wcd_mbhc_event_notify()
227 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS); in wcd_mbhc_event_notify()
230 clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); in wcd_mbhc_event_notify()
234 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB); in wcd_mbhc_event_notify()
237 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_CS); in wcd_mbhc_event_notify()
240 set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); in wcd_mbhc_event_notify()
244 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB); in wcd_mbhc_event_notify()
247 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP); in wcd_mbhc_event_notify()
250 set_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); in wcd_mbhc_event_notify()
254 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_MB); in wcd_mbhc_event_notify()
257 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_PULLUP); in wcd_mbhc_event_notify()
266 static int wcd_cancel_btn_work(struct wcd_mbhc *mbhc) in wcd_cancel_btn_work() argument
268 return cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork); in wcd_cancel_btn_work()
271 static void wcd_micbias_disable(struct wcd_mbhc *mbhc) in wcd_micbias_disable() argument
273 struct snd_soc_component *component = mbhc->component; in wcd_micbias_disable()
275 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_micbias_disable()
276 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE); in wcd_micbias_disable()
278 if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) in wcd_micbias_disable()
279 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false); in wcd_micbias_disable()
281 if (mbhc->mbhc_cb->set_micbias_value) { in wcd_micbias_disable()
282 mbhc->mbhc_cb->set_micbias_value(component); in wcd_micbias_disable()
283 wcd_mbhc_write_field(mbhc, WCD_MBHC_MICB_CTRL, 0); in wcd_micbias_disable()
287 static void wcd_mbhc_report_plug_removal(struct wcd_mbhc *mbhc, in wcd_mbhc_report_plug_removal() argument
290 mbhc->hph_status &= ~jack_type; in wcd_mbhc_report_plug_removal()
295 if (!wcd_cancel_btn_work(mbhc) && mbhc->buttons_pressed) { in wcd_mbhc_report_plug_removal()
296 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_report_plug_removal()
297 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK; in wcd_mbhc_report_plug_removal()
300 wcd_micbias_disable(mbhc); in wcd_mbhc_report_plug_removal()
301 mbhc->hph_type = WCD_MBHC_HPH_NONE; in wcd_mbhc_report_plug_removal()
302 mbhc->zl = mbhc->zr = 0; in wcd_mbhc_report_plug_removal()
303 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, WCD_MBHC_JACK_MASK); in wcd_mbhc_report_plug_removal()
304 mbhc->current_plug = MBHC_PLUG_TYPE_NONE; in wcd_mbhc_report_plug_removal()
305 mbhc->force_linein = false; in wcd_mbhc_report_plug_removal()
308 static void wcd_mbhc_compute_impedance(struct wcd_mbhc *mbhc) in wcd_mbhc_compute_impedance() argument
311 if (!mbhc->impedance_detect) in wcd_mbhc_compute_impedance()
314 if (mbhc->cfg->linein_th != 0) { in wcd_mbhc_compute_impedance()
315 u8 fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN); in wcd_mbhc_compute_impedance()
318 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_mbhc_compute_impedance()
319 wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO); in wcd_mbhc_compute_impedance()
320 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_mbhc_compute_impedance()
321 mbhc->mbhc_cb->compute_impedance(mbhc->component, &mbhc->zl, &mbhc->zr); in wcd_mbhc_compute_impedance()
322 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en); in wcd_mbhc_compute_impedance()
326 static void wcd_mbhc_report_plug_insertion(struct wcd_mbhc *mbhc, in wcd_mbhc_report_plug_insertion() argument
335 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET && in wcd_mbhc_report_plug_insertion()
337 mbhc->hph_status &= ~SND_JACK_HEADSET; in wcd_mbhc_report_plug_insertion()
342 mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE; in wcd_mbhc_report_plug_insertion()
345 mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET; in wcd_mbhc_report_plug_insertion()
346 mbhc->jiffies_atreport = jiffies; in wcd_mbhc_report_plug_insertion()
349 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
356 is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN); in wcd_mbhc_report_plug_insertion()
359 wcd_mbhc_compute_impedance(mbhc); in wcd_mbhc_report_plug_insertion()
360 if ((mbhc->zl > mbhc->cfg->linein_th) && in wcd_mbhc_report_plug_insertion()
361 (mbhc->zr > mbhc->cfg->linein_th) && in wcd_mbhc_report_plug_insertion()
364 mbhc->force_linein = true; in wcd_mbhc_report_plug_insertion()
365 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
366 if (mbhc->hph_status) { in wcd_mbhc_report_plug_insertion()
367 mbhc->hph_status &= ~(SND_JACK_HEADSET | in wcd_mbhc_report_plug_insertion()
369 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, in wcd_mbhc_report_plug_insertion()
380 if (is_pa_on && mbhc->force_linein) { in wcd_mbhc_report_plug_insertion()
382 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
383 if (mbhc->hph_status) { in wcd_mbhc_report_plug_insertion()
384 mbhc->hph_status &= ~(SND_JACK_HEADSET | in wcd_mbhc_report_plug_insertion()
386 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, in wcd_mbhc_report_plug_insertion()
391 mbhc->hph_status |= jack_type; in wcd_mbhc_report_plug_insertion()
393 if (jack_type == SND_JACK_HEADPHONE && mbhc->mbhc_cb->mbhc_micb_ramp_control) in wcd_mbhc_report_plug_insertion()
394 mbhc->mbhc_cb->mbhc_micb_ramp_control(mbhc->component, false); in wcd_mbhc_report_plug_insertion()
396 snd_soc_jack_report(mbhc->jack, (mbhc->hph_status | SND_JACK_MECHANICAL), in wcd_mbhc_report_plug_insertion()
400 static void wcd_mbhc_report_plug(struct wcd_mbhc *mbhc, int insertion, in wcd_mbhc_report_plug() argument
404 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_mbhc_report_plug()
407 wcd_mbhc_report_plug_removal(mbhc, jack_type); in wcd_mbhc_report_plug()
409 wcd_mbhc_report_plug_insertion(mbhc, jack_type); in wcd_mbhc_report_plug()
413 static void wcd_cancel_hs_detect_plug(struct wcd_mbhc *mbhc, in wcd_cancel_hs_detect_plug() argument
416 mbhc->hs_detect_work_stop = true; in wcd_cancel_hs_detect_plug()
417 mutex_unlock(&mbhc->lock); in wcd_cancel_hs_detect_plug()
419 mutex_lock(&mbhc->lock); in wcd_cancel_hs_detect_plug()
422 static void wcd_mbhc_cancel_pending_work(struct wcd_mbhc *mbhc) in wcd_mbhc_cancel_pending_work() argument
425 wcd_cancel_btn_work(mbhc); in wcd_mbhc_cancel_pending_work()
427 wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_cancel_pending_work()
430 static void wcd_mbhc_elec_hs_report_unplug(struct wcd_mbhc *mbhc) in wcd_mbhc_elec_hs_report_unplug() argument
432 wcd_mbhc_cancel_pending_work(mbhc); in wcd_mbhc_elec_hs_report_unplug()
434 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT); in wcd_mbhc_elec_hs_report_unplug()
439 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in wcd_mbhc_elec_hs_report_unplug()
440 wcd_mbhc_curr_micbias_control(mbhc, WCD_MBHC_EN_NONE); in wcd_mbhc_elec_hs_report_unplug()
442 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_mbhc_elec_hs_report_unplug()
443 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 3); in wcd_mbhc_elec_hs_report_unplug()
446 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1); in wcd_mbhc_elec_hs_report_unplug()
447 enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_elec_hs_report_unplug()
450 static void wcd_mbhc_find_plug_and_report(struct wcd_mbhc *mbhc, in wcd_mbhc_find_plug_and_report() argument
453 if (mbhc->current_plug == plug_type) in wcd_mbhc_find_plug_and_report()
456 mutex_lock(&mbhc->lock); in wcd_mbhc_find_plug_and_report()
460 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADPHONE); in wcd_mbhc_find_plug_and_report()
463 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_HEADSET); in wcd_mbhc_find_plug_and_report()
466 wcd_mbhc_report_plug(mbhc, 1, SND_JACK_LINEOUT); in wcd_mbhc_find_plug_and_report()
469 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) in wcd_mbhc_find_plug_and_report()
470 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADPHONE); in wcd_mbhc_find_plug_and_report()
471 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) in wcd_mbhc_find_plug_and_report()
472 wcd_mbhc_report_plug(mbhc, 0, SND_JACK_HEADSET); in wcd_mbhc_find_plug_and_report()
476 mbhc->current_plug, plug_type); in wcd_mbhc_find_plug_and_report()
479 mutex_unlock(&mbhc->lock); in wcd_mbhc_find_plug_and_report()
482 static void wcd_schedule_hs_detect_plug(struct wcd_mbhc *mbhc, in wcd_schedule_hs_detect_plug() argument
485 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_schedule_hs_detect_plug()
486 mbhc->hs_detect_work_stop = false; in wcd_schedule_hs_detect_plug()
490 static void wcd_mbhc_adc_detect_plug_type(struct wcd_mbhc *mbhc) in wcd_mbhc_adc_detect_plug_type() argument
492 struct snd_soc_component *component = mbhc->component; in wcd_mbhc_adc_detect_plug_type()
494 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_mbhc_adc_detect_plug_type()
496 if (mbhc->mbhc_cb->hph_pull_down_ctrl) in wcd_mbhc_adc_detect_plug_type()
497 mbhc->mbhc_cb->hph_pull_down_ctrl(component, false); in wcd_mbhc_adc_detect_plug_type()
499 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0); in wcd_mbhc_adc_detect_plug_type()
501 if (mbhc->mbhc_cb->mbhc_micbias_control) { in wcd_mbhc_adc_detect_plug_type()
502 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, in wcd_mbhc_adc_detect_plug_type()
504 wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_adc_detect_plug_type()
512 struct wcd_mbhc *mbhc = data; in wcd_mbhc_mech_plug_detect_irq() local
515 component = mbhc->component; in wcd_mbhc_mech_plug_detect_irq()
516 mutex_lock(&mbhc->lock); in wcd_mbhc_mech_plug_detect_irq()
518 mbhc->in_swch_irq_handler = true; in wcd_mbhc_mech_plug_detect_irq()
520 wcd_mbhc_cancel_pending_work(mbhc); in wcd_mbhc_mech_plug_detect_irq()
522 detection_type = wcd_mbhc_read_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE); in wcd_mbhc_mech_plug_detect_irq()
525 wcd_mbhc_write_field(mbhc, WCD_MBHC_MECH_DETECTION_TYPE, !detection_type); in wcd_mbhc_mech_plug_detect_irq()
528 if (mbhc->mbhc_cb->mbhc_micb_ramp_control) in wcd_mbhc_mech_plug_detect_irq()
529 mbhc->mbhc_cb->mbhc_micb_ramp_control(component, true); in wcd_mbhc_mech_plug_detect_irq()
532 if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE) in wcd_mbhc_mech_plug_detect_irq()
535 mbhc->mbhc_cb->mbhc_bias(component, true); in wcd_mbhc_mech_plug_detect_irq()
536 mbhc->is_btn_press = false; in wcd_mbhc_mech_plug_detect_irq()
537 wcd_mbhc_adc_detect_plug_type(mbhc); in wcd_mbhc_mech_plug_detect_irq()
540 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_mbhc_mech_plug_detect_irq()
541 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_mech_plug_detect_irq()
542 mbhc->extn_cable_hph_rem = false; in wcd_mbhc_mech_plug_detect_irq()
544 if (mbhc->current_plug == MBHC_PLUG_TYPE_NONE) in wcd_mbhc_mech_plug_detect_irq()
547 mbhc->is_btn_press = false; in wcd_mbhc_mech_plug_detect_irq()
548 switch (mbhc->current_plug) { in wcd_mbhc_mech_plug_detect_irq()
556 if (mbhc->mbhc_detection_logic == WCD_DETECTION_ADC) in wcd_mbhc_mech_plug_detect_irq()
557 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 0); in wcd_mbhc_mech_plug_detect_irq()
561 dev_err(mbhc->dev, "Ground and Mic Swapped on plug\n"); in wcd_mbhc_mech_plug_detect_irq()
564 dev_err(mbhc->dev, "Invalid current plug: %d\n", in wcd_mbhc_mech_plug_detect_irq()
565 mbhc->current_plug); in wcd_mbhc_mech_plug_detect_irq()
568 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in wcd_mbhc_mech_plug_detect_irq()
569 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_mech_plug_detect_irq()
570 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_DETECTION_TYPE, 1); in wcd_mbhc_mech_plug_detect_irq()
571 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0); in wcd_mbhc_mech_plug_detect_irq()
572 wcd_mbhc_report_plug(mbhc, 0, jack_type); in wcd_mbhc_mech_plug_detect_irq()
576 mbhc->in_swch_irq_handler = false; in wcd_mbhc_mech_plug_detect_irq()
577 mutex_unlock(&mbhc->lock); in wcd_mbhc_mech_plug_detect_irq()
581 static int wcd_mbhc_get_button_mask(struct wcd_mbhc *mbhc) in wcd_mbhc_get_button_mask() argument
586 btn = wcd_mbhc_read_field(mbhc, WCD_MBHC_BTN_RESULT); in wcd_mbhc_get_button_mask()
617 struct wcd_mbhc *mbhc = container_of(dwork, struct wcd_mbhc, mbhc_btn_dwork); in wcd_btn_long_press_fn() local
619 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) in wcd_btn_long_press_fn()
620 snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed, in wcd_btn_long_press_fn()
621 mbhc->buttons_pressed); in wcd_btn_long_press_fn()
626 struct wcd_mbhc *mbhc = data; in wcd_mbhc_btn_press_handler() local
630 mutex_lock(&mbhc->lock); in wcd_mbhc_btn_press_handler()
631 wcd_cancel_btn_work(mbhc); in wcd_mbhc_btn_press_handler()
632 mbhc->is_btn_press = true; in wcd_mbhc_btn_press_handler()
633 msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport); in wcd_mbhc_btn_press_handler()
640 if (mbhc->in_swch_irq_handler) in wcd_mbhc_btn_press_handler()
644 if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) in wcd_mbhc_btn_press_handler()
647 mask = wcd_mbhc_get_button_mask(mbhc); in wcd_mbhc_btn_press_handler()
648 mbhc->buttons_pressed |= mask; in wcd_mbhc_btn_press_handler()
649 if (schedule_delayed_work(&mbhc->mbhc_btn_dwork, msecs_to_jiffies(400)) == 0) in wcd_mbhc_btn_press_handler()
652 mutex_unlock(&mbhc->lock); in wcd_mbhc_btn_press_handler()
658 struct wcd_mbhc *mbhc = data; in wcd_mbhc_btn_release_handler() local
661 mutex_lock(&mbhc->lock); in wcd_mbhc_btn_release_handler()
662 if (mbhc->is_btn_press) in wcd_mbhc_btn_release_handler()
663 mbhc->is_btn_press = false; in wcd_mbhc_btn_release_handler()
667 if (!(mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK)) in wcd_mbhc_btn_release_handler()
670 ret = wcd_cancel_btn_work(mbhc); in wcd_mbhc_btn_release_handler()
672 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
674 if (!mbhc->in_swch_irq_handler) { in wcd_mbhc_btn_release_handler()
676 snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed, in wcd_mbhc_btn_release_handler()
677 mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
678 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
681 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK; in wcd_mbhc_btn_release_handler()
683 mutex_unlock(&mbhc->lock); in wcd_mbhc_btn_release_handler()
688 static irqreturn_t wcd_mbhc_hph_ocp_irq(struct wcd_mbhc *mbhc, bool hphr) in wcd_mbhc_hph_ocp_irq() argument
692 dev_err(mbhc->dev, "MBHC Over Current on %s detected\n", in wcd_mbhc_hph_ocp_irq()
695 wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 0); in wcd_mbhc_hph_ocp_irq()
696 wcd_mbhc_write_field(mbhc, WCD_MBHC_OCP_FSM_EN, 1); in wcd_mbhc_hph_ocp_irq()
711 static int wcd_mbhc_initialise(struct wcd_mbhc *mbhc) in wcd_mbhc_initialise() argument
713 struct snd_soc_component *component = mbhc->component; in wcd_mbhc_initialise()
715 mutex_lock(&mbhc->lock); in wcd_mbhc_initialise()
718 if (mbhc->mbhc_cb->hph_pull_up_control_v2) in wcd_mbhc_initialise()
719 mbhc->mbhc_cb->hph_pull_up_control_v2(component, in wcd_mbhc_initialise()
721 else if (mbhc->mbhc_cb->hph_pull_up_control) in wcd_mbhc_initialise()
722 mbhc->mbhc_cb->hph_pull_up_control(component, I_DEFAULT); in wcd_mbhc_initialise()
724 wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_CTRL, 3); in wcd_mbhc_initialise()
726 wcd_mbhc_write_field(mbhc, WCD_MBHC_HPHL_PLUG_TYPE, mbhc->cfg->hphl_swh); in wcd_mbhc_initialise()
727 wcd_mbhc_write_field(mbhc, WCD_MBHC_GND_PLUG_TYPE, mbhc->cfg->gnd_swh); in wcd_mbhc_initialise()
728 wcd_mbhc_write_field(mbhc, WCD_MBHC_SW_HPH_LP_100K_TO_GND, 1); in wcd_mbhc_initialise()
729 if (mbhc->cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl) in wcd_mbhc_initialise()
730 mbhc->mbhc_cb->mbhc_gnd_det_ctrl(component, true); in wcd_mbhc_initialise()
731 wcd_mbhc_write_field(mbhc, WCD_MBHC_HS_L_DET_PULL_UP_COMP_CTRL, 1); in wcd_mbhc_initialise()
733 wcd_mbhc_write_field(mbhc, WCD_MBHC_L_DET_EN, 1); in wcd_mbhc_initialise()
736 wcd_mbhc_write_field(mbhc, WCD_MBHC_INSREM_DBNC, 6); in wcd_mbhc_initialise()
739 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_DBNC, 2); in wcd_mbhc_initialise()
742 mbhc->mbhc_cb->mbhc_bias(component, true); in wcd_mbhc_initialise()
744 if (mbhc->mbhc_cb->clk_setup) in wcd_mbhc_initialise()
745 mbhc->mbhc_cb->clk_setup(component, true); in wcd_mbhc_initialise()
748 wcd_program_hs_vref(mbhc); in wcd_mbhc_initialise()
750 wcd_program_btn_threshold(mbhc, false); in wcd_mbhc_initialise()
752 mutex_unlock(&mbhc->lock); in wcd_mbhc_initialise()
757 static int wcd_mbhc_get_micbias(struct wcd_mbhc *mbhc) in wcd_mbhc_get_micbias() argument
761 if (mbhc->mbhc_cb->get_micbias_val) { in wcd_mbhc_get_micbias()
762 mbhc->mbhc_cb->get_micbias_val(mbhc->component, &micbias); in wcd_mbhc_get_micbias()
766 vout_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_MICB2_VOUT); in wcd_mbhc_get_micbias()
783 static int wcd_measure_adc_continuous(struct wcd_mbhc *mbhc) in wcd_measure_adc_continuous() argument
792 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0x00); in wcd_measure_adc_continuous()
794 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 1); in wcd_measure_adc_continuous()
796 adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN); in wcd_measure_adc_continuous()
798 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0); in wcd_measure_adc_continuous()
800 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_measure_adc_continuous()
802 wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_IN2P); in wcd_measure_adc_continuous()
804 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_measure_adc_continuous()
806 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1); in wcd_measure_adc_continuous()
811 adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT); in wcd_measure_adc_continuous()
815 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en); in wcd_measure_adc_continuous()
817 output_mv = wcd_get_voltage_from_adc(adc_result, wcd_mbhc_get_micbias(mbhc)); in wcd_measure_adc_continuous()
822 static int wcd_measure_adc_once(struct wcd_mbhc *mbhc, int mux_ctl) in wcd_measure_adc_once() argument
824 struct device *dev = mbhc->dev; in wcd_measure_adc_once()
833 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); in wcd_measure_adc_once()
835 adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN); in wcd_measure_adc_once()
837 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0); in wcd_measure_adc_once()
838 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_measure_adc_once()
840 wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, mux_ctl); in wcd_measure_adc_once()
841 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_measure_adc_once()
842 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 1); in wcd_measure_adc_once()
849 adc_timeout = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_TIMEOUT); in wcd_measure_adc_once()
854 adc_complete = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_COMPLETE); in wcd_measure_adc_once()
859 adc_result = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_RESULT); in wcd_measure_adc_once()
863 wcd_mbhc_get_micbias(mbhc)); in wcd_measure_adc_once()
868 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en); in wcd_measure_adc_once()
882 static int wcd_check_cross_conn(struct wcd_mbhc *mbhc) in wcd_check_cross_conn() argument
889 if (wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN)) in wcd_check_cross_conn()
893 elect_ctl = wcd_mbhc_read_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC); in wcd_check_cross_conn()
894 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, 0); in wcd_check_cross_conn()
897 adc_mode = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_MODE); in wcd_check_cross_conn()
899 adc_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_ADC_EN); in wcd_check_cross_conn()
901 fsm_en = wcd_mbhc_read_field(mbhc, WCD_MBHC_FSM_EN); in wcd_check_cross_conn()
904 hphl_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_L); in wcd_check_cross_conn()
909 hphr_adc_res = wcd_measure_adc_once(mbhc, MUX_CTL_HPH_R); in wcd_check_cross_conn()
917 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 0); in wcd_check_cross_conn()
919 wcd_mbhc_write_field(mbhc, WCD_MBHC_MUX_CTL, MUX_CTL_AUTO); in wcd_check_cross_conn()
920 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, 1); in wcd_check_cross_conn()
922 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, adc_en); in wcd_check_cross_conn()
924 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, adc_mode); in wcd_check_cross_conn()
926 wcd_mbhc_write_field(mbhc, WCD_MBHC_FSM_EN, fsm_en); in wcd_check_cross_conn()
928 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_SCHMT_ISRC, elect_ctl); in wcd_check_cross_conn()
933 static int wcd_mbhc_adc_get_hs_thres(struct wcd_mbhc *mbhc) in wcd_mbhc_adc_get_hs_thres() argument
937 micbias_mv = wcd_mbhc_get_micbias(mbhc); in wcd_mbhc_adc_get_hs_thres()
938 if (mbhc->cfg->hs_thr) { in wcd_mbhc_adc_get_hs_thres()
939 if (mbhc->cfg->micb_mv == micbias_mv) in wcd_mbhc_adc_get_hs_thres()
940 hs_threshold = mbhc->cfg->hs_thr; in wcd_mbhc_adc_get_hs_thres()
942 hs_threshold = (mbhc->cfg->hs_thr * in wcd_mbhc_adc_get_hs_thres()
943 micbias_mv) / mbhc->cfg->micb_mv; in wcd_mbhc_adc_get_hs_thres()
951 static int wcd_mbhc_adc_get_hph_thres(struct wcd_mbhc *mbhc) in wcd_mbhc_adc_get_hph_thres() argument
955 micbias_mv = wcd_mbhc_get_micbias(mbhc); in wcd_mbhc_adc_get_hph_thres()
956 if (mbhc->cfg->hph_thr) { in wcd_mbhc_adc_get_hph_thres()
957 if (mbhc->cfg->micb_mv == micbias_mv) in wcd_mbhc_adc_get_hph_thres()
958 hph_threshold = mbhc->cfg->hph_thr; in wcd_mbhc_adc_get_hph_thres()
960 hph_threshold = (mbhc->cfg->hph_thr * in wcd_mbhc_adc_get_hph_thres()
961 micbias_mv) / mbhc->cfg->micb_mv; in wcd_mbhc_adc_get_hph_thres()
969 static void wcd_mbhc_adc_update_fsm_source(struct wcd_mbhc *mbhc, in wcd_mbhc_adc_update_fsm_source() argument
976 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3); in wcd_mbhc_adc_update_fsm_source()
979 if (mbhc->mbhc_cb->micbias_enable_status) in wcd_mbhc_adc_update_fsm_source()
980 micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc->component, in wcd_mbhc_adc_update_fsm_source()
983 if (!mbhc->is_hs_recording && !micbias2) in wcd_mbhc_adc_update_fsm_source()
984 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 3); in wcd_mbhc_adc_update_fsm_source()
987 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_adc_update_fsm_source()
993 static void wcd_mbhc_bcs_enable(struct wcd_mbhc *mbhc, int plug_type, bool enable) in wcd_mbhc_bcs_enable() argument
998 if (mbhc->mbhc_cb->bcs_enable) in wcd_mbhc_bcs_enable()
999 mbhc->mbhc_cb->bcs_enable(mbhc->component, enable); in wcd_mbhc_bcs_enable()
1006 static int wcd_mbhc_get_plug_from_adc(struct wcd_mbhc *mbhc, int adc_result) in wcd_mbhc_get_plug_from_adc() argument
1012 hs_thr = wcd_mbhc_adc_get_hs_thres(mbhc); in wcd_mbhc_get_plug_from_adc()
1013 hph_thr = wcd_mbhc_adc_get_hph_thres(mbhc); in wcd_mbhc_get_plug_from_adc()
1027 struct wcd_mbhc *mbhc; in wcd_correct_swch_plug() local
1035 mbhc = container_of(work, struct wcd_mbhc, correct_plug_swch); in wcd_correct_swch_plug()
1036 component = mbhc->component; in wcd_correct_swch_plug()
1038 hs_threshold = wcd_mbhc_adc_get_hs_thres(mbhc); in wcd_correct_swch_plug()
1041 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_correct_swch_plug()
1045 cross_conn = wcd_check_cross_conn(mbhc); in wcd_correct_swch_plug()
1051 dev_err(mbhc->dev, "cross connection found, Plug type %d\n", in wcd_correct_swch_plug()
1057 output_mv = wcd_measure_adc_continuous(mbhc); in wcd_correct_swch_plug()
1058 plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); in wcd_correct_swch_plug()
1066 wcd_mbhc_find_plug_and_report(mbhc, plug_type); in wcd_correct_swch_plug()
1069 wcd_mbhc_find_plug_and_report(mbhc, plug_type); in wcd_correct_swch_plug()
1070 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); in wcd_correct_swch_plug()
1071 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0); in wcd_correct_swch_plug()
1072 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1); in wcd_correct_swch_plug()
1081 wcd_mbhc_bcs_enable(mbhc, plug_type, false); in wcd_correct_swch_plug()
1086 if (mbhc->hs_detect_work_stop) { in wcd_correct_swch_plug()
1087 wcd_micbias_disable(mbhc); in wcd_correct_swch_plug()
1096 output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); in wcd_correct_swch_plug()
1097 plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); in wcd_correct_swch_plug()
1098 is_pa_on = wcd_mbhc_read_field(mbhc, WCD_MBHC_HPH_PA_EN); in wcd_correct_swch_plug()
1102 cross_conn = wcd_check_cross_conn(mbhc); in wcd_correct_swch_plug()
1111 plug_type = wcd_mbhc_get_plug_from_adc(mbhc, output_mv); in wcd_correct_swch_plug()
1118 if (mbhc->cfg->swap_gnd_mic) { in wcd_correct_swch_plug()
1119 if (mbhc->cfg->swap_gnd_mic(component, true)) in wcd_correct_swch_plug()
1129 wcd_mbhc_bcs_enable(mbhc, plug_type, true); in wcd_correct_swch_plug()
1132 wcd_mbhc_write_field(mbhc, WCD_MBHC_ELECT_ISRC_EN, 1); in wcd_correct_swch_plug()
1134 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); in wcd_correct_swch_plug()
1135 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0); in wcd_correct_swch_plug()
1136 wcd_mbhc_find_plug_and_report(mbhc, plug_type); in wcd_correct_swch_plug()
1144 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1); in wcd_correct_swch_plug()
1146 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0); in wcd_correct_swch_plug()
1148 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_correct_swch_plug()
1149 wcd_mbhc_adc_update_fsm_source(mbhc, plug_type); in wcd_correct_swch_plug()
1152 if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) in wcd_correct_swch_plug()
1153 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE); in wcd_correct_swch_plug()
1161 wcd_micbias_disable(mbhc); in wcd_correct_swch_plug()
1167 enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_correct_swch_plug()
1170 if (mbhc->mbhc_cb->hph_pull_down_ctrl) in wcd_correct_swch_plug()
1171 mbhc->mbhc_cb->hph_pull_down_ctrl(component, true); in wcd_correct_swch_plug()
1176 struct wcd_mbhc *mbhc = data; in wcd_mbhc_adc_hs_rem_irq() local
1181 mutex_lock(&mbhc->lock); in wcd_mbhc_adc_hs_rem_irq()
1183 adc_threshold = wcd_mbhc_adc_get_hs_thres(mbhc); in wcd_mbhc_adc_hs_rem_irq()
1192 output_mv = wcd_measure_adc_once(mbhc, MUX_CTL_IN2P); in wcd_mbhc_adc_hs_rem_irq()
1204 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) in wcd_mbhc_adc_hs_rem_irq()
1205 mbhc->extn_cable_hph_rem = true; in wcd_mbhc_adc_hs_rem_irq()
1207 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 0); in wcd_mbhc_adc_hs_rem_irq()
1208 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_MODE, 0); in wcd_mbhc_adc_hs_rem_irq()
1209 wcd_mbhc_write_field(mbhc, WCD_MBHC_ADC_EN, 0); in wcd_mbhc_adc_hs_rem_irq()
1210 wcd_mbhc_elec_hs_report_unplug(mbhc); in wcd_mbhc_adc_hs_rem_irq()
1211 wcd_mbhc_write_field(mbhc, WCD_MBHC_BTN_ISRC_CTL, 0); in wcd_mbhc_adc_hs_rem_irq()
1215 wcd_mbhc_write_field(mbhc, WCD_MBHC_HPH_PA_EN, 3); in wcd_mbhc_adc_hs_rem_irq()
1218 mutex_unlock(&mbhc->lock); in wcd_mbhc_adc_hs_rem_irq()
1224 struct wcd_mbhc *mbhc = data; in wcd_mbhc_adc_hs_ins_irq() local
1233 if (mbhc->extn_cable_hph_rem == true) { in wcd_mbhc_adc_hs_ins_irq()
1234 mbhc->extn_cable_hph_rem = false; in wcd_mbhc_adc_hs_ins_irq()
1239 clamp_state = wcd_mbhc_read_field(mbhc, WCD_MBHC_IN2P_CLAMP_STATE); in wcd_mbhc_adc_hs_ins_irq()
1254 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) { in wcd_mbhc_adc_hs_ins_irq()
1255 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_adc_hs_ins_irq()
1256 wcd_mbhc_write_field(mbhc, WCD_MBHC_DETECTION_DONE, 1); in wcd_mbhc_adc_hs_ins_irq()
1257 wcd_mbhc_find_plug_and_report(mbhc, MBHC_PLUG_TYPE_HEADSET); in wcd_mbhc_adc_hs_ins_irq()
1264 int wcd_mbhc_get_impedance(struct wcd_mbhc *mbhc, uint32_t *zl, uint32_t *zr) in wcd_mbhc_get_impedance() argument
1266 *zl = mbhc->zl; in wcd_mbhc_get_impedance()
1267 *zr = mbhc->zr; in wcd_mbhc_get_impedance()
1276 void wcd_mbhc_set_hph_type(struct wcd_mbhc *mbhc, int hph_type) in wcd_mbhc_set_hph_type() argument
1278 mbhc->hph_type = hph_type; in wcd_mbhc_set_hph_type()
1282 int wcd_mbhc_get_hph_type(struct wcd_mbhc *mbhc) in wcd_mbhc_get_hph_type() argument
1284 return mbhc->hph_type; in wcd_mbhc_get_hph_type()
1288 int wcd_mbhc_start(struct wcd_mbhc *mbhc, struct wcd_mbhc_config *cfg, in wcd_mbhc_start() argument
1291 if (!mbhc || !cfg || !jack) in wcd_mbhc_start()
1294 mbhc->cfg = cfg; in wcd_mbhc_start()
1295 mbhc->jack = jack; in wcd_mbhc_start()
1297 return wcd_mbhc_initialise(mbhc); in wcd_mbhc_start()
1301 void wcd_mbhc_stop(struct wcd_mbhc *mbhc) in wcd_mbhc_stop() argument
1303 mbhc->current_plug = MBHC_PLUG_TYPE_NONE; in wcd_mbhc_stop()
1304 mbhc->hph_status = 0; in wcd_mbhc_stop()
1305 disable_irq_nosync(mbhc->intr_ids->hph_left_ocp); in wcd_mbhc_stop()
1306 disable_irq_nosync(mbhc->intr_ids->hph_right_ocp); in wcd_mbhc_stop()
1365 struct wcd_mbhc *mbhc; in wcd_mbhc_init() local
1373 mbhc = devm_kzalloc(dev, sizeof(*mbhc), GFP_KERNEL); in wcd_mbhc_init()
1374 if (!mbhc) in wcd_mbhc_init()
1377 mbhc->component = component; in wcd_mbhc_init()
1378 mbhc->dev = dev; in wcd_mbhc_init()
1379 mbhc->intr_ids = intr_ids; in wcd_mbhc_init()
1380 mbhc->mbhc_cb = mbhc_cb; in wcd_mbhc_init()
1381 mbhc->fields = fields; in wcd_mbhc_init()
1382 mbhc->mbhc_detection_logic = WCD_DETECTION_ADC; in wcd_mbhc_init()
1385 mbhc->impedance_detect = impedance_det_en; in wcd_mbhc_init()
1387 INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_long_press_fn); in wcd_mbhc_init()
1389 mutex_init(&mbhc->lock); in wcd_mbhc_init()
1391 INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug); in wcd_mbhc_init()
1393 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_sw_intr, NULL, in wcd_mbhc_init()
1396 "mbhc sw intr", mbhc); in wcd_mbhc_init()
1400 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_press_intr, NULL, in wcd_mbhc_init()
1403 "Button Press detect", mbhc); in wcd_mbhc_init()
1407 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_btn_release_intr, NULL, in wcd_mbhc_init()
1410 "Button Release detect", mbhc); in wcd_mbhc_init()
1414 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_ins_intr, NULL, in wcd_mbhc_init()
1417 "Elect Insert", mbhc); in wcd_mbhc_init()
1421 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_init()
1423 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->mbhc_hs_rem_intr, NULL, in wcd_mbhc_init()
1426 "Elect Remove", mbhc); in wcd_mbhc_init()
1430 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in wcd_mbhc_init()
1432 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_left_ocp, NULL, in wcd_mbhc_init()
1435 "HPH_L OCP detect", mbhc); in wcd_mbhc_init()
1439 ret = devm_request_threaded_irq(dev, mbhc->intr_ids->hph_right_ocp, NULL, in wcd_mbhc_init()
1442 "HPH_R OCP detect", mbhc); in wcd_mbhc_init()
1446 return mbhc; in wcd_mbhc_init()
1454 void wcd_mbhc_deinit(struct wcd_mbhc *mbhc) in wcd_mbhc_deinit() argument
1456 mutex_lock(&mbhc->lock); in wcd_mbhc_deinit()
1457 wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_deinit()
1458 mutex_unlock(&mbhc->lock); in wcd_mbhc_deinit()