--- /dev/null
+From 0ff4e8c61b794a4bf6c854ab071a1abaaa80f358 Mon Sep 17 00:00:00 2001
+From: "S.j. Wang" <shengjiu.wang@nxp.com>
+Date: Wed, 27 Feb 2019 06:31:12 +0000
+Subject: ASoC: fsl_esai: fix channel swap issue when stream starts
+
+From: S.j. Wang <shengjiu.wang@nxp.com>
+
+commit 0ff4e8c61b794a4bf6c854ab071a1abaaa80f358 upstream.
+
+There is very low possibility ( < 0.1% ) that channel swap happened
+in beginning when multi output/input pin is enabled. The issue is
+that hardware can't send data to correct pin in the beginning with
+the normal enable flow.
+
+This is hardware issue, but there is no errata, the workaround flow
+is that: Each time playback/recording, firstly clear the xSMA/xSMB,
+then enable TE/RE, then enable xSMB and xSMA (xSMB must be enabled
+before xSMA). Which is to use the xSMA as the trigger start register,
+previously the xCR_TE or xCR_RE is the bit for starting.
+
+Fixes commit 43d24e76b698 ("ASoC: fsl_esai: Add ESAI CPU DAI driver")
+Cc: <stable@vger.kernel.org>
+Reviewed-by: Fabio Estevam <festevam@gmail.com>
+Acked-by: Nicolin Chen <nicoleotsuka@gmail.com>
+Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ sound/soc/fsl/fsl_esai.c | 47 +++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 37 insertions(+), 10 deletions(-)
+
+--- a/sound/soc/fsl/fsl_esai.c
++++ b/sound/soc/fsl/fsl_esai.c
+@@ -57,6 +57,8 @@ struct fsl_esai {
+ u32 fifo_depth;
+ u32 slot_width;
+ u32 slots;
++ u32 tx_mask;
++ u32 rx_mask;
+ u32 hck_rate[2];
+ u32 sck_rate[2];
+ bool hck_dir[2];
+@@ -357,21 +359,13 @@ static int fsl_esai_set_dai_tdm_slot(str
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_TCCR,
+ ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
+
+- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMA,
+- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(tx_mask));
+- regmap_update_bits(esai_priv->regmap, REG_ESAI_TSMB,
+- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(tx_mask));
+-
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_RCCR,
+ ESAI_xCCR_xDC_MASK, ESAI_xCCR_xDC(slots));
+
+- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMA,
+- ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(rx_mask));
+- regmap_update_bits(esai_priv->regmap, REG_ESAI_RSMB,
+- ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(rx_mask));
+-
+ esai_priv->slot_width = slot_width;
+ esai_priv->slots = slots;
++ esai_priv->tx_mask = tx_mask;
++ esai_priv->rx_mask = rx_mask;
+
+ return 0;
+ }
+@@ -577,6 +571,7 @@ static int fsl_esai_trigger(struct snd_p
+ bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+ u8 i, channels = substream->runtime->channels;
+ u32 pins = DIV_ROUND_UP(channels, esai_priv->slots);
++ u32 mask;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+@@ -589,15 +584,38 @@ static int fsl_esai_trigger(struct snd_p
+ for (i = 0; tx && i < channels; i++)
+ regmap_write(esai_priv->regmap, REG_ESAI_ETDR, 0x0);
+
++ /*
++ * When set the TE/RE in the end of enablement flow, there
++ * will be channel swap issue for multi data line case.
++ * In order to workaround this issue, we switch the bit
++ * enablement sequence to below sequence
++ * 1) clear the xSMB & xSMA: which is done in probe and
++ * stop state.
++ * 2) set TE/RE
++ * 3) set xSMB
++ * 4) set xSMA: xSMA is the last one in this flow, which
++ * will trigger esai to start.
++ */
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+ tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK,
+ tx ? ESAI_xCR_TE(pins) : ESAI_xCR_RE(pins));
++ mask = tx ? esai_priv->tx_mask : esai_priv->rx_mask;
++
++ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
++ ESAI_xSMB_xS_MASK, ESAI_xSMB_xS(mask));
++ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
++ ESAI_xSMA_xS_MASK, ESAI_xSMA_xS(mask));
++
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xCR(tx),
+ tx ? ESAI_xCR_TE_MASK : ESAI_xCR_RE_MASK, 0);
++ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMA(tx),
++ ESAI_xSMA_xS_MASK, 0);
++ regmap_update_bits(esai_priv->regmap, REG_ESAI_xSMB(tx),
++ ESAI_xSMB_xS_MASK, 0);
+
+ /* Disable and reset FIFO */
+ regmap_update_bits(esai_priv->regmap, REG_ESAI_xFCR(tx),
+@@ -838,6 +856,15 @@ static int fsl_esai_probe(struct platfor
+ return ret;
+ }
+
++ esai_priv->tx_mask = 0xFFFFFFFF;
++ esai_priv->rx_mask = 0xFFFFFFFF;
++
++ /* Clear the TSMA, TSMB, RSMA, RSMB */
++ regmap_write(esai_priv->regmap, REG_ESAI_TSMA, 0);
++ regmap_write(esai_priv->regmap, REG_ESAI_TSMB, 0);
++ regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0);
++ regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0);
++
+ ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component,
+ &fsl_esai_dai, 1);
+ if (ret) {