ASoC: SOF: Intel: hda: make sure DMA is start/stop by read the RUN bit
authorZhu Yingjiang <yingjiang.zhu@linux.intel.com>
Wed, 12 Jun 2019 17:23:46 +0000 (12:23 -0500)
committerMark Brown <broonie@kernel.org>
Mon, 17 Jun 2019 12:46:01 +0000 (13:46 +0100)
As per the HW recommendation, after setting the RUN bit
(start as 1, stop as 0), software must read the bit back
to make sure the bit is set right, before modifying related
control registers/re-starting the DMA engine.

Signed-off-by: Zhu Yingjiang <yingjiang.zhu@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
sound/soc/sof/intel/hda-stream.c
sound/soc/sof/intel/hda.h

index 23cff5aca007f6185c71ce86c116268848f8893f..13d114993f96fe6addcf55d008be89ccdb8f5043 100644 (file)
@@ -217,6 +217,9 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
 {
        struct hdac_stream *hstream = &stream->hstream;
        int sd_offset = SOF_STREAM_SD_OFFSET(hstream);
+       u32 dma_start = SOF_HDA_SD_CTL_DMA_START;
+       int ret;
+       u32 run;
 
        /* cmd must be for audio stream */
        switch (cmd) {
@@ -234,6 +237,16 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
                                        SOF_HDA_SD_CTL_DMA_START |
                                        SOF_HDA_CL_DMA_SD_INT_MASK);
 
+               ret = snd_sof_dsp_read_poll_timeout(sdev,
+                                       HDA_DSP_HDA_BAR,
+                                       sd_offset, run,
+                                       ((run & dma_start) == dma_start),
+                                       HDA_DSP_REG_POLL_INTERVAL_US,
+                                       HDA_DSP_STREAM_RUN_TIMEOUT);
+
+               if (ret)
+                       return ret;
+
                hstream->running = true;
                break;
        case SNDRV_PCM_TRIGGER_SUSPEND:
@@ -244,6 +257,15 @@ int hda_dsp_stream_trigger(struct snd_sof_dev *sdev,
                                        SOF_HDA_SD_CTL_DMA_START |
                                        SOF_HDA_CL_DMA_SD_INT_MASK, 0x0);
 
+               ret = snd_sof_dsp_read_poll_timeout(sdev, HDA_DSP_HDA_BAR,
+                                               sd_offset, run,
+                                               !(run & dma_start),
+                                               HDA_DSP_REG_POLL_INTERVAL_US,
+                                               HDA_DSP_STREAM_RUN_TIMEOUT);
+
+               if (ret)
+                       return ret;
+
                snd_sof_dsp_write(sdev, HDA_DSP_HDA_BAR, sd_offset +
                                  SOF_HDA_ADSP_REG_CL_SD_STS,
                                  SOF_HDA_CL_DMA_SD_INT_MASK);
index 50653859e0a04425e410eaa3933070edf554db2f..73d7cc08afc2253037cedc6f80da433f7d7687f8 100644 (file)
 #define HDA_DSP_MBOX_UPLINK_OFFSET             0x81000
 
 #define HDA_DSP_STREAM_RESET_TIMEOUT           300
+/*
+ * Timeout in us, for setting the stream RUN bit, during
+ * start/stop the stream. The timeout expires if new RUN bit
+ * value cannot be read back within the specified time.
+ */
+#define HDA_DSP_STREAM_RUN_TIMEOUT             300
 #define HDA_DSP_CL_TRIGGER_TIMEOUT             300
 
 #define HDA_DSP_SPIB_ENABLE                    1