summaryrefslogtreecommitdiffstats
path: root/drivers/soundwire/qcom.c
diff options
context:
space:
mode:
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>2023-05-25 14:38:10 +0100
committerVinod Koul <vkoul@kernel.org>2023-05-29 10:42:28 +0530
commit9ac4a4441a393599a2d50148ee979b8754c97b2b (patch)
tree27a9e40776097f1f9c6f42b8faab3182ae07570e /drivers/soundwire/qcom.c
parent0a207b6b1892efafef80ad2fb21761f3b0f6f13a (diff)
downloadlinux-stable-9ac4a4441a393599a2d50148ee979b8754c97b2b.tar.gz
linux-stable-9ac4a4441a393599a2d50148ee979b8754c97b2b.tar.bz2
linux-stable-9ac4a4441a393599a2d50148ee979b8754c97b2b.zip
soundwire: qcom: wait for fifo to be empty before suspend
Wait for Fifo to be empty before going to suspend or before bank switch happens. Just to make sure that all the reads/writes are done. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org> Link: https://lore.kernel.org/r/20230525133812.30841-3-srinivas.kandagatla@linaro.org Signed-off-by: Vinod Koul <vkoul@kernel.org>
Diffstat (limited to 'drivers/soundwire/qcom.c')
-rw-r--r--drivers/soundwire/qcom.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index ab1098ec56e6..91d9de554542 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -401,6 +401,32 @@ static int swrm_wait_for_wr_fifo_avail(struct qcom_swrm_ctrl *ctrl)
return 0;
}
+static bool swrm_wait_for_wr_fifo_done(struct qcom_swrm_ctrl *ctrl)
+{
+ u32 fifo_outstanding_cmds, value;
+ int fifo_retry_count = SWR_OVERFLOW_RETRY_COUNT;
+
+ /* Check for fifo overflow during write */
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value);
+ fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value);
+
+ if (fifo_outstanding_cmds) {
+ while (fifo_retry_count) {
+ usleep_range(500, 510);
+ ctrl->reg_read(ctrl, ctrl->reg_layout[SWRM_REG_CMD_FIFO_STATUS], &value);
+ fifo_outstanding_cmds = FIELD_GET(SWRM_WR_CMD_FIFO_CNT_MASK, value);
+ fifo_retry_count--;
+ if (fifo_outstanding_cmds == 0)
+ return true;
+ }
+ } else {
+ return true;
+ }
+
+
+ return false;
+}
+
static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data,
u8 dev_addr, u16 reg_addr)
{
@@ -431,6 +457,7 @@ static int qcom_swrm_cmd_fifo_wr_cmd(struct qcom_swrm_ctrl *ctrl, u8 cmd_data,
usleep_range(150, 155);
if (cmd_id == SWR_BROADCAST_CMD_ID) {
+ swrm_wait_for_wr_fifo_done(ctrl);
/*
* sleep for 10ms for MSM soundwire variant to allow broadcast
* command to complete.
@@ -1227,6 +1254,7 @@ static void qcom_swrm_shutdown(struct snd_pcm_substream *substream,
{
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dai->dev);
+ swrm_wait_for_wr_fifo_done(ctrl);
sdw_release_stream(ctrl->sruntime[dai->id]);
ctrl->sruntime[dai->id] = NULL;
pm_runtime_mark_last_busy(ctrl->dev);
@@ -1685,6 +1713,7 @@ static int __maybe_unused swrm_runtime_suspend(struct device *dev)
struct qcom_swrm_ctrl *ctrl = dev_get_drvdata(dev);
int ret;
+ swrm_wait_for_wr_fifo_done(ctrl);
if (!ctrl->clock_stop_not_supported) {
/* Mask bus clash interrupt */
ctrl->intr_mask &= ~SWRM_INTERRUPT_STATUS_MASTER_CLASH_DET;