From 75f229237a51f8c0de070cbcc560f383de176215 Mon Sep 17 00:00:00 2001 From: Vignesh Kulothungan Date: Wed, 20 May 2020 15:50:14 -0700 Subject: [PATCH] ASoC: codecs: handle device disconnect during SSR During SSR, when usbc analog device is disconnected, the respective disconnect interrupt is not handled and hence userspace is not notified. When ADSP recovers, fsa driver sends a disconnect notification. So handle device disconnect and notify jack/userspace through this notification. Change-Id: Ic695c2267c9289f9528d50202938ec09f634de8a Signed-off-by: Vignesh Kulothungan --- asoc/codecs/wcd-mbhc-v2.c | 19 +++++++++++++++++++ asoc/codecs/wcd938x/wcd938x.c | 2 ++ include/asoc/wcd-mbhc-v2.h | 1 + 3 files changed, 22 insertions(+) diff --git a/asoc/codecs/wcd-mbhc-v2.c b/asoc/codecs/wcd-mbhc-v2.c index 17ce0ef790..08d7678b7d 100644 --- a/asoc/codecs/wcd-mbhc-v2.c +++ b/asoc/codecs/wcd-mbhc-v2.c @@ -1621,6 +1621,8 @@ static int wcd_mbhc_set_keycode(struct wcd_mbhc *mbhc) static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb, unsigned long mode, void *ptr) { + unsigned int l_det_en = 0; + unsigned int detection_type = 0; struct wcd_mbhc *mbhc = container_of(nb, struct wcd_mbhc, fsa_nb); if (!mbhc) @@ -1633,6 +1635,23 @@ static int wcd_mbhc_usbc_ana_event_handler(struct notifier_block *nb, mbhc->mbhc_cb->clk_setup(mbhc->component, true); /* insertion detected, enable L_DET_EN */ WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_L_DET_EN, 1); + } else { + WCD_MBHC_REG_READ(WCD_MBHC_MECH_DETECTION_TYPE, detection_type); + WCD_MBHC_REG_READ(WCD_MBHC_L_DET_EN, l_det_en); + /* If both l_det_en and detection type are set, it means device was + * unplugged during SSR and detection interrupt was not handled. + * So trigger device disconnect */ + if (detection_type && l_det_en) { + /* Set the detection type appropriately */ + WCD_MBHC_REG_UPDATE_BITS(WCD_MBHC_MECH_DETECTION_TYPE, + !detection_type); + /* Set current plug type to the state before SSR */ + mbhc->current_plug = mbhc->plug_before_ssr; + + wcd_mbhc_swch_irq_handler(mbhc); + mbhc->mbhc_cb->lock_sleep(mbhc, false); + mbhc->plug_before_ssr = MBHC_PLUG_TYPE_NONE; + } } return 0; } diff --git a/asoc/codecs/wcd938x/wcd938x.c b/asoc/codecs/wcd938x/wcd938x.c index 22bea4cb65..6a044bd6f1 100644 --- a/asoc/codecs/wcd938x/wcd938x.c +++ b/asoc/codecs/wcd938x/wcd938x.c @@ -2061,6 +2061,8 @@ static int wcd938x_event_notify(struct notifier_block *block, case BOLERO_WCD_EVT_SSR_DOWN: wcd938x->dev_up = false; wcd938x->mbhc->wcd_mbhc.deinit_in_progress = true; + wcd938x->mbhc->wcd_mbhc.plug_before_ssr = + wcd938x->mbhc->wcd_mbhc.current_plug; mbhc = &wcd938x->mbhc->wcd_mbhc; wcd938x->usbc_hs_status = get_usbc_hs_status(component, mbhc->mbhc_cfg); diff --git a/include/asoc/wcd-mbhc-v2.h b/include/asoc/wcd-mbhc-v2.h index 1c351f8012..e9dd2ae165 100644 --- a/include/asoc/wcd-mbhc-v2.h +++ b/include/asoc/wcd-mbhc-v2.h @@ -551,6 +551,7 @@ struct wcd_mbhc { wait_queue_head_t wait_btn_press; bool is_btn_press; u8 current_plug; + u8 plug_before_ssr; bool in_swch_irq_handler; bool hphl_swh; /*track HPHL switch NC / NO */ bool gnd_swh; /*track GND switch NC / NO */