diff mbox

[v4,6/6] ASoC: fsl_ssi: Fix channel slipping on capture (or playback) restart in full duplex.

Message ID 1462277640-20052-7-git-send-email-arnaud.mouiche@invoxia.com (mailing list archive)
State Accepted
Commit 027db2e122db81b055a2b569d72f2f1d29c4d007
Headers show

Commit Message

Arnaud Mouiche May 3, 2016, 12:14 p.m. UTC
Happened when the Playback (or Capture) is running continuously
and Capture (or Playback) is restarted (xrun, manual stop/start...)

Since the RX (or TX) FIFO are only reset when the whole SSI is disabled,
pending samples from previous capture (or playback) session may still
be present. They must be erased to not introduce channel slipping.

FIFO Clear register fields are documented in IMX51, IMX35 reference manual.
They are not documented in IMX50 or IMX6 RM, despite they are
working as expected on IMX6SL and IMX6solo.

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

Comments

Fabio Estevam May 3, 2016, 12:24 p.m. UTC | #1
On Tue, May 3, 2016 at 9:14 AM, Arnaud Mouiche
<arnaud.mouiche@invoxia.com> wrote:
> Happened when the Playback (or Capture) is running continuously
> and Capture (or Playback) is restarted (xrun, manual stop/start...)
>
> Since the RX (or TX) FIFO are only reset when the whole SSI is disabled,
> pending samples from previous capture (or playback) session may still
> be present. They must be erased to not introduce channel slipping.
>
> FIFO Clear register fields are documented in IMX51, IMX35 reference manual.
> They are not documented in IMX50 or IMX6 RM, despite they are
> working as expected on IMX6SL and IMX6solo.
>
> Signed-off-by: Arnaud Mouiche <arnaud.mouiche@invoxia.com>

Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Caleb Crome May 10, 2016, 4:34 p.m. UTC | #2
On Tue, May 3, 2016 at 5:24 AM, Fabio Estevam <festevam@gmail.com> wrote:
> On Tue, May 3, 2016 at 9:14 AM, Arnaud Mouiche
> <arnaud.mouiche@invoxia.com> wrote:
>> Happened when the Playback (or Capture) is running continuously
>> and Capture (or Playback) is restarted (xrun, manual stop/start...)
>>
>> Since the RX (or TX) FIFO are only reset when the whole SSI is disabled,
>> pending samples from previous capture (or playback) session may still
>> be present. They must be erased to not introduce channel slipping.
>>
>> FIFO Clear register fields are documented in IMX51, IMX35 reference manual.
>> They are not documented in IMX50 or IMX6 RM, despite they are
>> working as expected on IMX6SL and IMX6solo.
>>
>> Signed-off-by: Arnaud Mouiche <arnaud.mouiche@invoxia.com>
>
> Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
Tested-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 6c0c72f..632ecc0 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -402,6 +402,26 @@  static void fsl_ssi_rxtx_config(struct fsl_ssi_private *ssi_private,
 }
 
 /*
+ * Clear RX or TX FIFO to remove samples from the previous
+ * stream session which may be still present in the FIFO and
+ * may introduce bad samples and/or channel slipping.
+ *
+ * Note: The SOR is not documented in recent IMX datasheet, but
+ * is described in IMX51 reference manual at section 56.3.3.15.
+ */
+static void fsl_ssi_fifo_clear(struct fsl_ssi_private *ssi_private,
+		bool is_rx)
+{
+	if (is_rx) {
+		regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+			CCSR_SSI_SOR_RX_CLR, CCSR_SSI_SOR_RX_CLR);
+	} else {
+		regmap_update_bits(ssi_private->regs, CCSR_SSI_SOR,
+			CCSR_SSI_SOR_TX_CLR, CCSR_SSI_SOR_TX_CLR);
+	}
+}
+
+/*
  * Calculate the bits that have to be disabled for the current stream that is
  * getting disabled. This keeps the bits enabled that are necessary for the
  * second stream to work if 'stream_active' is true.
@@ -476,6 +496,8 @@  static void fsl_ssi_config(struct fsl_ssi_private *ssi_private, bool enable,
 	 * (online configuration)
 	 */
 	if (enable) {
+		fsl_ssi_fifo_clear(ssi_private, vals->scr & CCSR_SSI_SCR_RE);
+
 		regmap_update_bits(regs, CCSR_SSI_SRCR, vals->srcr, vals->srcr);
 		regmap_update_bits(regs, CCSR_SSI_STCR, vals->stcr, vals->stcr);
 		regmap_update_bits(regs, CCSR_SSI_SIER, vals->sier, vals->sier);