Prechádzať zdrojové kódy

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 <[email protected]>
Vignesh Kulothungan 4 rokov pred
rodič
commit
75f229237a

+ 19 - 0
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;
 }

+ 2 - 0
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);

+ 1 - 0
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 */