From 162a43abaab11d1c64258a972ed21868736a8a33 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Tue, 1 Dec 2020 16:58:04 +0800 Subject: [PATCH] byt: ssp: refine the RX FIFO flushing logic Mimid the SSP RX FIFO flushing logic which verified work on CNL/WHL. We need to read out entries every time the FIFO is not empty. This flushing may need take place several rounds, and we need to wait 1 sample time between 2 flushing rounds. Fixes #3520 Signed-off-by: Keyon Jie --- src/drivers/intel/baytrail/ssp.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/drivers/intel/baytrail/ssp.c b/src/drivers/intel/baytrail/ssp.c index 56f86238f62e..9e3c46928e06 100644 --- a/src/drivers/intel/baytrail/ssp.c +++ b/src/drivers/intel/baytrail/ssp.c @@ -25,22 +25,36 @@ /* empty SSP receive FIFO */ static void ssp_empty_rx_fifo(struct dai *dai) { - uint32_t sssr; + struct ssp_pdata *ssp = dai_get_drvdata(dai); + uint64_t sample_ticks = clock_ticks_per_sample(PLATFORM_DEFAULT_CLOCK, + ssp->params.fsync_rate); + uint32_t retry = SSP_RX_FLUSH_RETRY_MAX; uint32_t entries; uint32_t i; - sssr = ssp_read(dai, SSSR); - - /* clear interrupt */ - if (sssr & SSSR_ROR) - ssp_write(dai, SSSR, sssr); - - /* empty fifo */ - if (sssr & SSSR_RNE) { + /* + * 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, + * and then re-check to see if there is any subsequent entries written + * to the FIFO. This will help to make sure there is no sample mismatched + * issue for the next run with the SSP RX. + */ + while ((ssp_read(dai, SSSR) & SSSR_RNE) && retry--) { entries = SFIFOL_RFL(ssp_read(dai, SFIFOL)); + 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); + + /* wait to get valid fifo status and re-check */ + wait_delay(sample_ticks); + entries = SFIFOL_RFL(ssp_read(dai, SFIFOL)); + dai_dbg(dai, "ssp_empty_rx_fifo(), after flushing, entries %d", entries); } + + /* clear interrupt */ + ssp_update_bits(dai, SSSR, SSSR_ROR, SSSR_ROR); + } /* save SSP context prior to entering D3 */