diff mbox

[v3,5/6] ASoC: fsl_ssi: Fix channel slipping in Playback at startup

Message ID 1453130771-24419-6-git-send-email-arnaud.mouiche@invoxia.com (mailing list archive)
State New, archived
Headers show

Commit Message

Arnaud Mouiche Jan. 18, 2016, 3:26 p.m. UTC
Previously, SCR.SSIEN and SCR.TE were enabled at once if no capture
stream was also running.
This may not give a chance for the DMA to write the first sample in
TX FIFO before the streaming starts on the PCM bus, inserting void
samples first.
Those void samples are then responsible for slipping the channels.

Signed-off-by: Arnaud Mouiche <arnaud.mouiche@invoxia.com>
---
 sound/soc/fsl/fsl_ssi.c | 34 +++++++++++++++++++++++++++++++++-
 1 file changed, 33 insertions(+), 1 deletion(-)

Comments

Caleb Crome April 25, 2016, 5:22 p.m. UTC | #1
On Mon, Jan 18, 2016 at 7:26 AM, Arnaud Mouiche
<arnaud.mouiche@invoxia.com> wrote:
> Previously, SCR.SSIEN and SCR.TE were enabled at once if no capture
> stream was also running.
> This may not give a chance for the DMA to write the first sample in
> TX FIFO before the streaming starts on the PCM bus, inserting void
> samples first.
> Those void samples are then responsible for slipping the channels.
>
> Signed-off-by: Arnaud Mouiche <arnaud.mouiche@invoxia.com>
> ---
>  sound/soc/fsl/fsl_ssi.c | 34 +++++++++++++++++++++++++++++++++-
>  1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
> index c9ba8ca..530d592 100644
> --- a/sound/soc/fsl/fsl_ssi.c
> +++ b/sound/soc/fsl/fsl_ssi.c
> @@ -520,8 +520,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);
> +       }
>  }
>
>
> --
> 1.9.1
>

Tested-By: Caleb Crome <caleb@crome.org>
Reviewed-"By: Caleb Crome <caleb@crome.org>
diff mbox

Patch

diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c9ba8ca..530d592 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -520,8 +520,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);
+	}
 }