From ec48d3e0831e06cc089209eed65a9275fbd7d312 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 (cherry picked from commit e94071fb822b98d03b5ee9687bd4e4f3d2d736bb) --- 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 cc30cfba7908..3a2ed6979ef6 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 b2b222aa1f7d31ebcbd94eedf4e9cad5927d8ecb 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 (cherry picked from commit 4a4d8d261907bd900c91d0e64d7458bdb32e4cb3) --- 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 3a2ed6979ef6..b0a4296f813d 100644 --- a/src/drivers/intel/ssp/ssp.c +++ b/src/drivers/intel/ssp/ssp.c @@ -962,6 +962,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);