[alsa-devel] [PATCH 1/2] ASoC: codecs: ad193x: Fix memory corruption on BE 64b systems
Since change_bit() requires unsigned long*, making this cast on an unsigned int variable will change a wrong bit on BE platforms, causing memory corruption. Replace this function with a simple XOR.
Fixes: 90f6e6803139 ("ASoC: codecs: ad193x: Fix frame polarity for DSP_A format") Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Codrin Ciubotariu codrin.ciubotariu@microchip.com --- sound/soc/codecs/ad193x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 05f4514048e2..3ebc0524f4b2 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -240,10 +240,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, }
/* For DSP_*, LRCLK's polarity must be inverted */ - if (fmt & SND_SOC_DAIFMT_DSP_A) { - change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1, - (unsigned long *)&dac_fmt); - } + if (fmt & SND_SOC_DAIFMT_DSP_A) + dac_fmt ^= AD193X_DAC_LEFT_HIGH;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
Since the ad193x codecs have no software reset, we have to reinitialize the registers after a hardware reset. For example, if we change the device-tree between these resets, changing the audio format of the DAI link from DSP_A with 8 TDM channels to I2S 2 channels, DAC Control 1 register will remain configured for 8 channels. This patch resets this register at probe to its default value.
Signed-off-by: Codrin Ciubotariu codrin.ciubotariu@microchip.com --- sound/soc/codecs/ad193x.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 3ebc0524f4b2..cda435562a1d 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -427,6 +427,8 @@ static int ad193x_component_probe(struct snd_soc_component *component) regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A); /* dac in tdm mode */ regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x40); + /* reset DAC ctrl1 */ + regmap_write(ad193x->regmap, AD193X_DAC_CTRL1, 0x00);
/* adc only */ if (ad193x_has_adc(ad193x)) {
On Wed, Jun 26, 2019 at 01:49:47PM +0300, Codrin Ciubotariu wrote:
Since the ad193x codecs have no software reset, we have to reinitialize the registers after a hardware reset. For example, if we change the device-tree between these resets, changing the audio format of the DAI link from DSP_A with 8 TDM channels to I2S 2 channels, DAC Control 1 register will remain configured for 8 channels. This patch resets this register at probe to its default value.
Would it not be more robust/complete to have a set of register defaults and write the whole lot out rather than individually going through and adding writes for specific registers as needed?
On 26.06.2019 14:23, Mark Brown wrote:
On Wed, Jun 26, 2019 at 01:49:47PM +0300, Codrin Ciubotariu wrote:
Since the ad193x codecs have no software reset, we have to reinitialize the registers after a hardware reset. For example, if we change the device-tree between these resets, changing the audio format of the DAI link from DSP_A with 8 TDM channels to I2S 2 channels, DAC Control 1 register will remain configured for 8 channels. This patch resets this register at probe to its default value.
Would it not be more robust/complete to have a set of register defaults and write the whole lot out rather than individually going through and adding writes for specific registers as needed?
It would indeed. I will make two patches, one that implements what you suggested, for the registers that we touch only, and another one that will add AD193X_DAC_CTRL1 to these defaults. You can drop this patch.
Thanks and best regards, Codrin
The patch
ASoC: codecs: ad193x: Fix memory corruption on BE 64b systems
has been applied to the asoc tree at
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git for-5.2
All being well this means that it will be integrated into the linux-next tree (usually sometime in the next 24 hours) and sent to Linus during the next merge window (or sooner if it is a bug fix), however if problems are discovered then the patch may be dropped or reverted.
You may get further e-mails resulting from automated or manual testing and review of the tree, please engage with people reporting problems and send followup patches addressing any issues that are reported if needed.
If any updates are required or you are submitting further changes they should be sent as incremental updates against current git, existing patches will not be replaced.
Please add any relevant lists and maintainers to the CCs when replying to this mail.
Thanks, Mark
From da7260cc8d1dc3564eb4f33550b0525541d71a47 Mon Sep 17 00:00:00 2001
From: Codrin Ciubotariu codrin.ciubotariu@microchip.com Date: Wed, 26 Jun 2019 13:49:46 +0300 Subject: [PATCH] ASoC: codecs: ad193x: Fix memory corruption on BE 64b systems
Since change_bit() requires unsigned long*, making this cast on an unsigned int variable will change a wrong bit on BE platforms, causing memory corruption. Replace this function with a simple XOR.
Fixes: 90f6e6803139 ("ASoC: codecs: ad193x: Fix frame polarity for DSP_A format") Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Codrin Ciubotariu codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown broonie@kernel.org --- sound/soc/codecs/ad193x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 96d7cb2e4a56..16e2d334bbe0 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -241,10 +241,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, }
/* For DSP_*, LRCLK's polarity must be inverted */ - if (fmt & SND_SOC_DAIFMT_DSP_A) { - change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1, - (unsigned long *)&dac_fmt); - } + if (fmt & SND_SOC_DAIFMT_DSP_A) + dac_fmt ^= AD193X_DAC_LEFT_HIGH;
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
On 06/26/2019 12:49 PM, Codrin Ciubotariu wrote:
Since change_bit() requires unsigned long*, making this cast on an unsigned int variable will change a wrong bit on BE platforms, causing memory corruption. Replace this function with a simple XOR.
Fixes: 90f6e6803139 ("ASoC: codecs: ad193x: Fix frame polarity for DSP_A format") Reported-by: Dan Carpenter dan.carpenter@oracle.com Signed-off-by: Codrin Ciubotariu codrin.ciubotariu@microchip.com
sound/soc/codecs/ad193x.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 05f4514048e2..3ebc0524f4b2 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c @@ -240,10 +240,8 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai, }
/* For DSP_*, LRCLK's polarity must be inverted */
- if (fmt & SND_SOC_DAIFMT_DSP_A) {
change_bit(ffs(AD193X_DAC_LEFT_HIGH) - 1,
(unsigned long *)&dac_fmt);
- }
- if (fmt & SND_SOC_DAIFMT_DSP_A)
dac_fmt ^= AD193X_DAC_LEFT_HIGH;
BigEndian RULEZ! ;-P
participants (4)
-
Codrin Ciubotariu
-
Codrin.Ciubotariu@microchip.com
-
gianluca
-
Mark Brown