From dfdc31a46d58dd4be449b1e905e80b0a7f70eb74 Mon Sep 17 00:00:00 2001
From: Bhalchandra Gajare <gajare@codeaurora.org>
Date: Wed, 9 Jul 2014 15:18:17 -0700
Subject: [PATCH] ASoC: wcd_cpe_core: Fix interrupt requests during SSR

When the bus to the codec goes down, the codec interrupt handlers need
to be freed and re-registered to make sure the interrupts are routed to
correct handlers. This fixes the issue of CPE becoming unresponsive once
the underlying bus goes down and comes back up again.

CRs-fixed: 698888
Change-Id: I3ba4be83b5e4db22140fb4e338cbbf4f19ff2ce0
Signed-off-by: Bhalchandra Gajare <gajare@codeaurora.org>
---
 sound/soc/codecs/wcd_cpe_core.c | 37 ++++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/sound/soc/codecs/wcd_cpe_core.c b/sound/soc/codecs/wcd_cpe_core.c
index 73a680bb5b23..4d77bf87bf90 100644
--- a/sound/soc/codecs/wcd_cpe_core.c
+++ b/sound/soc/codecs/wcd_cpe_core.c
@@ -91,6 +91,7 @@ struct wcd_cpe_core * (*wcd_get_cpe_core) (struct snd_soc_codec *);
 static struct wcd_cmi_afe_port_data afe_ports[WCD_CPE_AFE_MAX_PORTS + 1];
 static void wcd_cpe_svc_event_cb(const struct cpe_svc_notification *param);
 static int wcd_cpe_setup_irqs(struct wcd_cpe_core *core);
+static void wcd_cpe_cleanup_irqs(struct wcd_cpe_core *core);
 
 /*
  * wcd_cpe_lsm_session_active: check if any session is active
@@ -591,6 +592,9 @@ static void wcd_cpe_clr_ready_status(struct wcd_cpe_core *core,
 {
 	WCD_CPE_GRAB_LOCK(&core->ssr_lock, "SSR");
 	core->ready_status &= ~(value);
+	dev_dbg(core->dev,
+		"%s: ready_status = 0x%x\n",
+		__func__, core->ready_status);
 	WCD_CPE_REL_LOCK(&core->ssr_lock, "SSR");
 }
 
@@ -607,10 +611,11 @@ static void wcd_cpe_set_and_complete(struct wcd_cpe_core *core,
 {
 	WCD_CPE_GRAB_LOCK(&core->ssr_lock, "SSR");
 	core->ready_status |= value;
-	if (core->ready_status & WCD_CPE_READY_TO_DLOAD) {
+	if ((core->ready_status & WCD_CPE_READY_TO_DLOAD) ==
+	    WCD_CPE_READY_TO_DLOAD) {
 		dev_dbg(core->dev,
-			"%s: marking ready completion\n",
-			__func__);
+			"%s: marking ready, status = 0x%x\n",
+			__func__, core->ready_status);
 		complete(&core->ready_compl);
 	}
 	WCD_CPE_REL_LOCK(&core->ssr_lock, "SSR");
@@ -743,6 +748,8 @@ int wcd_cpe_ssr_event(void *core_handle,
 		break;
 
 	case WCD_CPE_BUS_UP_EVENT:
+		wcd_cpe_cleanup_irqs(core);
+		wcd_cpe_setup_irqs(core);
 		wcd_cpe_set_and_complete(core, WCD_CPE_BUS_READY);
 		/*
 		 * In case of bus up event ssr_type will be changed
@@ -968,6 +975,30 @@ static void wcd_cpe_svc_event_cb(const struct cpe_svc_notification *param)
 	return;
 }
 
+/*
+ * wcd_cpe_cleanup_irqs: free the irq resources required by cpe
+ * @core: handle the cpe core
+ *
+ * This API will free the IRQs for CPE but does not mask the
+ * CPE interrupts. If masking is needed, it has to be done
+ * explicity by caller.
+ */
+static void wcd_cpe_cleanup_irqs(struct wcd_cpe_core *core)
+{
+
+	struct snd_soc_codec *codec = core->codec;
+	struct wcd9xxx *wcd9xxx = codec->control_data;
+	struct wcd9xxx_core_resource *core_res = &wcd9xxx->core_res;
+
+	wcd9xxx_free_irq(core_res,
+			 WCD9330_IRQ_SVASS_ENGINE,
+			 core);
+	wcd9xxx_free_irq(core_res,
+			 WCD9330_IRQ_SVASS_ERR_EXCEPTION,
+			 core);
+
+}
+
 /*
  * wcd_cpe_setup_sva_err_intr: setup the irqs for CPE
  * @core: handle to wcd_cpe_core
-- 
GitLab