All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Péter Ujfalusi" <peter.ujfalusi@gmail.com>
To: Peter Rosin <peda@axentia.se>,
	"alsa-devel@alsa-project.org" <alsa-devel@alsa-project.org>
Cc: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Takashi Iwai <tiwai@suse.com>,
	Liam Girdwood <lgirdwood@gmail.com>,
	Kirill Marinushkin <kmarinushkin@birdec.com>,
	Mark Brown <broonie@kernel.org>
Subject: Re: [PATCH] ASoC: pcm512x: Mend accesses to the I2S_1 and I2S_2 registers
Date: Tue, 21 Sep 2021 07:20:52 +0300	[thread overview]
Message-ID: <7537b141-0ef1-fb44-7e02-27b4dd1e772b@gmail.com> (raw)
In-Reply-To: <815cbba4-60d6-8d97-c483-146c2f7c3912@axentia.se>

[-- Attachment #1: Type: text/plain, Size: 4825 bytes --]

Hi Peter.

On 20/09/2021 22:37, Peter Rosin wrote:

> Nope, MODE1/2 are wired for I2C -> FMT is just the last I2C address
> bit. So, nothing to do with I2S. And I can't see how that would explain
> the same problem with the I2S_2 register?

true, but worth the question ;)
 
>>> This fix is not 100% correct. The datasheet of at least the pcm5142
>>> states that four bits (0xcc) in the I2S_1 register are "RSV"
>>> ("Reserved. Do not access.") and no hint is given as to what theHi
>>> initial values are supposed to be. So, specifying defaults for
>>> these bits is wrong. But perhaps better than a broken driver?
>>
>> The default of 0x02 (AFMT = 00b - I2S, ALEN = 10b - 24bits) is correct
>> for I2S_1 and the 0 is the default of I2S_2.
>>
>> The failure happens when updating the AFMT (bit4-5) and when regmap is
>> doing a i2c read since the default is not specified.
>>
>> It would be interesting to see what it is reading... Out of interest:
>> can you mar the I2S_1 and I2S_2 as volatile and read / print the value
>> just before the afmt and alen update?
> 
> My first attempt was to mark the register volatile, and then read and
> compare if the update was needed at all. But marking volatile wasn't
> enough.

If the value is not provided in the defaults then the first read is reading out to the chip anyways.

> I also tried to set both a default and mark as volatile,

Volatile always skips the cache, default would be ignored.

> but it seems every read fails with -16 (EBUSY). I don't get why, to me
> it almost feels like a regmap issue of some sort (probably the regmap
> config is bad in some way), but I'm not fluent in regmap...

Or most likely the chip is not powered at pcm512x_set_fmt() time?

> So, since I can't read, I can't get to the initial values of the four
> reserved bits. So, I winged them as zero.

The value of the reserved bits are don't care.

Can you try the attached patch w/o without the defaults for i2s_1/2?
Not even compile tested...

From e013a03286b6a744914c50239d3123b7723068df Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Date: Tue, 21 Sep 2021 07:12:06 +0300
Subject: [PATCH] ASoC: pcm512x: test regmap register accesses

read i2c_1 in different stages.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
 sound/soc/codecs/pcm512x.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4dc844f3c1fc..d0382e9ac329 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1166,6 +1166,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int alen;
 	int gpio;
 	int ret;
@@ -1193,6 +1194,18 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_ALEN, alen);
 	if (ret != 0) {
@@ -1335,6 +1348,7 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int afmt;
 	int offset = 0;
 	int clock_output;
@@ -1396,18 +1410,28 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_AFMT, afmt);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data format: %d\n", ret);
-		return ret;
 	}
 
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_2,
 				 0xFF, offset);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data offset: %d\n", ret);
-		return ret;
 	}
 
 	pcm512x->fmt = fmt;
-- 
2.33.0



-- 
Péter

[-- Attachment #2: 0001-ASoC-pcm512x-test-regmap-register-accesses.patch --]
[-- Type: text/x-patch, Size: 2832 bytes --]

From e013a03286b6a744914c50239d3123b7723068df Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Date: Tue, 21 Sep 2021 07:12:06 +0300
Subject: [PATCH] ASoC: pcm512x: test regmap register accesses

read i2c_1 in different stages.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
 sound/soc/codecs/pcm512x.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4dc844f3c1fc..d0382e9ac329 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1166,6 +1166,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int alen;
 	int gpio;
 	int ret;
@@ -1193,6 +1194,18 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_ALEN, alen);
 	if (ret != 0) {
@@ -1335,6 +1348,7 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int afmt;
 	int offset = 0;
 	int clock_output;
@@ -1396,18 +1410,28 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_AFMT, afmt);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data format: %d\n", ret);
-		return ret;
 	}
 
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_2,
 				 0xFF, offset);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data offset: %d\n", ret);
-		return ret;
 	}
 
 	pcm512x->fmt = fmt;
-- 
2.33.0


WARNING: multiple messages have this Message-ID (diff)
From: "Péter Ujfalusi" <peter.ujfalusi@gmail.com>
To: Peter Rosin <peda@axentia.se>,
	"alsa-devel@alsa-project.org" <alsa-devel@alsa-project.org>
Cc: Liam Girdwood <lgirdwood@gmail.com>,
	Mark Brown <broonie@kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Kirill Marinushkin <kmarinushkin@birdec.com>,
	Takashi Iwai <tiwai@suse.com>
Subject: Re: [PATCH] ASoC: pcm512x: Mend accesses to the I2S_1 and I2S_2 registers
Date: Tue, 21 Sep 2021 07:20:52 +0300	[thread overview]
Message-ID: <7537b141-0ef1-fb44-7e02-27b4dd1e772b@gmail.com> (raw)
In-Reply-To: <815cbba4-60d6-8d97-c483-146c2f7c3912@axentia.se>

[-- Attachment #1: Type: text/plain, Size: 4825 bytes --]

Hi Peter.

On 20/09/2021 22:37, Peter Rosin wrote:

> Nope, MODE1/2 are wired for I2C -> FMT is just the last I2C address
> bit. So, nothing to do with I2S. And I can't see how that would explain
> the same problem with the I2S_2 register?

true, but worth the question ;)
 
>>> This fix is not 100% correct. The datasheet of at least the pcm5142
>>> states that four bits (0xcc) in the I2S_1 register are "RSV"
>>> ("Reserved. Do not access.") and no hint is given as to what theHi
>>> initial values are supposed to be. So, specifying defaults for
>>> these bits is wrong. But perhaps better than a broken driver?
>>
>> The default of 0x02 (AFMT = 00b - I2S, ALEN = 10b - 24bits) is correct
>> for I2S_1 and the 0 is the default of I2S_2.
>>
>> The failure happens when updating the AFMT (bit4-5) and when regmap is
>> doing a i2c read since the default is not specified.
>>
>> It would be interesting to see what it is reading... Out of interest:
>> can you mar the I2S_1 and I2S_2 as volatile and read / print the value
>> just before the afmt and alen update?
> 
> My first attempt was to mark the register volatile, and then read and
> compare if the update was needed at all. But marking volatile wasn't
> enough.

If the value is not provided in the defaults then the first read is reading out to the chip anyways.

> I also tried to set both a default and mark as volatile,

Volatile always skips the cache, default would be ignored.

> but it seems every read fails with -16 (EBUSY). I don't get why, to me
> it almost feels like a regmap issue of some sort (probably the regmap
> config is bad in some way), but I'm not fluent in regmap...

Or most likely the chip is not powered at pcm512x_set_fmt() time?

> So, since I can't read, I can't get to the initial values of the four
> reserved bits. So, I winged them as zero.

The value of the reserved bits are don't care.

Can you try the attached patch w/o without the defaults for i2s_1/2?
Not even compile tested...

From e013a03286b6a744914c50239d3123b7723068df Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Date: Tue, 21 Sep 2021 07:12:06 +0300
Subject: [PATCH] ASoC: pcm512x: test regmap register accesses

read i2c_1 in different stages.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
 sound/soc/codecs/pcm512x.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4dc844f3c1fc..d0382e9ac329 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1166,6 +1166,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int alen;
 	int gpio;
 	int ret;
@@ -1193,6 +1194,18 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_ALEN, alen);
 	if (ret != 0) {
@@ -1335,6 +1348,7 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int afmt;
 	int offset = 0;
 	int clock_output;
@@ -1396,18 +1410,28 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_AFMT, afmt);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data format: %d\n", ret);
-		return ret;
 	}
 
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_2,
 				 0xFF, offset);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data offset: %d\n", ret);
-		return ret;
 	}
 
 	pcm512x->fmt = fmt;
-- 
2.33.0



-- 
Péter

[-- Attachment #2: 0001-ASoC-pcm512x-test-regmap-register-accesses.patch --]
[-- Type: text/x-patch, Size: 2832 bytes --]

From e013a03286b6a744914c50239d3123b7723068df Mon Sep 17 00:00:00 2001
From: Peter Ujfalusi <peter.ujfalusi@gmail.com>
Date: Tue, 21 Sep 2021 07:12:06 +0300
Subject: [PATCH] ASoC: pcm512x: test regmap register accesses

read i2c_1 in different stages.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@gmail.com>
---
 sound/soc/codecs/pcm512x.c | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index 4dc844f3c1fc..d0382e9ac329 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -1166,6 +1166,7 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int alen;
 	int gpio;
 	int ret;
@@ -1193,6 +1194,18 @@ static int pcm512x_hw_params(struct snd_pcm_substream *substream,
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_ALEN, alen);
 	if (ret != 0) {
@@ -1335,6 +1348,7 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
 	struct snd_soc_component *component = dai->component;
 	struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
+	unsigned int val;
 	int afmt;
 	int offset = 0;
 	int clock_output;
@@ -1396,18 +1410,28 @@ static int pcm512x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 		return -EINVAL;
 	}
 
+	ret = regmap_read(pcm512x->regmap, PCM512x_I2S_1, &val);
+	if (ret) {
+		dev_err(component->dev, "%s: failed to read I2S_1: %d\n", __func_, ret);
+		ret = regmap_read(pcm512x->regmap, PCM512x_PLL_EN, &val);
+		if (ret)
+			dev_err(component->dev, "%s: failed to read PLL_EN: %d\n", __func__, ret);
+		else
+			dev_err(component->dev, "%s: PLL_EN: %#x\n", __func__, val);
+	} else {
+		dev_err(component->dev, "%s: I2S_1: %#x\n", __func__, val);
+	}
+
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_1,
 				 PCM512x_AFMT, afmt);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data format: %d\n", ret);
-		return ret;
 	}
 
 	ret = regmap_update_bits(pcm512x->regmap, PCM512x_I2S_2,
 				 0xFF, offset);
 	if (ret != 0) {
 		dev_err(component->dev, "Failed to set data offset: %d\n", ret);
-		return ret;
 	}
 
 	pcm512x->fmt = fmt;
-- 
2.33.0


  parent reply	other threads:[~2021-09-21  4:20 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-20 14:49 [PATCH] ASoC: pcm512x: Mend accesses to the I2S_1 and I2S_2 registers Peter Rosin
2021-09-20 14:49 ` Peter Rosin
2021-09-20 18:37 ` Péter Ujfalusi
2021-09-20 19:37   ` Peter Rosin
2021-09-20 19:37     ` Peter Rosin
2021-09-20 21:29     ` Mark Brown
2021-09-20 21:29       ` Mark Brown
2021-09-21  6:37       ` Peter Rosin
2021-09-21  6:37         ` Peter Rosin
2021-09-21 11:11         ` Mark Brown
2021-09-21 11:11           ` Mark Brown
2021-09-21  4:20     ` Péter Ujfalusi [this message]
2021-09-21  4:20       ` Péter Ujfalusi
2021-09-21  6:52       ` Peter Rosin
2021-09-21  6:52         ` Peter Rosin
2021-09-21  8:10         ` Peter Rosin
2021-09-21  8:10           ` Peter Rosin
2021-09-21  8:48           ` Peter Rosin
2021-09-21  8:48             ` Peter Rosin
2021-09-21 12:01             ` Mark Brown
2021-09-21 12:01               ` Mark Brown
2021-09-21 13:30               ` Peter Rosin
2021-09-21 13:30                 ` Peter Rosin
2021-09-21 17:22                 ` Péter Ujfalusi
2021-09-21 15:25 ` Mark Brown
2021-09-21 15:25   ` Mark Brown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7537b141-0ef1-fb44-7e02-27b4dd1e772b@gmail.com \
    --to=peter.ujfalusi@gmail.com \
    --cc=alsa-devel@alsa-project.org \
    --cc=broonie@kernel.org \
    --cc=kmarinushkin@birdec.com \
    --cc=lgirdwood@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=peda@axentia.se \
    --cc=tiwai@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.