soundwire: qcom: wait for fifo to be empty before suspend
authorSrinivas Kandagatla <srinivas.kandagatla@linaro.org>
Thu, 25 May 2023 13:38:10 +0000 (14:38 +0100)
committerVinod Koul <vkoul@kernel.org>
Mon, 29 May 2023 05:12:28 +0000 (10:42 +0530)
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>
drivers/soundwire/qcom.c

index ab1098e..91d9de5 100644 (file)
@@ -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;