From ac6190212e776d443efc1ddf3c0144f69a4efd59 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 5 May 2023 15:46:55 +0300 Subject: [PATCH 1/2] intel: ssp: do not read data directly if DMA is active If DMA is active, do not read data directly from the SSP RX fifo. Signed-off-by: Kai Vehmanen --- src/drivers/intel/ssp/ssp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/drivers/intel/ssp/ssp.c b/src/drivers/intel/ssp/ssp.c index a00ff4c2b797..4a006c5a166a 100644 --- a/src/drivers/intel/ssp/ssp.c +++ b/src/drivers/intel/ssp/ssp.c @@ -74,9 +74,18 @@ static void ssp_empty_rx_fifo(struct dai *dai) uint64_t sample_ticks = clock_ticks_per_sample(PLATFORM_DEFAULT_CLOCK, ssp->params.fsync_rate); uint32_t retry = SSP_RX_FLUSH_RETRY_MAX; + bool direct_reads = ssp->state[DAI_DIR_CAPTURE] <= COMP_STATE_PREPARE; uint32_t entries; uint32_t i; +#if CONFIG_DMA_SUSPEND_DRAIN + /* + * In drain mode, DMA is stopped before DAI, so flush must be + * always done with direct register read. + */ + direct_reads = true; +#endif + /* * To make sure all the RX FIFO entries are read out for the flushing, * we need to wait a minimal SSP port delay after entries are all read, @@ -87,9 +96,12 @@ static void ssp_empty_rx_fifo(struct dai *dai) while ((ssp_read(dai, SSSR) & SSSR_RNE) && retry--) { entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3)); dai_dbg(dai, "ssp_empty_rx_fifo(), before flushing, entries %d", entries); - for (i = 0; i < entries + 1; i++) - /* read to try empty fifo */ - ssp_read(dai, SSDR); + + /* let DMA consume data or read RX FIFO directly */ + if (direct_reads) { + for (i = 0; i < entries + 1; i++) + ssp_read(dai, SSDR); + } /* wait to get valid fifo status and re-check */ wait_delay(sample_ticks); From d52796e65d42accbdb2f01e26d37d752282dfc0f Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Fri, 5 May 2023 15:37:22 +0300 Subject: [PATCH 2/2] intel: ssp: drain RX fifo when starting If DMA transaction is ongoing when RX is enabled, this can lead to stuck communication between DMA and SSP (DMA service request not seen by the DMA). To avoid this, flush the RX fifo before enabling SSP RX. Link: https://github.com/thesofproject/sof/issues/7548 Suggested-by: Peter Ujfalusi Signed-off-by: Kai Vehmanen --- src/drivers/intel/ssp/ssp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/drivers/intel/ssp/ssp.c b/src/drivers/intel/ssp/ssp.c index 4a006c5a166a..e654161181ed 100644 --- a/src/drivers/intel/ssp/ssp.c +++ b/src/drivers/intel/ssp/ssp.c @@ -975,6 +975,10 @@ static void ssp_early_start(struct dai *dai, int direction) key = k_spin_lock(&dai->lock); + /* RX fifo must be cleared before start */ + if (direction == DAI_DIR_CAPTURE) + ssp_empty_rx_fifo(dai); + /* request mclk/bclk */ ssp_pre_start(dai);