From: Greg Kroah-Hartman Date: Mon, 15 Apr 2019 11:33:44 +0000 (+0200) Subject: 3.18-stable patches X-Git-Tag: v4.9.169~27 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fkernel%2Fstable-queue.git;a=commitdiff_plain;h=7412aa52a69ebbea06b889e53c2db8e5569a4f70 3.18-stable patches added patches: asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch --- diff --git a/queue-3.18/asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch b/queue-3.18/asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch new file mode 100644 index 0000000000..269e9ecb1a --- /dev/null +++ b/queue-3.18/asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch @@ -0,0 +1,130 @@ +From 0ff4e8c61b794a4bf6c854ab071a1abaaa80f358 Mon Sep 17 00:00:00 2001 +From: "S.j. Wang" +Date: Wed, 27 Feb 2019 06:31:12 +0000 +Subject: ASoC: fsl_esai: fix channel swap issue when stream starts + +From: S.j. Wang + +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: +Reviewed-by: Fabio Estevam +Acked-by: Nicolin Chen +Signed-off-by: Shengjiu Wang +Signed-off-by: Mark Brown +Signed-off-by: Greg Kroah-Hartman + +--- + 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) { diff --git a/queue-3.18/series b/queue-3.18/series index b5e8fbf707..a373b3a46b 100644 --- a/queue-3.18/series +++ b/queue-3.18/series @@ -50,3 +50,4 @@ netns-provide-pure-entropy-for-net_hash_mix.patch net-ethtool-not-call-vzalloc-for-zero-sized-memory-request.patch ip6_tunnel-match-to-arphrd_tunnel6-for-dev-type.patch alsa-seq-fix-oob-reads-from-strlcpy.patch +asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch