From 58c0e7ebf11c350a79f41d1e4fb63e0020778054 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 16e9e1727768..8a688486f19d 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 728d96d645031921696df9b406897fabc20daca6 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 8a688486f19d..f5b2fb6b24fc 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);