ALSA: ASoC: cs4720: use snd_soc_cache_sync()
Subsystems (3)
PATCH 1/1 ALSA: ASoC: cs4720: use snd_soc_cache_sync()
Replace the manual register restore mechanism in cs4270.c and call snd_soc_cache_sync() instead. The current is also wrong, as it doesn't update the internal cache, leading to cache inconsitency after suspend.
---
Not sure if it's worth marking this one for stable@?
sound/soc/codecs/cs4270.c | 10 +--------- 1 files changed, 1 insertions(+), 9 deletions(-)
sound/soc/codecs/cs4270.c +1 -9
@@ -601,7 +601,6 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)static int cs4270_soc_resume (struct snd_soc_codec *codec) {struct cs4270_private *cs4270 =snd_soc_codec_get_drvdata (codec); -struct i2c_client *i2c_client =to_i2c_client (codec->dev);int reg; regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -612,14 +611,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)ndelay (500 );/* first restore the entire register cache ... */ -for (reg =CS4270_FIRSTREG ; reg <=CS4270_LASTREG ; reg++) { -u8 val =snd_soc_read (codec, reg); - -if (i2c_smbus_write_byte_data (i2c_client, reg, val)) { -dev_err (codec->dev,"i2c write failed\n" ); -return -EIO ; - } - } +snd_soc_cache_sync (codec);/* ... then disable the power-down bits */ reg =snd_soc_read (codec,CS4270_PWRCTL );
Signature · 1 line
1.7.7.3
Quoted 3 lines · Daniel Mack
Replace the manual register restore mechanism in
cs4270.cand callsnd_soc_cache_sync()instead. The current is also wrong, as it doesn't update the internal cache, leading to cache inconsitency after suspend.
I don't understand why this is a bug fix - the code is writing the values from the internal cache to the hardware and what's there doesn't look obviously wrong...
sound/soc/codecs/cs4270.c static int cs4270_soc_resume(struct snd_soc_codec *codec) · line 617
Quoted 4 lines
sound/soc/codecs/cs4270.c +0
-3/* first restore the entire register cache ... */ -for (reg =CS4270_FIRSTREG ; reg <=CS4270_LASTREG ; reg++) { -u8 val =snd_soc_read (codec, reg); -
This reads from the cache.
sound/soc/codecs/cs4270.c static int cs4270_soc_resume(struct snd_soc_codec *codec) · line 621
Quoted 4 lines
sound/soc/codecs/cs4270.c +0
-4-if (i2c_smbus_write_byte_data (i2c_client, reg, val)) { -dev_err (codec->dev,"i2c write failed\n" ); -return -EIO ; - }
This writes the cached value to the hardware.
Quoted 8 lines · Mark Brown
Quoted 3 lines · Daniel Mack
Replace the manual register restore mechanism in
cs4270.cand callsnd_soc_cache_sync()instead. The current is also wrong, as it doesn't update the internal cache, leading to cache inconsitency after suspend.I don't understand why this is a bug fix - the code is writing the values from the internal cache to the hardware and what's there doesn't look obviously wrong...
Hmm, you're right, that isn't obvious. I was too fast in blaming the code wrong as it stands. But as a matter of fact, the patch *does* fix the problem, Sven successfully tested it on various devices.
The bug is reproducible by setting the output volume to 50% before sending the device to suspend. After wakeup, amixer still reports the old volume level, but the codec is in fact set to 100%. Changing it to 50% doesn't do anything, but to any other level has an effect. This is clearly a cache sync bug, but the piece that's missing is the reason why my patch does the right thing.
I'll look into this again - thanks for the heads-up.
Quoted 6 lines · Daniel Mack
The bug is reproducible by setting the output volume to 50% before sending the device to suspend. After wakeup, amixer still reports the old volume level, but the codec is in fact set to 100%. Changing it to 50% doesn't do anything, but to any other level has an effect. This is clearly a cache sync bug, but the piece that's missing is the reason why my patch does the right thing.
That's very odd, not ringing any bells at all. It's not like the existing code is trying to do anything clever with skipping writes, it just blasts in all the register values and it's affecting two different registers.
In any case, the patch is moving to factor code out in favour of core facilities so it's a good idea anyway.
Quoted 4 lines · Mark Brown
That's very odd, not ringing any bells at all. It's not like the existing code is trying to do anything clever with skipping writes, it just blasts in all the register values and it's affecting two different registers.
Is there a quick-and-dirty way to test suspend/resume? It's not officially supported on our board with a CS4270, so I never tried it, and I'm not familiar with it.
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Quoted 10 lines · Timur Tabi
Quoted 4 lines · Mark Brown
That's very odd, not ringing any bells at all. It's not like the existing code is trying to do anything clever with skipping writes, it just blasts in all the register values and it's affecting two different registers.
Is there a quick-and-dirty way to test suspend/resume? It's not officially supported on our board with a CS4270, so I never tried it, and I'm not familiar with it.
echo mem > /sys/power/state
But in our case, the codec is powered off completely, so you might have a very different power regulator setup on your board. And that might cause the bug not to show up, as it retains its register values over suspend.
Daniel
Quoted 3 lines · Timur Tabi
Is there a quick-and-dirty way to test suspend/resume? It's not officially supported on our board with a CS4270, so I never tried it, and I'm not familiar with it.
No, not really. Nearest thing would be to enable idle_bias_off and then do the stuff you currently do in suspend and resume in the bias management (which might not be a bad idea actually, unless there's pops when powering off and on it'll probably save some power).
Quoted 9 lines · Mark Brown
Quoted 6 lines · Daniel Mack
The bug is reproducible by setting the output volume to 50% before sending the device to suspend. After wakeup, amixer still reports the old volume level, but the codec is in fact set to 100%. Changing it to 50% doesn't do anything, but to any other level has an effect. This is clearly a cache sync bug, but the piece that's missing is the reason why my patch does the right thing.
Quoted 4 lines
That's very odd, not ringing any bells at all. It's not like the existing code is trying to do anything clever with skipping writes, it just blasts in all the register values and it's affecting two different registers.
The code is so simple that I'm starting to suspect i2c_smbus_write_byte_data() is doing something very wrong, but I can't trace it without a hardware I2C analyzer right now. The i2c-regmap low-level implementation uses different access functions under the hood, so maybe that's a regression.
We also think that the effect is actually rather new.
Quoted 2 lines
In any case, the patch is moving to factor code out in favour of core facilities so it's a good idea anyway.
Hmm, we should really care for the root cause, but maybe we can still commit this thing, with a more appropriate commit log?
Daniel
Quoted 5 lines · Daniel Mack
The code is so simple that I'm starting to suspect
i2c_smbus_write_byte_data()is doing something very wrong, but I can't trace it without a hardware I2C analyzer right now. The i2c-regmap low-level implementation uses different access functions under the hood, so maybe that's a regression.
What platform are you testing this on? I never really understood the i2c vs. smbus thing (I can never tell which function an i2c device really needs), so I only know that the i2c code works on my PowerPC board.
Also keep in mind that a patch that affects i2c_smbus_write_byte_data() on PowerPC was recently posted, but not approved yet. Check the thread, "i2c/busses: (mpc) Add support for SMBUS_READ_BLOCK_DATA".
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Quoted 8 lines · Timur Tabi
Quoted 5 lines · Daniel Mack
The code is so simple that I'm starting to suspect
i2c_smbus_write_byte_data()is doing something very wrong, but I can't trace it without a hardware I2C analyzer right now. The i2c-regmap low-level implementation uses different access functions under the hood, so maybe that's a regression.What platform are you testing this on?
Some Raumfeld devices feature this codec, connected to an ARM PXA3xx.
Quoted 4 lines
I never really understood the
i2c vs. smbus thing (I can never tell which function an i2c device really needs), so I only know that the i2c code works on my PowerPC board.
Yes, that's a mess. SMBUS is a higher level protocol that is based in I2C and adds an awareness of "registers" and "values". However, it really just resembles to 2-byte instructions on the bus, which is what I needed when I implemented the code some years ago.
Quoted 4 lines
Also keep in mind that a patch that affects
i2c_smbus_write_byte_data()on PowerPC was recently posted, but not approved yet. Check the thread, "i2c/busses: (mpc) Add support forSMBUS_READ_BLOCK_DATA".
Well, we're on a different platform and we don't use BLOCK_DATA transfers but single byte instructions. You still think it's related?
Daniel
Quoted 2 lines · Daniel Mack
Well, we're on a different platform and we don't use
BLOCK_DATAtransfers but single byte instructions. You still think it's related?
I have no idea, I just wanted to bring it to your attention, in case it sparked something. The original code uses i2c_smbus_write_byte_data, but the new code uses i2c_transfer(). Maybe that function is smarter about handling the I2C bus?
Signature · 2 lines
Timur Tabi Linux kernel developer at Freescale
Quoted 5 lines · Daniel Mack
The code is so simple that I'm starting to suspect
i2c_smbus_write_byte_data()is doing something very wrong, but I can't trace it without a hardware I2C analyzer right now. The i2c-regmap low-level implementation uses different access functions under the hood, so maybe that's a regression.
Could be, though I can't see any changes in the code here. It might be that a change between SMBus and regmap at runtime is upsetting the device somehow but given that it's supposed to be coming back from a power on reset...
Quoted 1 line
We also think that the effect is actually rather new.
Does reverting to the non-regmap soc-io.c help?
Quoted 5 lines
Quoted 2 lines
In any case, the patch is moving to factor code out in favour of core facilities so it's a good idea anyway.
Hmm, we should really care for the root cause, but maybe we can still commit this thing, with a more appropriate commit log?
I think so.
Quoted 8 lines · Mark Brown
Quoted 5 lines · Daniel Mack
The code is so simple that I'm starting to suspect
i2c_smbus_write_byte_data()is doing something very wrong, but I can't trace it without a hardware I2C analyzer right now. The i2c-regmap low-level implementation uses different access functions under the hood, so maybe that's a regression.
Quoted 4 lines
Could be, though I can't see any changes in the code here. It might be that a change between SMBus and regmap at runtime is upsetting the device somehow but given that it's supposed to be coming back from a power on reset...
That should affect more codecs then, right?
$ git grep -l i2c_smbus_write sound/ sound/aoa/codecs/onyx.c sound/aoa/codecs/tas.c sound/ppc/daca.c sound/ppc/tumbler.c sound/soc/codecs/tpa6130a2.c
Quoted 3 lines
Quoted 1 line
We also think that the effect is actually rather new.
Does reverting to the non-regmap
soc-io.chelp?
Is there a single commit we can revert on top of 3.2-git to test this?
Quoted 7 lines
Quoted 5 lines
Quoted 2 lines
In any case, the patch is moving to factor code out in favour of core facilities so it's a good idea anyway.
Hmm, we should really care for the root cause, but maybe we can still commit this thing, with a more appropriate commit log?
I think so.
Ok, I'll repost with a better log then.
Quoted 7 lines · Daniel Mack
Quoted 4 lines · Mark Brown
Could be, though I can't see any changes in the code here. It might be that a change between SMBus and regmap at runtime is upsetting the device somehow but given that it's supposed to be coming back from a power on reset...
Quoted 8 lines
That should affect more codecs then, right?
$ git grep -l i2c_smbus_write sound/ sound/aoa/codecs/onyx.c sound/aoa/codecs/tas.c sound/ppc/daca.c sound/ppc/tumbler.c sound/soc/codecs/tpa6130a2.c
None of these use regmap so wouldn't be affected by an interaction between the two. The tpa6130a2 isn't going through the standard ASoC structures at all.
Quoted 3 lines
Quoted 1 line
Does reverting to the non-regmap
soc-io.chelp?Is there a single commit we can revert on top of 3.2-git to test this?
Should be, or a small series anyway. git log sound/soc/soc-io.c should show.