From: Greg Kroah-Hartman Date: Mon, 15 Apr 2019 11:34:00 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.9.169~26 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f0c75f3871403a5efb9fb556deb7852192096851;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch include-linux-bitrev.h-fix-constant-bitrev.patch --- diff --git a/queue-4.4/asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch b/queue-4.4/asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch new file mode 100644 index 00000000000..22e4b190efc --- /dev/null +++ b/queue-4.4/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; + } +@@ -582,6 +576,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: +@@ -594,15 +589,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), +@@ -887,6 +905,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-4.4/include-linux-bitrev.h-fix-constant-bitrev.patch b/queue-4.4/include-linux-bitrev.h-fix-constant-bitrev.patch new file mode 100644 index 00000000000..48b39cd52e5 --- /dev/null +++ b/queue-4.4/include-linux-bitrev.h-fix-constant-bitrev.patch @@ -0,0 +1,112 @@ +From 6147e136ff5071609b54f18982dea87706288e21 Mon Sep 17 00:00:00 2001 +From: Arnd Bergmann +Date: Fri, 5 Apr 2019 18:38:53 -0700 +Subject: include/linux/bitrev.h: fix constant bitrev + +From: Arnd Bergmann + +commit 6147e136ff5071609b54f18982dea87706288e21 upstream. + +clang points out with hundreds of warnings that the bitrev macros have a +problem with constant input: + + drivers/hwmon/sht15.c:187:11: error: variable '__x' is uninitialized when used within its own initialization + [-Werror,-Wuninitialized] + u8 crc = bitrev8(data->val_status & 0x0F); + ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + include/linux/bitrev.h:102:21: note: expanded from macro 'bitrev8' + __constant_bitrev8(__x) : \ + ~~~~~~~~~~~~~~~~~~~^~~~ + include/linux/bitrev.h:67:11: note: expanded from macro '__constant_bitrev8' + u8 __x = x; \ + ~~~ ^ + +Both the bitrev and the __constant_bitrev macros use an internal +variable named __x, which goes horribly wrong when passing one to the +other. + +The obvious fix is to rename one of the variables, so this adds an extra +'_'. + +It seems we got away with this because + + - there are only a few drivers using bitrev macros + + - usually there are no constant arguments to those + + - when they are constant, they tend to be either 0 or (unsigned)-1 + (drivers/isdn/i4l/isdnhdlc.o, drivers/iio/amplifiers/ad8366.c) and + give the correct result by pure chance. + +In fact, the only driver that I could find that gets different results +with this is drivers/net/wan/slic_ds26522.c, which in turn is a driver +for fairly rare hardware (adding the maintainer to Cc for testing). + +Link: http://lkml.kernel.org/r/20190322140503.123580-1-arnd@arndb.de +Fixes: 556d2f055bf6 ("ARM: 8187/1: add CONFIG_HAVE_ARCH_BITREVERSE to support rbit instruction") +Signed-off-by: Arnd Bergmann +Reviewed-by: Nick Desaulniers +Cc: Zhao Qiang +Cc: Yalin Wang +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/bitrev.h | 36 ++++++++++++++++++------------------ + 1 file changed, 18 insertions(+), 18 deletions(-) + +--- a/include/linux/bitrev.h ++++ b/include/linux/bitrev.h +@@ -31,32 +31,32 @@ static inline u32 __bitrev32(u32 x) + + #define __constant_bitrev32(x) \ + ({ \ +- u32 __x = x; \ +- __x = (__x >> 16) | (__x << 16); \ +- __x = ((__x & (u32)0xFF00FF00UL) >> 8) | ((__x & (u32)0x00FF00FFUL) << 8); \ +- __x = ((__x & (u32)0xF0F0F0F0UL) >> 4) | ((__x & (u32)0x0F0F0F0FUL) << 4); \ +- __x = ((__x & (u32)0xCCCCCCCCUL) >> 2) | ((__x & (u32)0x33333333UL) << 2); \ +- __x = ((__x & (u32)0xAAAAAAAAUL) >> 1) | ((__x & (u32)0x55555555UL) << 1); \ +- __x; \ ++ u32 ___x = x; \ ++ ___x = (___x >> 16) | (___x << 16); \ ++ ___x = ((___x & (u32)0xFF00FF00UL) >> 8) | ((___x & (u32)0x00FF00FFUL) << 8); \ ++ ___x = ((___x & (u32)0xF0F0F0F0UL) >> 4) | ((___x & (u32)0x0F0F0F0FUL) << 4); \ ++ ___x = ((___x & (u32)0xCCCCCCCCUL) >> 2) | ((___x & (u32)0x33333333UL) << 2); \ ++ ___x = ((___x & (u32)0xAAAAAAAAUL) >> 1) | ((___x & (u32)0x55555555UL) << 1); \ ++ ___x; \ + }) + + #define __constant_bitrev16(x) \ + ({ \ +- u16 __x = x; \ +- __x = (__x >> 8) | (__x << 8); \ +- __x = ((__x & (u16)0xF0F0U) >> 4) | ((__x & (u16)0x0F0FU) << 4); \ +- __x = ((__x & (u16)0xCCCCU) >> 2) | ((__x & (u16)0x3333U) << 2); \ +- __x = ((__x & (u16)0xAAAAU) >> 1) | ((__x & (u16)0x5555U) << 1); \ +- __x; \ ++ u16 ___x = x; \ ++ ___x = (___x >> 8) | (___x << 8); \ ++ ___x = ((___x & (u16)0xF0F0U) >> 4) | ((___x & (u16)0x0F0FU) << 4); \ ++ ___x = ((___x & (u16)0xCCCCU) >> 2) | ((___x & (u16)0x3333U) << 2); \ ++ ___x = ((___x & (u16)0xAAAAU) >> 1) | ((___x & (u16)0x5555U) << 1); \ ++ ___x; \ + }) + + #define __constant_bitrev8(x) \ + ({ \ +- u8 __x = x; \ +- __x = (__x >> 4) | (__x << 4); \ +- __x = ((__x & (u8)0xCCU) >> 2) | ((__x & (u8)0x33U) << 2); \ +- __x = ((__x & (u8)0xAAU) >> 1) | ((__x & (u8)0x55U) << 1); \ +- __x; \ ++ u8 ___x = x; \ ++ ___x = (___x >> 4) | (___x << 4); \ ++ ___x = ((___x & (u8)0xCCU) >> 2) | ((___x & (u8)0x33U) << 2); \ ++ ___x = ((___x & (u8)0xAAU) >> 1) | ((___x & (u8)0x55U) << 1); \ ++ ___x; \ + }) + + #define bitrev32(x) \ diff --git a/queue-4.4/series b/queue-4.4/series index 19b1a3cc9e3..72a187f9495 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -85,3 +85,5 @@ 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 +include-linux-bitrev.h-fix-constant-bitrev.patch +asoc-fsl_esai-fix-channel-swap-issue-when-stream-starts.patch