[alsa-devel] [PATCH 00/10] Convert wm8xxx codec drivers to use snd_soc_cache_sync
This serial converts the wm8xxx codec drivers to use snd_soc_cache_sync. I don't have these hardware, but I assume Mark has all these hardware. These patches are UNTESTED. I'd appreciate if someone can test them. (Current code is broken anyway, thus we need convert to use new API. )
Axel Lin (10): ASoC: wm8510: Convert to snd_soc_cache_sync ASoC: wm8711: Convert to snd_soc_cache_sync ASoC: wm8731: Convert to snd_soc_cache_sync ASoC: wm8750: Convert to snd_soc_cache_sync ASoC: wm8776: Convert to snd_soc_cache_sync ASoC: wm8940: Convert to snd_soc_cache_sync ASoC: wm8960: Convert to snd_soc_cache_sync ASoC: wm8971: Convert to snd_soc_cache_sync ASoC: wm8974: Convert to snd_soc_cache_sync ASoC: wm8988: Convert to snd_soc_cache_sync
sound/soc/codecs/wm8510.c | 30 ++++++++++++++++++---------- sound/soc/codecs/wm8711.c | 19 +++++++---------- sound/soc/codecs/wm8731.c | 29 ++++++++++++++++----------- sound/soc/codecs/wm8750.c | 32 +++++++++++++++++------------- sound/soc/codecs/wm8776.c | 33 ++++++++++++++++++------------- sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- sound/soc/codecs/wm8960.c | 37 +++++++++++++++++++++++++---------- sound/soc/codecs/wm8971.c | 32 +++++++++++++++++++----------- sound/soc/codecs/wm8974.c | 29 +++++++++++++++++---------- sound/soc/codecs/wm8988.c | 32 +++++++++++++++++------------- 10 files changed, 185 insertions(+), 134 deletions(-)
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8510.c | 30 +++++++++++++++++++----------- 1 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 55a4c83..8e2fe22 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -55,6 +55,17 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = { #define WM8510_POWER1_BIASEN 0x08 #define WM8510_POWER1_BUFIOEN 0x10
+static int wm8510_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8510_RESET: + return 1; + default: + return 0; + } +} + #define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
/* codec private data */ @@ -467,6 +478,7 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
switch (level) { @@ -480,6 +492,12 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); @@ -541,18 +559,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8510_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; }
@@ -597,6 +604,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { .reg_cache_size = ARRAY_SIZE(wm8510_reg), .reg_word_size = sizeof(u16), .reg_cache_default =wm8510_reg, + .volatile_register = wm8510_volatile_register, };
static const struct of_device_id wm8510_of_match[] = {
On Thu, Oct 06, 2011 at 02:11:43PM +0800, Axel Lin wrote:
+static int wm8510_volatile_register(struct snd_soc_codec *codec,
unsigned int reg)
+{
- switch (reg) {
- case WM8510_RESET:
return 1;
- default:
return 0;
- }
+}
This is wrong in quite a few of the patches - all the 7, 9 CODECs are write only, there's no readback support at all (in general if the driver isn't actully verifying a device ID or otherwise doing a physical read then it probably doesn't support readback).
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8711.c | 19 ++++++++----------- 1 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 47c7fd5..b489edf 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -291,6 +291,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f;
switch (level) { @@ -300,6 +301,13 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + } snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: @@ -346,18 +354,7 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8711_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; }
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8731.c | 29 +++++++++++++++++------------ 1 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index f76b6fc..78cbcf8 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -63,6 +63,17 @@ static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { 0x0000, 0x0000 };
+static int wm8731_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8731_RESET: + return 1; + default: + return 0; + } +} + #define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
static const char *wm8731_input_select[] = {"Line In", "Mic"}; @@ -427,9 +438,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec); - int i, ret; - u8 data[2]; - u16 *cache = codec->reg_cache; + int ret; u16 reg;
switch (level) { @@ -444,15 +453,10 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec, if (ret != 0) return ret;
- /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { - if (cache[i] == wm8731_reg[i]) - continue; - - data[0] = (i << 1) | ((cache[i] >> 8) - & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; } }
@@ -606,6 +610,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets), .dapm_routes = wm8731_intercon, .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), + .volatile_register = wm8731_volatile_register, };
static const struct of_device_id wm8731_of_match[] = {
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8750.c | 32 ++++++++++++++++++-------------- 1 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 862c520..7e5af9f 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -55,6 +55,17 @@ struct wm8750_priv { enum snd_soc_control_type control_type; };
+static int wm8750_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8750_RESET: + return 1; + default: + return 0; + } +} + #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
/* @@ -605,6 +616,7 @@ static int wm8750_mute(struct snd_soc_dai *dai, int mute) static int wm8750_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
switch (level) { @@ -616,6 +628,11 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } /* Set VMID to 5k */ snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
@@ -673,21 +690,7 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8750_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) { - if (i == WM8750_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; }
@@ -742,6 +745,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { .reg_cache_size = ARRAY_SIZE(wm8750_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8750_reg, + .volatile_register = wm8750_volatile_register, };
static const struct of_device_id wm8750_of_match[] = {
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8776.c | 33 +++++++++++++++++++-------------- 1 files changed, 19 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 00d8846..4f24446 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -37,6 +37,17 @@ struct wm8776_priv { int sysclk[2]; };
+static int wm8776_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8776_RESET: + return 1; + default: + return 0; + } +} + static const u16 wm8776_reg[WM8776_CACHEREGNUM] = { 0x79, 0x79, 0x79, 0xff, 0xff, /* 4 */ 0xff, 0x00, 0x90, 0x00, 0x00, /* 9 */ @@ -301,6 +312,8 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, static int wm8776_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; + switch (level) { case SND_SOC_BIAS_ON: break; @@ -308,6 +321,11 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); } @@ -379,21 +397,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8776_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) { - if (cache[i] == wm8776_reg[i]) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; } #else @@ -451,6 +455,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { .reg_cache_size = ARRAY_SIZE(wm8776_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8776_reg, + .volatile_register = wm8776_volatile_register, };
static const struct of_device_id wm8776_of_match[] = {
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- 1 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 7e0f54c..a4abfdf 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -45,6 +45,17 @@ struct wm8940_priv { enum snd_soc_control_type control_type; };
+static int wm8940_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8940_SOFTRESET: + return 1; + default: + return 0; + } +} + static u16 wm8940_reg_defaults[] = { 0x8940, /* Soft Reset */ 0x0000, /* Power 1 */ @@ -459,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + } + /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* set vmid to 300k for standby */ @@ -659,30 +678,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8940_resume(struct snd_soc_codec *codec) { - int i; - int ret; - u8 data[3]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware - * Could use auto incremented writes to speed this up - */ - for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) { - data[0] = i; - data[1] = (cache[i] & 0xFF00) >> 8; - data[2] = cache[i] & 0x00FF; - ret = codec->hw_write(codec->control_data, data, 3); - if (ret < 0) - goto error_ret; - else if (ret != 3) { - ret = -EIO; - goto error_ret; - } - } - ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - -error_ret: - return ret; + wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY); + return 0; }
static int wm8940_probe(struct snd_soc_codec *codec) @@ -742,6 +739,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), .reg_word_size = sizeof(u16), .reg_cache_default = wm8940_reg_defaults, + .volatile_register = wm8940_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
On 10/06/11 07:17, Axel Lin wrote:
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Looks sane, but I'm not that familiar with the cache side of things, so you'll want an ack from someone who is. One comment inline.
Signed-off-by: Axel Lin axel.lin@gmail.com
sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- 1 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 7e0f54c..a4abfdf 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c @@ -45,6 +45,17 @@ struct wm8940_priv { enum snd_soc_control_type control_type; };
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
unsigned int reg)
+{
- switch (reg) {
- case WM8940_SOFTRESET:
return 1;
- default:
return 0;
- }
+}
I guess this makes sense from point of view of keeping things inline with more complex drivers. Otherwise I'd expect to see something like: { return !!(reg == WM894_SOFTRESET); }
static u16 wm8940_reg_defaults[] = { 0x8940, /* Soft Reset */ 0x0000, /* Power 1 */ @@ -459,6 +470,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec, ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1); break; case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
ret = snd_soc_cache_sync(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
return ret;
}
}
- /* ensure bufioen and biasen */ pwr_reg |= (1 << 2) | (1 << 3); /* set vmid to 300k for standby */
@@ -659,30 +678,8 @@ static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8940_resume(struct snd_soc_codec *codec) {
- int i;
- int ret;
- u8 data[3];
- u16 *cache = codec->reg_cache;
- /* Sync reg_cache with the hardware
* Could use auto incremented writes to speed this up
*/
- for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
data[0] = i;
data[1] = (cache[i] & 0xFF00) >> 8;
data[2] = cache[i] & 0x00FF;
ret = codec->hw_write(codec->control_data, data, 3);
if (ret < 0)
goto error_ret;
else if (ret != 3) {
ret = -EIO;
goto error_ret;
}
- }
- ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-error_ret:
- return ret;
- wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- return 0;
}
static int wm8940_probe(struct snd_soc_codec *codec) @@ -742,6 +739,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = { .reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults), .reg_word_size = sizeof(u16), .reg_cache_default = wm8940_reg_defaults,
- .volatile_register = wm8940_volatile_register,
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
+{
- switch (reg) {
- case WM8940_SOFTRESET:
- return 1;
- default:
- return 0;
- }
+}
I guess this makes sense from point of view of keeping things inline with more complex drivers. Otherwise I'd expect to see something like: { return !!(reg == WM894_SOFTRESET); }
Either is ok to me. But current syntax makes it easier to add more registers to be volatile if necessary.
So I'll let Mark decide if I need to send a v2 for changing this.
Regards, Axel
On Thu, Oct 06, 2011 at 12:28:41PM +0100, Jonathan Cameron wrote:
On 10/06/11 07:17, Axel Lin wrote:
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
unsigned int reg)
+{
- switch (reg) {
- case WM8940_SOFTRESET:
return 1;
- default:
return 0;
- }
+}
I guess this makes sense from point of view of keeping things inline with more complex drivers. Otherwise I'd expect to see something like: { return !!(reg == WM894_SOFTRESET); }
On the other hand we actually want people to be able to read the code (though the !! there which is the major complication isn't actually doing anything...).
On 10/06/11 14:18, Mark Brown wrote:
On Thu, Oct 06, 2011 at 12:28:41PM +0100, Jonathan Cameron wrote:
On 10/06/11 07:17, Axel Lin wrote:
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
unsigned int reg)
+{
- switch (reg) {
- case WM8940_SOFTRESET:
return 1;
- default:
return 0;
- }
+}
I guess this makes sense from point of view of keeping things inline with more complex drivers. Otherwise I'd expect to see something like: { return !!(reg == WM894_SOFTRESET); }
On the other hand we actually want people to be able to read the code (though the !! there which is the major complication isn't actually doing anything...).
Fair point.
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8960.c | 37 ++++++++++++++++++++++++++----------- 1 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 831c20f..ef5c2d8 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -81,6 +81,17 @@ struct wm8960_priv { int playback_fs; };
+static int wm8960_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8960_RESET: + return 1; + default: + return 0; + } +} + #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
/* enumerated controls */ @@ -558,6 +569,7 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 reg;
switch (level) { @@ -574,6 +586,12 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -620,7 +638,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int reg; + int reg, ret;
switch (level) { case SND_SOC_BIAS_ON: @@ -629,6 +647,12 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: switch (codec->dapm.bias_level) { case SND_SOC_BIAS_STANDBY: + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* Enable anti pop mode */ snd_soc_update_bits(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -901,16 +925,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8960_resume(struct snd_soc_codec *codec) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - }
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -998,6 +1012,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .reg_cache_size = ARRAY_SIZE(wm8960_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8960_reg, + .volatile_register = wm8960_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- v2: Just found in v1 I put snd_soc_cache_sync() at wrong place in wm8960_set_bias_level_capless().
sound/soc/codecs/wm8960.c | 38 +++++++++++++++++++++++++++----------- 1 files changed, 27 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 831c20f..e8262a0 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -81,6 +81,17 @@ struct wm8960_priv { int playback_fs; };
+static int wm8960_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8960_RESET: + return 1; + default: + return 0; + } +} + #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
/* enumerated controls */ @@ -558,6 +569,7 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 reg;
switch (level) { @@ -574,6 +586,12 @@ static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -620,7 +638,7 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int reg; + int reg, ret;
switch (level) { case SND_SOC_BIAS_ON: @@ -697,6 +715,13 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, WM8960_BUFDCOPEN); break;
+ case SND_SOC_BIAS_OFF: + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + break; default: break; } @@ -901,16 +926,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state) static int wm8960_resume(struct snd_soc_codec *codec) { struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - }
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; @@ -998,6 +1013,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = { .reg_cache_size = ARRAY_SIZE(wm8960_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8960_reg, + .volatile_register = wm8960_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8971.c | 32 ++++++++++++++++++++------------ 1 files changed, 20 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 08ea6f8..b50927f 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -58,6 +58,17 @@ static const u16 wm8971_reg[] = { 0x0079, 0x0079, 0x0079, /* 40 */ };
+static int wm8971_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8971_RESET: + return 1; + default: + return 0; + } +} + #define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
/* WM8971 Controls */ @@ -536,6 +547,7 @@ static int wm8971_mute(struct snd_soc_dai *dai, int mute) static int wm8971_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
switch (level) { @@ -546,6 +558,13 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec, case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: + if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + } /* mute dac and set vmid to 500k, enable VREF */ snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); break; @@ -605,20 +624,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8971_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; u16 reg;
- /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) { - if (i == WM8971_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* charge wm8971 caps */ @@ -696,6 +703,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { .reg_cache_size = ARRAY_SIZE(wm8971_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8971_reg, + .volatile_register = wm8971_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8974.c | 29 ++++++++++++++++++----------- 1 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index ca646a8..e25f0ad 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -46,6 +46,17 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = { 0x0000, };
+static int wm8974_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8974_RESET: + return 1; + default: + return 0; + } +} + #define WM8974_POWER1_BIASEN 0x08 #define WM8974_POWER1_BUFIOEN 0x04
@@ -517,6 +528,7 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute) static int wm8974_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 power1 = snd_soc_read(codec, WM8974_POWER1) & ~0x3;
switch (level) { @@ -530,6 +542,11 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec, power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); mdelay(100); @@ -589,18 +606,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8974_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) { - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; }
@@ -644,6 +650,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = { .reg_cache_size = ARRAY_SIZE(wm8974_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8974_reg, + .volatile_register = wm8974_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
Convert to snd_soc_cache_sync for sync reg_cache with the hardware.
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8988.c | 32 ++++++++++++++++++-------------- 1 files changed, 18 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 1c6f8bf..ed453e5 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -55,6 +55,16 @@ struct wm8988_priv { struct snd_pcm_hw_constraint_list *sysclk_constraints; };
+static int wm8988_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8988_RESET: + return 1; + default: + return 0; + } +}
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
@@ -663,6 +673,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute) static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
switch (level) { @@ -676,6 +687,12 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY: if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { + ret = snd_soc_cache_sync(codec); + if (ret < 0) { + dev_err(codec->dev, "Failed to sync cache: %d\n", ret); + return ret; + } + /* VREF, VMID=2x5k */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -736,21 +753,7 @@ static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8988_resume(struct snd_soc_codec *codec) { - int i; - u8 data[2]; - u16 *cache = codec->reg_cache; - - /* Sync reg_cache with the hardware */ - for (i = 0; i < WM8988_NUM_REG; i++) { - if (i == WM8988_RESET) - continue; - data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - return 0; }
@@ -805,6 +808,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = { .reg_cache_size = ARRAY_SIZE(wm8988_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8988_reg, + .volatile_register = wm8988_volatile_register, };
#if defined(CONFIG_SPI_MASTER)
Sorry. I just found we need to set codec->cache_sync = 1 in SND_SOC_BIAS_OFF. Otherwise, snd_soc_cache_sync won't sync work.
Will send a v2 soon.
Axel
於 四,2011-10-06 於 14:10 +0800,Axel Lin 提到:
This serial converts the wm8xxx codec drivers to use snd_soc_cache_sync. I don't have these hardware, but I assume Mark has all these hardware. These patches are UNTESTED. I'd appreciate if someone can test them. (Current code is broken anyway, thus we need convert to use new API. )
Axel Lin (10): ASoC: wm8510: Convert to snd_soc_cache_sync ASoC: wm8711: Convert to snd_soc_cache_sync ASoC: wm8731: Convert to snd_soc_cache_sync ASoC: wm8750: Convert to snd_soc_cache_sync ASoC: wm8776: Convert to snd_soc_cache_sync ASoC: wm8940: Convert to snd_soc_cache_sync ASoC: wm8960: Convert to snd_soc_cache_sync ASoC: wm8971: Convert to snd_soc_cache_sync ASoC: wm8974: Convert to snd_soc_cache_sync ASoC: wm8988: Convert to snd_soc_cache_sync
sound/soc/codecs/wm8510.c | 30 ++++++++++++++++++---------- sound/soc/codecs/wm8711.c | 19 +++++++---------- sound/soc/codecs/wm8731.c | 29 ++++++++++++++++----------- sound/soc/codecs/wm8750.c | 32 +++++++++++++++++------------- sound/soc/codecs/wm8776.c | 33 ++++++++++++++++++------------- sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- sound/soc/codecs/wm8960.c | 37 +++++++++++++++++++++++++---------- sound/soc/codecs/wm8971.c | 32 +++++++++++++++++++----------- sound/soc/codecs/wm8974.c | 29 +++++++++++++++++---------- sound/soc/codecs/wm8988.c | 32 +++++++++++++++++------------- 10 files changed, 185 insertions(+), 134 deletions(-)
於 四,2011-10-06 於 14:52 +0800,Axel Lin 提到:
Sorry. I just found we need to set codec->cache_sync = 1 in SND_SOC_BIAS_OFF. Otherwise, snd_soc_cache_sync won't sync work.
Will send a v2 soon.
I take it back. sorry again. After commit 7be4ba24 "ASoC: Mark cache as dirty when suspending", The soc-core will set codec->cache_sync flag now.
Regards, Axel
On Thu, Oct 06, 2011 at 02:10:17PM +0800, Axel Lin wrote:
This serial converts the wm8xxx codec drivers to use snd_soc_cache_sync. I don't have these hardware, but I assume Mark has all these hardware. These patches are UNTESTED. I'd appreciate if someone can test them. (Current code is broken anyway, thus we need convert to use new API. )
Axel, when submitting patches please don't fish e-mail addresses out of the code - use the git logs to find out who's working on the driver. This seems to be a fairly big source of bouncing e-mails in your CC lists.
Axel Lin (10): ASoC: wm8510: Convert to snd_soc_cache_sync ASoC: wm8711: Convert to snd_soc_cache_sync ASoC: wm8731: Convert to snd_soc_cache_sync ASoC: wm8750: Convert to snd_soc_cache_sync ASoC: wm8776: Convert to snd_soc_cache_sync ASoC: wm8940: Convert to snd_soc_cache_sync ASoC: wm8960: Convert to snd_soc_cache_sync ASoC: wm8971: Convert to snd_soc_cache_sync ASoC: wm8974: Convert to snd_soc_cache_sync ASoC: wm8988: Convert to snd_soc_cache_sync
sound/soc/codecs/wm8510.c | 30 ++++++++++++++++++---------- sound/soc/codecs/wm8711.c | 19 +++++++---------- sound/soc/codecs/wm8731.c | 29 ++++++++++++++++----------- sound/soc/codecs/wm8750.c | 32 +++++++++++++++++------------- sound/soc/codecs/wm8776.c | 33 ++++++++++++++++++------------- sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- sound/soc/codecs/wm8960.c | 37 +++++++++++++++++++++++++---------- sound/soc/codecs/wm8971.c | 32 +++++++++++++++++++----------- sound/soc/codecs/wm8974.c | 29 +++++++++++++++++---------- sound/soc/codecs/wm8988.c | 32 +++++++++++++++++------------- 10 files changed, 185 insertions(+), 134 deletions(-)
-- 1.7.4.1
participants (3)
-
Axel Lin
-
Jonathan Cameron
-
Mark Brown