Lines Matching +full:disable +full:- +full:report +full:- +full:mask
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
14 #include "wcd-mbhc-v2.h"
54 /* Delayed work to report long button press */
56 /* Work to handle plug report */
76 /* Holds type of Headset - Mono/Stereo */
78 /* Holds mbhc detection method - ADC/Legacy */
85 if (!mbhc->fields[field].reg) in wcd_mbhc_write_field()
88 return snd_soc_component_write_field(mbhc->component, in wcd_mbhc_write_field()
89 mbhc->fields[field].reg, in wcd_mbhc_write_field()
90 mbhc->fields[field].mask, val); in wcd_mbhc_write_field()
95 if (!mbhc->fields[field].reg) in wcd_mbhc_read_field()
98 return snd_soc_component_read_field(mbhc->component, in wcd_mbhc_read_field()
99 mbhc->fields[field].reg, in wcd_mbhc_read_field()
100 mbhc->fields[field].mask); in wcd_mbhc_read_field()
105 u32 reg_val = ((mbhc->cfg->v_hs_max - HS_VREF_MIN_VAL) / 100); in wcd_program_hs_vref()
112 struct snd_soc_component *component = mbhc->component; in wcd_program_btn_threshold()
114 mbhc->mbhc_cb->set_btn_thr(component, mbhc->cfg->btn_low, in wcd_program_btn_threshold()
115 mbhc->cfg->btn_high, in wcd_program_btn_threshold()
116 mbhc->cfg->num_btn, micbias); in wcd_program_btn_threshold()
129 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_mbhc_curr_micbias_control()
142 /* Disable PULL_UP_EN & enable MICBIAS */ in wcd_mbhc_curr_micbias_control()
160 dev_err(mbhc->dev, "%s: Invalid parameter", __func__); in wcd_mbhc_curr_micbias_control()
174 component = mbhc->component; in wcd_mbhc_event_notify()
176 if (mbhc->mbhc_cb->micbias_enable_status) in wcd_mbhc_event_notify()
177 micbias2 = mbhc->mbhc_cb->micbias_enable_status(component, MIC_BIAS_2); in wcd_mbhc_event_notify()
182 mbhc->is_hs_recording = true; in wcd_mbhc_event_notify()
185 /* Disable current source if micbias2 enabled */ in wcd_mbhc_event_notify()
186 if (mbhc->mbhc_cb->mbhc_micbias_control) { in wcd_mbhc_event_notify()
190 mbhc->is_hs_recording = true; in wcd_mbhc_event_notify()
200 if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) { in wcd_mbhc_event_notify()
207 mbhc->is_hs_recording = false; in wcd_mbhc_event_notify()
210 if (!mbhc->mbhc_cb->mbhc_micbias_control) in wcd_mbhc_event_notify()
211 mbhc->is_hs_recording = false; in wcd_mbhc_event_notify()
214 if ((test_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state)) || in wcd_mbhc_event_notify()
215 (test_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state))) in wcd_mbhc_event_notify()
216 /* enable pullup and cs, disable mb */ in wcd_mbhc_event_notify()
219 /* enable current source and disable mb, pullup*/ in wcd_mbhc_event_notify()
224 clear_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); in wcd_mbhc_event_notify()
228 /* Disable cs, pullup & enable micbias */ in wcd_mbhc_event_notify()
231 /* Disable micbias, pullup & enable cs */ in wcd_mbhc_event_notify()
235 clear_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); in wcd_mbhc_event_notify()
238 /* Disable cs, pullup & enable micbias */ in wcd_mbhc_event_notify()
241 /* Disable micbias, pullup & enable cs */ in wcd_mbhc_event_notify()
245 set_bit(WCD_MBHC_EVENT_PA_HPHL, &mbhc->event_state); in wcd_mbhc_event_notify()
248 /* Disable cs, pullup & enable micbias */ in wcd_mbhc_event_notify()
251 /* Disable micbias, enable pullup & cs */ in wcd_mbhc_event_notify()
255 set_bit(WCD_MBHC_EVENT_PA_HPHR, &mbhc->event_state); in wcd_mbhc_event_notify()
258 /* Disable cs, pullup & enable micbias */ in wcd_mbhc_event_notify()
261 /* Disable micbias, enable pullup & cs */ in wcd_mbhc_event_notify()
273 return cancel_delayed_work_sync(&mbhc->mbhc_btn_dwork); in wcd_cancel_btn_work()
278 struct snd_soc_component *component = mbhc->component; in wcd_micbias_disable()
280 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_micbias_disable()
281 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE); in wcd_micbias_disable()
283 if (mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) in wcd_micbias_disable()
284 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(component, MIC_BIAS_2, false); in wcd_micbias_disable()
286 if (mbhc->mbhc_cb->set_micbias_value) { in wcd_micbias_disable()
287 mbhc->mbhc_cb->set_micbias_value(component); in wcd_micbias_disable()
295 mbhc->hph_status &= ~jack_type; in wcd_mbhc_report_plug_removal()
298 * report release if we reported button press in wcd_mbhc_report_plug_removal()
300 if (!wcd_cancel_btn_work(mbhc) && mbhc->buttons_pressed) { in wcd_mbhc_report_plug_removal()
301 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_report_plug_removal()
302 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK; in wcd_mbhc_report_plug_removal()
306 mbhc->hph_type = WCD_MBHC_HPH_NONE; in wcd_mbhc_report_plug_removal()
307 mbhc->zl = mbhc->zr = 0; in wcd_mbhc_report_plug_removal()
308 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, WCD_MBHC_JACK_MASK); in wcd_mbhc_report_plug_removal()
309 mbhc->current_plug = MBHC_PLUG_TYPE_NONE; in wcd_mbhc_report_plug_removal()
310 mbhc->force_linein = false; in wcd_mbhc_report_plug_removal()
316 if (!mbhc->impedance_detect) in wcd_mbhc_compute_impedance()
319 if (mbhc->cfg->linein_th != 0) { in wcd_mbhc_compute_impedance()
321 /* Set MUX_CTL to AUTO for Z-det */ in wcd_mbhc_compute_impedance()
326 mbhc->mbhc_cb->compute_impedance(mbhc->component, &mbhc->zl, &mbhc->zr); in wcd_mbhc_compute_impedance()
336 * Report removal of current jack type. in wcd_mbhc_report_plug_insertion()
337 * Headphone to headset shouldn't report headphone in wcd_mbhc_report_plug_insertion()
340 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET && in wcd_mbhc_report_plug_insertion()
342 mbhc->hph_status &= ~SND_JACK_HEADSET; in wcd_mbhc_report_plug_insertion()
344 /* Report insertion */ in wcd_mbhc_report_plug_insertion()
347 mbhc->current_plug = MBHC_PLUG_TYPE_HEADPHONE; in wcd_mbhc_report_plug_insertion()
350 mbhc->current_plug = MBHC_PLUG_TYPE_HEADSET; in wcd_mbhc_report_plug_insertion()
351 mbhc->jiffies_atreport = jiffies; in wcd_mbhc_report_plug_insertion()
354 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
365 if ((mbhc->zl > mbhc->cfg->linein_th) && in wcd_mbhc_report_plug_insertion()
366 (mbhc->zr > mbhc->cfg->linein_th) && in wcd_mbhc_report_plug_insertion()
369 mbhc->force_linein = true; in wcd_mbhc_report_plug_insertion()
370 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
371 if (mbhc->hph_status) { in wcd_mbhc_report_plug_insertion()
372 mbhc->hph_status &= ~(SND_JACK_HEADSET | in wcd_mbhc_report_plug_insertion()
374 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, in wcd_mbhc_report_plug_insertion()
385 if (is_pa_on && mbhc->force_linein) { in wcd_mbhc_report_plug_insertion()
387 mbhc->current_plug = MBHC_PLUG_TYPE_HIGH_HPH; in wcd_mbhc_report_plug_insertion()
388 if (mbhc->hph_status) { in wcd_mbhc_report_plug_insertion()
389 mbhc->hph_status &= ~(SND_JACK_HEADSET | in wcd_mbhc_report_plug_insertion()
391 snd_soc_jack_report(mbhc->jack, mbhc->hph_status, in wcd_mbhc_report_plug_insertion()
396 mbhc->hph_status |= jack_type; in wcd_mbhc_report_plug_insertion()
398 if (jack_type == SND_JACK_HEADPHONE && mbhc->mbhc_cb->mbhc_micb_ramp_control) in wcd_mbhc_report_plug_insertion()
399 mbhc->mbhc_cb->mbhc_micb_ramp_control(mbhc->component, false); in wcd_mbhc_report_plug_insertion()
401 snd_soc_jack_report(mbhc->jack, (mbhc->hph_status | SND_JACK_MECHANICAL), in wcd_mbhc_report_plug_insertion()
409 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_mbhc_report_plug()
411 if (!insertion) /* Report removal */ in wcd_mbhc_report_plug()
421 mbhc->hs_detect_work_stop = true; in wcd_cancel_hs_detect_plug()
422 mutex_unlock(&mbhc->lock); in wcd_cancel_hs_detect_plug()
424 mutex_lock(&mbhc->lock); in wcd_cancel_hs_detect_plug()
432 wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_cancel_pending_work()
438 /* Report extension cable */ in wcd_mbhc_elec_hs_report_unplug()
441 * Disable HPHL trigger and MIC Schmitt triggers. in wcd_mbhc_elec_hs_report_unplug()
444 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in wcd_mbhc_elec_hs_report_unplug()
446 /* Disable HW FSM */ in wcd_mbhc_elec_hs_report_unplug()
452 enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_elec_hs_report_unplug()
458 if (mbhc->current_plug == plug_type) in wcd_mbhc_find_plug_and_report()
461 mutex_lock(&mbhc->lock); in wcd_mbhc_find_plug_and_report()
474 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) in wcd_mbhc_find_plug_and_report()
476 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) in wcd_mbhc_find_plug_and_report()
481 mbhc->current_plug, plug_type); in wcd_mbhc_find_plug_and_report()
484 mutex_unlock(&mbhc->lock); in wcd_mbhc_find_plug_and_report()
490 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_schedule_hs_detect_plug()
491 mbhc->hs_detect_work_stop = false; in wcd_schedule_hs_detect_plug()
497 struct snd_soc_component *component = mbhc->component; in wcd_mbhc_adc_detect_plug_type()
499 WARN_ON(!mutex_is_locked(&mbhc->lock)); in wcd_mbhc_adc_detect_plug_type()
501 if (mbhc->mbhc_cb->hph_pull_down_ctrl) in wcd_mbhc_adc_detect_plug_type()
502 mbhc->mbhc_cb->hph_pull_down_ctrl(component, false); in wcd_mbhc_adc_detect_plug_type()
506 if (mbhc->mbhc_cb->mbhc_micbias_control) { in wcd_mbhc_adc_detect_plug_type()
507 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, in wcd_mbhc_adc_detect_plug_type()
509 wcd_schedule_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_adc_detect_plug_type()
516 struct snd_soc_component *component = mbhc->component; in mbhc_plug_detect_fn()
520 mutex_lock(&mbhc->lock); in mbhc_plug_detect_fn()
522 mbhc->in_swch_irq_handler = true; in mbhc_plug_detect_fn()
532 if (mbhc->mbhc_cb->mbhc_micb_ramp_control) in mbhc_plug_detect_fn()
533 mbhc->mbhc_cb->mbhc_micb_ramp_control(component, true); in mbhc_plug_detect_fn()
536 if (mbhc->current_plug != MBHC_PLUG_TYPE_NONE) in mbhc_plug_detect_fn()
539 mbhc->mbhc_cb->mbhc_bias(component, true); in mbhc_plug_detect_fn()
540 mbhc->is_btn_press = false; in mbhc_plug_detect_fn()
543 /* Disable HW FSM */ in mbhc_plug_detect_fn()
546 mbhc->extn_cable_hph_rem = false; in mbhc_plug_detect_fn()
548 if (mbhc->current_plug == MBHC_PLUG_TYPE_NONE) in mbhc_plug_detect_fn()
551 mbhc->is_btn_press = false; in mbhc_plug_detect_fn()
552 switch (mbhc->current_plug) { in mbhc_plug_detect_fn()
560 if (mbhc->mbhc_detection_logic == WCD_DETECTION_ADC) in mbhc_plug_detect_fn()
565 dev_err(mbhc->dev, "Ground and Mic Swapped on plug\n"); in mbhc_plug_detect_fn()
568 dev_err(mbhc->dev, "Invalid current plug: %d\n", in mbhc_plug_detect_fn()
569 mbhc->current_plug); in mbhc_plug_detect_fn()
572 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in mbhc_plug_detect_fn()
573 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in mbhc_plug_detect_fn()
580 mbhc->in_swch_irq_handler = false; in mbhc_plug_detect_fn()
581 mutex_unlock(&mbhc->lock); in mbhc_plug_detect_fn()
588 if (!mbhc->cfg->typec_analog_mux) in wcd_mbhc_mech_plug_detect_irq()
589 schedule_work(&mbhc->mbhc_plug_detect_work); in wcd_mbhc_mech_plug_detect_irq()
597 if (!mbhc || !mbhc->cfg->typec_analog_mux) in wcd_mbhc_typec_report_unplug()
598 return -EINVAL; in wcd_mbhc_typec_report_unplug()
600 if (mbhc->mbhc_cb->clk_setup) in wcd_mbhc_typec_report_unplug()
601 mbhc->mbhc_cb->clk_setup(mbhc->component, false); in wcd_mbhc_typec_report_unplug()
606 schedule_work(&mbhc->mbhc_plug_detect_work); in wcd_mbhc_typec_report_unplug()
614 if (!mbhc || !mbhc->cfg->typec_analog_mux) in wcd_mbhc_typec_report_plug()
615 return -EINVAL; in wcd_mbhc_typec_report_plug()
617 if (mbhc->mbhc_cb->clk_setup) in wcd_mbhc_typec_report_plug()
618 mbhc->mbhc_cb->clk_setup(mbhc->component, true); in wcd_mbhc_typec_report_plug()
621 schedule_work(&mbhc->mbhc_plug_detect_work); in wcd_mbhc_typec_report_plug()
629 int mask = 0; in wcd_mbhc_get_button_mask() local
636 mask = SND_JACK_BTN_0; in wcd_mbhc_get_button_mask()
639 mask = SND_JACK_BTN_1; in wcd_mbhc_get_button_mask()
642 mask = SND_JACK_BTN_2; in wcd_mbhc_get_button_mask()
645 mask = SND_JACK_BTN_3; in wcd_mbhc_get_button_mask()
648 mask = SND_JACK_BTN_4; in wcd_mbhc_get_button_mask()
651 mask = SND_JACK_BTN_5; in wcd_mbhc_get_button_mask()
657 return mask; in wcd_mbhc_get_button_mask()
665 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADSET) in wcd_btn_long_press_fn()
666 snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed, in wcd_btn_long_press_fn()
667 mbhc->buttons_pressed); in wcd_btn_long_press_fn()
673 int mask; in wcd_mbhc_btn_press_handler() local
676 mutex_lock(&mbhc->lock); in wcd_mbhc_btn_press_handler()
678 mbhc->is_btn_press = true; in wcd_mbhc_btn_press_handler()
679 msec_val = jiffies_to_msecs(jiffies - mbhc->jiffies_atreport); in wcd_mbhc_btn_press_handler()
686 if (mbhc->in_swch_irq_handler) in wcd_mbhc_btn_press_handler()
690 if (mbhc->current_plug != MBHC_PLUG_TYPE_HEADSET) in wcd_mbhc_btn_press_handler()
693 mask = wcd_mbhc_get_button_mask(mbhc); in wcd_mbhc_btn_press_handler()
694 mbhc->buttons_pressed |= mask; in wcd_mbhc_btn_press_handler()
695 if (schedule_delayed_work(&mbhc->mbhc_btn_dwork, msecs_to_jiffies(400)) == 0) in wcd_mbhc_btn_press_handler()
698 mutex_unlock(&mbhc->lock); in wcd_mbhc_btn_press_handler()
707 mutex_lock(&mbhc->lock); in wcd_mbhc_btn_release_handler()
708 if (mbhc->is_btn_press) in wcd_mbhc_btn_release_handler()
709 mbhc->is_btn_press = false; in wcd_mbhc_btn_release_handler()
713 if (!(mbhc->buttons_pressed & WCD_MBHC_JACK_BUTTON_MASK)) in wcd_mbhc_btn_release_handler()
718 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
720 if (!mbhc->in_swch_irq_handler) { in wcd_mbhc_btn_release_handler()
722 snd_soc_jack_report(mbhc->jack, mbhc->buttons_pressed, in wcd_mbhc_btn_release_handler()
723 mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
724 snd_soc_jack_report(mbhc->jack, 0, mbhc->buttons_pressed); in wcd_mbhc_btn_release_handler()
727 mbhc->buttons_pressed &= ~WCD_MBHC_JACK_BUTTON_MASK; in wcd_mbhc_btn_release_handler()
729 mutex_unlock(&mbhc->lock); in wcd_mbhc_btn_release_handler()
737 /* TODO Find a better way to report this to Userspace */ in wcd_mbhc_hph_ocp_irq()
738 dev_err(mbhc->dev, "MBHC Over Current on %s detected\n", in wcd_mbhc_hph_ocp_irq()
759 struct snd_soc_component *component = mbhc->component; in wcd_mbhc_initialise()
762 ret = pm_runtime_get_sync(component->dev); in wcd_mbhc_initialise()
763 if (ret < 0 && ret != -EACCES) { in wcd_mbhc_initialise()
764 dev_err_ratelimited(component->dev, in wcd_mbhc_initialise()
767 pm_runtime_put_noidle(component->dev); in wcd_mbhc_initialise()
771 mutex_lock(&mbhc->lock); in wcd_mbhc_initialise()
773 if (mbhc->cfg->typec_analog_mux) in wcd_mbhc_initialise()
774 mbhc->swap_thr = GND_MIC_USBC_SWAP_THRESHOLD; in wcd_mbhc_initialise()
776 mbhc->swap_thr = GND_MIC_SWAP_THRESHOLD; in wcd_mbhc_initialise()
779 if (mbhc->mbhc_cb->hph_pull_up_control_v2) in wcd_mbhc_initialise()
780 mbhc->mbhc_cb->hph_pull_up_control_v2(component, in wcd_mbhc_initialise()
781 mbhc->cfg->typec_analog_mux ? in wcd_mbhc_initialise()
783 else if (mbhc->mbhc_cb->hph_pull_up_control) in wcd_mbhc_initialise()
784 mbhc->mbhc_cb->hph_pull_up_control(component, in wcd_mbhc_initialise()
785 mbhc->cfg->typec_analog_mux ? in wcd_mbhc_initialise()
789 mbhc->cfg->typec_analog_mux ? 0 : 3); in wcd_mbhc_initialise()
791 wcd_mbhc_write_field(mbhc, WCD_MBHC_HPHL_PLUG_TYPE, mbhc->cfg->hphl_swh); in wcd_mbhc_initialise()
792 wcd_mbhc_write_field(mbhc, WCD_MBHC_GND_PLUG_TYPE, mbhc->cfg->gnd_swh); in wcd_mbhc_initialise()
794 if (mbhc->cfg->gnd_det_en && mbhc->mbhc_cb->mbhc_gnd_det_ctrl) in wcd_mbhc_initialise()
795 mbhc->mbhc_cb->mbhc_gnd_det_ctrl(component, true); in wcd_mbhc_initialise()
799 if (mbhc->cfg->typec_analog_mux) in wcd_mbhc_initialise()
804 if (mbhc->cfg->typec_analog_mux) in wcd_mbhc_initialise()
815 mbhc->mbhc_cb->mbhc_bias(component, true); in wcd_mbhc_initialise()
817 if (mbhc->mbhc_cb->clk_setup) in wcd_mbhc_initialise()
818 mbhc->mbhc_cb->clk_setup(component, in wcd_mbhc_initialise()
819 mbhc->cfg->typec_analog_mux ? false : true); in wcd_mbhc_initialise()
826 mutex_unlock(&mbhc->lock); in wcd_mbhc_initialise()
828 pm_runtime_mark_last_busy(component->dev); in wcd_mbhc_initialise()
829 pm_runtime_put_autosuspend(component->dev); in wcd_mbhc_initialise()
838 if (mbhc->mbhc_cb->get_micbias_val) { in wcd_mbhc_get_micbias()
839 mbhc->mbhc_cb->get_micbias_val(mbhc->component, &micbias); in wcd_mbhc_get_micbias()
867 /* Pre-requisites for ADC continuous measurement */ in wcd_measure_adc_continuous()
868 /* Read legacy electircal detection and disable */ in wcd_measure_adc_continuous()
874 /* Disable ADC_ENABLE bit */ in wcd_measure_adc_continuous()
876 /* Disable MBHC FSM */ in wcd_measure_adc_continuous()
885 while (retry--) { in wcd_measure_adc_continuous()
901 struct device *dev = mbhc->dev; in wcd_measure_adc_once()
921 while (retry--) { in wcd_measure_adc_once()
950 ret = -EINVAL; in wcd_measure_adc_once()
965 /* If PA is enabled, dont check for cross-connection */ in wcd_check_cross_conn()
967 return -EINVAL; in wcd_check_cross_conn()
969 /* Read legacy electircal detection and disable */ in wcd_check_cross_conn()
1015 if (mbhc->cfg->hs_thr) { in wcd_mbhc_adc_get_hs_thres()
1016 if (mbhc->cfg->micb_mv == micbias_mv) in wcd_mbhc_adc_get_hs_thres()
1017 hs_threshold = mbhc->cfg->hs_thr; in wcd_mbhc_adc_get_hs_thres()
1019 hs_threshold = (mbhc->cfg->hs_thr * in wcd_mbhc_adc_get_hs_thres()
1020 micbias_mv) / mbhc->cfg->micb_mv; in wcd_mbhc_adc_get_hs_thres()
1033 if (mbhc->cfg->hph_thr) { in wcd_mbhc_adc_get_hph_thres()
1034 if (mbhc->cfg->micb_mv == micbias_mv) in wcd_mbhc_adc_get_hph_thres()
1035 hph_threshold = mbhc->cfg->hph_thr; in wcd_mbhc_adc_get_hph_thres()
1037 hph_threshold = (mbhc->cfg->hph_thr * in wcd_mbhc_adc_get_hph_thres()
1038 micbias_mv) / mbhc->cfg->micb_mv; in wcd_mbhc_adc_get_hph_thres()
1056 if (mbhc->mbhc_cb->micbias_enable_status) in wcd_mbhc_adc_update_fsm_source()
1057 micbias2 = mbhc->mbhc_cb->micbias_enable_status(mbhc->component, in wcd_mbhc_adc_update_fsm_source()
1060 if (!mbhc->is_hs_recording && !micbias2) in wcd_mbhc_adc_update_fsm_source()
1075 if (mbhc->mbhc_cb->bcs_enable) in wcd_mbhc_bcs_enable()
1076 mbhc->mbhc_cb->bcs_enable(mbhc->component, enable); in wcd_mbhc_bcs_enable()
1107 if (mbhc->cfg->hs_thr && mbhc->cfg->micb_mv != WCD_MBHC_ADC_MICBIAS_MV) { in wcd_mbhc_get_spl_hs_thres()
1108 if (mbhc->cfg->micb_mv == micbias_mv) in wcd_mbhc_get_spl_hs_thres()
1109 hs_threshold = mbhc->cfg->hs_thr; in wcd_mbhc_get_spl_hs_thres()
1111 hs_threshold = (mbhc->cfg->hs_thr * micbias_mv) / mbhc->cfg->micb_mv; in wcd_mbhc_get_spl_hs_thres()
1124 if (!mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic) in wcd_mbhc_check_for_spl_headset()
1128 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, true); in wcd_mbhc_check_for_spl_headset()
1140 mbhc->mbhc_cb->mbhc_micb_ctrl_thr_mic(mbhc->component, MIC_BIAS_2, false); in wcd_mbhc_check_for_spl_headset()
1161 component = mbhc->component; in wcd_correct_swch_plug()
1163 ret = pm_runtime_get_sync(component->dev); in wcd_correct_swch_plug()
1164 if (ret < 0 && ret != -EACCES) { in wcd_correct_swch_plug()
1165 dev_err_ratelimited(component->dev, in wcd_correct_swch_plug()
1168 pm_runtime_put_noidle(component->dev); in wcd_correct_swch_plug()
1174 /* Mask ADC COMPLETE interrupt */ in wcd_correct_swch_plug()
1175 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_correct_swch_plug()
1181 } while (try < mbhc->swap_thr); in wcd_correct_swch_plug()
1185 dev_err(mbhc->dev, "cross connection found, Plug type %d\n", in wcd_correct_swch_plug()
1195 * Report plug type if it is either headset or headphone in wcd_correct_swch_plug()
1214 /* Disable BCS slow insertion detection */ in wcd_correct_swch_plug()
1220 if (mbhc->hs_detect_work_stop) { in wcd_correct_swch_plug()
1247 if (cross_conn > 0) { /* cross-connection */ in wcd_correct_swch_plug()
1249 if (pt_gnd_mic_swap_cnt < mbhc->swap_thr) in wcd_correct_swch_plug()
1260 if (pt_gnd_mic_swap_cnt == mbhc->swap_thr) { in wcd_correct_swch_plug()
1262 if (mbhc->cfg->swap_gnd_mic) { in wcd_correct_swch_plug()
1263 if (mbhc->cfg->swap_gnd_mic(component, true)) in wcd_correct_swch_plug()
1270 if (output_mv > hs_threshold || mbhc->force_linein) in wcd_correct_swch_plug()
1297 if (mbhc->mbhc_cb->mbhc_micbias_control) in wcd_correct_swch_plug()
1301 if (mbhc->mbhc_cb->mbhc_micbias_control/* && !mbhc->micbias_enable*/) in wcd_correct_swch_plug()
1302 mbhc->mbhc_cb->mbhc_micbias_control(component, MIC_BIAS_2, MICB_DISABLE); in wcd_correct_swch_plug()
1307 * disable micbias. in wcd_correct_swch_plug()
1316 enable_irq(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_correct_swch_plug()
1319 if (mbhc->mbhc_cb->hph_pull_down_ctrl) in wcd_correct_swch_plug()
1320 mbhc->mbhc_cb->hph_pull_down_ctrl(component, true); in wcd_correct_swch_plug()
1322 pm_runtime_mark_last_busy(component->dev); in wcd_correct_swch_plug()
1323 pm_runtime_put_autosuspend(component->dev); in wcd_correct_swch_plug()
1332 mutex_lock(&mbhc->lock); in wcd_mbhc_adc_hs_rem_irq()
1355 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) in wcd_mbhc_adc_hs_rem_irq()
1356 mbhc->extn_cable_hph_rem = true; in wcd_mbhc_adc_hs_rem_irq()
1365 mutex_unlock(&mbhc->lock); in wcd_mbhc_adc_hs_rem_irq()
1380 if (mbhc->extn_cable_hph_rem == true) { in wcd_mbhc_adc_hs_ins_irq()
1381 mbhc->extn_cable_hph_rem = false; in wcd_mbhc_adc_hs_ins_irq()
1394 } while (--clamp_retry); in wcd_mbhc_adc_hs_ins_irq()
1401 if (mbhc->current_plug == MBHC_PLUG_TYPE_HEADPHONE) { in wcd_mbhc_adc_hs_ins_irq()
1402 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_adc_hs_ins_irq()
1413 *zl = mbhc->zl; in wcd_mbhc_get_impedance()
1414 *zr = mbhc->zr; in wcd_mbhc_get_impedance()
1419 return -EINVAL; in wcd_mbhc_get_impedance()
1425 mbhc->hph_type = hph_type; in wcd_mbhc_set_hph_type()
1431 return mbhc->hph_type; in wcd_mbhc_get_hph_type()
1439 return -EINVAL; in wcd_mbhc_start()
1441 mbhc->cfg = cfg; in wcd_mbhc_start()
1442 mbhc->jack = jack; in wcd_mbhc_start()
1450 mbhc->current_plug = MBHC_PLUG_TYPE_NONE; in wcd_mbhc_stop()
1451 mbhc->hph_status = 0; in wcd_mbhc_stop()
1452 disable_irq_nosync(mbhc->intr_ids->hph_left_ocp); in wcd_mbhc_stop()
1453 disable_irq_nosync(mbhc->intr_ids->hph_right_ocp); in wcd_mbhc_stop()
1459 struct device_node *np = dev->of_node; in wcd_dt_parse_mbhc_data()
1462 if (of_property_read_bool(np, "qcom,hphl-jack-type-normally-closed")) in wcd_dt_parse_mbhc_data()
1463 cfg->hphl_swh = false; in wcd_dt_parse_mbhc_data()
1465 cfg->hphl_swh = true; in wcd_dt_parse_mbhc_data()
1467 if (of_property_read_bool(np, "qcom,ground-jack-type-normally-closed")) in wcd_dt_parse_mbhc_data()
1468 cfg->gnd_swh = false; in wcd_dt_parse_mbhc_data()
1470 cfg->gnd_swh = true; in wcd_dt_parse_mbhc_data()
1472 ret = of_property_read_u32(np, "qcom,mbhc-headset-vthreshold-microvolt", in wcd_dt_parse_mbhc_data()
1475 dev_dbg(dev, "missing qcom,mbhc-hs-mic-max-vthreshold--microvolt in dt node\n"); in wcd_dt_parse_mbhc_data()
1477 cfg->hs_thr = microvolt/1000; in wcd_dt_parse_mbhc_data()
1479 ret = of_property_read_u32(np, "qcom,mbhc-headphone-vthreshold-microvolt", in wcd_dt_parse_mbhc_data()
1482 dev_dbg(dev, "missing qcom,mbhc-hs-mic-min-vthreshold-microvolt entry\n"); in wcd_dt_parse_mbhc_data()
1484 cfg->hph_thr = microvolt/1000; in wcd_dt_parse_mbhc_data()
1487 "qcom,mbhc-buttons-vthreshold-microvolt", in wcd_dt_parse_mbhc_data()
1488 &cfg->btn_high[0], in wcd_dt_parse_mbhc_data()
1491 dev_err(dev, "missing qcom,mbhc-buttons-vthreshold-microvolt entry\n"); in wcd_dt_parse_mbhc_data()
1495 cfg->btn_high[i] = 500000; in wcd_dt_parse_mbhc_data()
1498 cfg->btn_high[i] = cfg->btn_high[i]/1000; in wcd_dt_parse_mbhc_data()
1511 struct device *dev = component->dev; in wcd_mbhc_init()
1515 if (!intr_ids || !fields || !mbhc_cb || !mbhc_cb->mbhc_bias || !mbhc_cb->set_btn_thr) { in wcd_mbhc_init()
1517 return ERR_PTR(-EINVAL); in wcd_mbhc_init()
1522 return ERR_PTR(-ENOMEM); in wcd_mbhc_init()
1524 mbhc->component = component; in wcd_mbhc_init()
1525 mbhc->dev = dev; in wcd_mbhc_init()
1526 mbhc->intr_ids = intr_ids; in wcd_mbhc_init()
1527 mbhc->mbhc_cb = mbhc_cb; in wcd_mbhc_init()
1528 mbhc->fields = fields; in wcd_mbhc_init()
1529 mbhc->mbhc_detection_logic = WCD_DETECTION_ADC; in wcd_mbhc_init()
1531 if (mbhc_cb->compute_impedance) in wcd_mbhc_init()
1532 mbhc->impedance_detect = impedance_det_en; in wcd_mbhc_init()
1534 INIT_DELAYED_WORK(&mbhc->mbhc_btn_dwork, wcd_btn_long_press_fn); in wcd_mbhc_init()
1536 mutex_init(&mbhc->lock); in wcd_mbhc_init()
1538 INIT_WORK(&mbhc->correct_plug_swch, wcd_correct_swch_plug); in wcd_mbhc_init()
1539 INIT_WORK(&mbhc->mbhc_plug_detect_work, mbhc_plug_detect_fn); in wcd_mbhc_init()
1541 ret = request_threaded_irq(mbhc->intr_ids->mbhc_sw_intr, NULL, in wcd_mbhc_init()
1548 ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_press_intr, NULL, in wcd_mbhc_init()
1555 ret = request_threaded_irq(mbhc->intr_ids->mbhc_btn_release_intr, NULL, in wcd_mbhc_init()
1562 ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_ins_intr, NULL, in wcd_mbhc_init()
1569 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_ins_intr); in wcd_mbhc_init()
1571 ret = request_threaded_irq(mbhc->intr_ids->mbhc_hs_rem_intr, NULL, in wcd_mbhc_init()
1578 disable_irq_nosync(mbhc->intr_ids->mbhc_hs_rem_intr); in wcd_mbhc_init()
1580 ret = request_threaded_irq(mbhc->intr_ids->hph_left_ocp, NULL, in wcd_mbhc_init()
1587 ret = request_threaded_irq(mbhc->intr_ids->hph_right_ocp, NULL, in wcd_mbhc_init()
1597 free_irq(mbhc->intr_ids->hph_left_ocp, mbhc); in wcd_mbhc_init()
1599 free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc); in wcd_mbhc_init()
1601 free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc); in wcd_mbhc_init()
1603 free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc); in wcd_mbhc_init()
1605 free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc); in wcd_mbhc_init()
1607 free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc); in wcd_mbhc_init()
1619 free_irq(mbhc->intr_ids->hph_right_ocp, mbhc); in wcd_mbhc_deinit()
1620 free_irq(mbhc->intr_ids->hph_left_ocp, mbhc); in wcd_mbhc_deinit()
1621 free_irq(mbhc->intr_ids->mbhc_hs_rem_intr, mbhc); in wcd_mbhc_deinit()
1622 free_irq(mbhc->intr_ids->mbhc_hs_ins_intr, mbhc); in wcd_mbhc_deinit()
1623 free_irq(mbhc->intr_ids->mbhc_btn_release_intr, mbhc); in wcd_mbhc_deinit()
1624 free_irq(mbhc->intr_ids->mbhc_btn_press_intr, mbhc); in wcd_mbhc_deinit()
1625 free_irq(mbhc->intr_ids->mbhc_sw_intr, mbhc); in wcd_mbhc_deinit()
1627 mutex_lock(&mbhc->lock); in wcd_mbhc_deinit()
1628 wcd_cancel_hs_detect_plug(mbhc, &mbhc->correct_plug_swch); in wcd_mbhc_deinit()
1629 cancel_work_sync(&mbhc->mbhc_plug_detect_work); in wcd_mbhc_deinit()
1630 mutex_unlock(&mbhc->lock); in wcd_mbhc_deinit()