drivers: mfd: fix audio mute issue after ADSP SSR

Native audio playback is muted after adsp subsystem restart,
because codec device_reset() API is called even before device_down()
API finishes execution. This causes audio to mute, as codec is not
in proper reset state. Add new lock to synchronize codec subsystem
restart APIs.

Change-Id: I2366f8b04fc6cb7d874661b948c3e9af10470107
Signed-off-by: Vidyakumar Athota <vathota@codeaurora.org>
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 3ed7277..d143536 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -505,6 +505,7 @@
 
 	mutex_init(&wcd9xxx->io_lock);
 	mutex_init(&wcd9xxx->xfer_lock);
+	mutex_init(&wcd9xxx->reset_lock);
 
 	ret = wcd9xxx_bringup(wcd9xxx->dev);
 	if (ret) {
@@ -583,6 +584,7 @@
 err_bring_up:
 	mutex_destroy(&wcd9xxx->io_lock);
 	mutex_destroy(&wcd9xxx->xfer_lock);
+	mutex_destroy(&wcd9xxx->reset_lock);
 	return ret;
 }
 
@@ -595,6 +597,7 @@
 	wcd9xxx_core_res_deinit(&wcd9xxx->core_res);
 	mutex_destroy(&wcd9xxx->io_lock);
 	mutex_destroy(&wcd9xxx->xfer_lock);
+	mutex_destroy(&wcd9xxx->reset_lock);
 	if (wcd9xxx_get_intf_type() == WCD9XXX_INTERFACE_TYPE_SLIMBUS)
 		slim_remove_device(wcd9xxx->slim_slave);
 }
@@ -1481,9 +1484,11 @@
 	if (wcd9xxx->dev_up)
 		return 0;
 
+	mutex_lock(&wcd9xxx->reset_lock);
 	ret = wcd9xxx_reset(wcd9xxx->dev);
 	if (ret)
 		dev_err(wcd9xxx->dev, "%s: Resetting Codec failed\n", __func__);
+	mutex_unlock(&wcd9xxx->reset_lock);
 
 	return ret;
 }
@@ -1491,6 +1496,7 @@
 static int wcd9xxx_slim_device_up(struct slim_device *sldev)
 {
 	struct wcd9xxx *wcd9xxx = slim_get_devicedata(sldev);
+	int ret = 0;
 
 	if (!wcd9xxx) {
 		pr_err("%s: wcd9xxx is NULL\n", __func__);
@@ -1502,7 +1508,12 @@
 		return 0;
 
 	wcd9xxx->dev_up = true;
-	return wcd9xxx_device_up(wcd9xxx);
+
+	mutex_lock(&wcd9xxx->reset_lock);
+	ret = wcd9xxx_device_up(wcd9xxx);
+	mutex_unlock(&wcd9xxx->reset_lock);
+
+	return ret;
 }
 
 static int wcd9xxx_slim_device_down(struct slim_device *sldev)
@@ -1520,10 +1531,14 @@
 		return 0;
 
 	wcd9xxx->dev_up = false;
+
+	mutex_lock(&wcd9xxx->reset_lock);
 	if (wcd9xxx->dev_down)
 		wcd9xxx->dev_down(wcd9xxx);
 	wcd9xxx_irq_exit(&wcd9xxx->core_res);
 	wcd9xxx_reset_low(wcd9xxx->dev);
+	mutex_unlock(&wcd9xxx->reset_lock);
+
 	return 0;
 }
 
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index d747408..30ad689e 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -307,6 +307,7 @@
 		goto err_disable_irq;
 	}
 
+	memset(status, 0, sizeof(status));
 	ret = regmap_bulk_read(wcd9xxx_res->wcd_core_regmap,
 		wcd9xxx_res->intr_reg[WCD9XXX_INTR_STATUS_BASE],
 		status, num_irq_regs);
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 8a507d2..c6c8d24 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -334,6 +334,7 @@
 	struct slim_device *slim_slave;
 	struct mutex io_lock;
 	struct mutex xfer_lock;
+	struct mutex reset_lock;
 	u8 version;
 
 	int reset_gpio;