|
@@ -507,8 +507,40 @@ static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
|
|
|
|
|
|
config_done:
|
|
|
/* Enabling of subunits is done after configuration */
|
|
|
- if (enable)
|
|
|
+ if (enable) {
|
|
|
+ if (ssi_private->use_dma && (vals->scr & CCSR_SSI_SCR_TE)) {
|
|
|
+ /*
|
|
|
+ * Be sure the Tx FIFO is filled when TE is set.
|
|
|
+ * Otherwise, there are some chances to start the
|
|
|
+ * playback with some void samples inserted first,
|
|
|
+ * generating a channel slip.
|
|
|
+ *
|
|
|
+ * First, SSIEN must be set, to let the FIFO be filled.
|
|
|
+ *
|
|
|
+ * Notes:
|
|
|
+ * - Limit this fix to the DMA case until FIQ cases can
|
|
|
+ * be tested.
|
|
|
+ * - Limit the length of the busy loop to not lock the
|
|
|
+ * system too long, even if 1-2 loops are sufficient
|
|
|
+ * in general.
|
|
|
+ */
|
|
|
+ int i;
|
|
|
+ int max_loop = 100;
|
|
|
+ regmap_update_bits(regs, CCSR_SSI_SCR,
|
|
|
+ CCSR_SSI_SCR_SSIEN, CCSR_SSI_SCR_SSIEN);
|
|
|
+ for (i = 0; i < max_loop; i++) {
|
|
|
+ u32 sfcsr;
|
|
|
+ regmap_read(regs, CCSR_SSI_SFCSR, &sfcsr);
|
|
|
+ if (CCSR_SSI_SFCSR_TFCNT0(sfcsr))
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ if (i == max_loop) {
|
|
|
+ dev_err(ssi_private->dev,
|
|
|
+ "Timeout waiting TX FIFO filling\n");
|
|
|
+ }
|
|
|
+ }
|
|
|
regmap_update_bits(regs, CCSR_SSI_SCR, vals->scr, vals->scr);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|