diff --git a/src/drivers/intel/ssp/ssp.c b/src/drivers/intel/ssp/ssp.c index bb4bf5990151..cf103da73328 100644 --- a/src/drivers/intel/ssp/ssp.c +++ b/src/drivers/intel/ssp/ssp.c @@ -67,22 +67,27 @@ static void ssp_empty_tx_fifo(struct dai *dai) /* empty SSP receive FIFO */ static void ssp_empty_rx_fifo(struct dai *dai) { - uint32_t sssr; - uint32_t entries; - uint32_t i; + struct timer *timer = timer_get(); + uint64_t deadline = platform_timer_get(timer) + + clock_ms_to_ticks(PLATFORM_DEFAULT_CLOCK, 1) * + SSP_RX_FLUSH_TIMEOUT / 1000; - sssr = ssp_read(dai, SSSR); + /* + * To make sure all the RX FIFO entries are read out for the flushing, + * we need to wait until the SSSR_RNE is cleared after the SSP link is + * stopped (the SSSR_BSY is cleared), otherwise, there might be + * obsoleted entries remained in the FIFO, which will impact the next + * run with the SSP RX and lead to samples mismatched issue. + */ + do { + while (ssp_read(dai, SSSR) & SSSR_RNE) + /* read to empty the fifo */ + ssp_read(dai, SSDR); + } while ((ssp_read(dai, SSSR) & SSSR_BSY) && + platform_timer_get(timer) < deadline); /* clear interrupt */ - if (sssr & SSSR_ROR) - ssp_write(dai, SSSR, sssr); - - /* empty fifo */ - if (sssr & SSSR_RNE) { - entries = SSCR3_RFL_VAL(ssp_read(dai, SSCR3)); - for (i = 0; i < entries + 1; i++) - ssp_read(dai, SSDR); - } + ssp_update_bits(dai, SSSR, SSSR_ROR, SSSR_ROR); } /* save SSP context prior to entering D3 */ diff --git a/src/include/sof/drivers/ssp.h b/src/include/sof/drivers/ssp.h index e4b95da0a94a..9e2a2f0d36a5 100644 --- a/src/include/sof/drivers/ssp.h +++ b/src/include/sof/drivers/ssp.h @@ -220,6 +220,9 @@ extern const struct dai_driver ssp_driver; /* For 8000 Hz rate one sample is transmitted within 125us */ #define SSP_MAX_SEND_TIME_PER_SAMPLE 125 +/* SSP flush timeout in microseconds */ +#define SSP_RX_FLUSH_TIMEOUT 200 + #define ssp_irq(ssp) \ ssp->plat_data.irq