[alsa-devel] [PATCH 00/11 v2] Convert wm8xxx codec drivers to use snd_soc_write/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 it. (Current code is broken anyway, thus we need convert to use new API. )
v2: For 7, 9 CODECs that are write only, convert to using cache_bypass + snd_soc_write v2 also includes wm8990 that I had sent separately.
*** BLURB HERE ***
Axel Lin (11): ASoC: wm8510: Convert to snd_soc_write ASoC: wm8711: Convert to snd_soc_write ASoC: wm8731: Convert to snd_soc_write ASoC: wm8750: Convert to snd_soc_write ASoC: wm8776: Convert to snd_soc_write ASoC: wm8940: Convert to snd_soc_cache_sync ASoC: wm8960: Convert to snd_soc_write ASoC: wm8971: Convert to snd_soc_write ASoC: wm8974: Convert to snd_soc_write ASoC: wm8988: Convert to snd_soc_write ASoC: wm8990: Convert to snd_soc_cache_sync
sound/soc/codecs/wm8510.c | 33 +++++++++++++++++++++---------- sound/soc/codecs/wm8711.c | 33 +++++++++++++++++++++---------- sound/soc/codecs/wm8731.c | 35 +++++++++++++++++++++------------ sound/soc/codecs/wm8750.c | 36 +++++++++++++++++++++------------- sound/soc/codecs/wm8776.c | 36 +++++++++++++++++++++------------- sound/soc/codecs/wm8940.c | 46 +++++++++++++++++++++----------------------- sound/soc/codecs/wm8960.c | 34 +++++++++++++++++++++++--------- sound/soc/codecs/wm8971.c | 35 ++++++++++++++++++++++----------- sound/soc/codecs/wm8974.c | 33 +++++++++++++++++++++---------- sound/soc/codecs/wm8988.c | 37 +++++++++++++++++++++-------------- sound/soc/codecs/wm8990.c | 32 ++++++++++++++++++------------ 11 files changed, 242 insertions(+), 148 deletions(-)
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8510.c | 33 ++++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 55a4c83..fc8bc9c 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -463,6 +463,26 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8510_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 0; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8510_RESET || cache[i] == wm8510_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 1; + codec->cache_sync = 0; +} + /* liam need to make this lower power with dapm */ static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -480,6 +500,8 @@ 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) { + wm8510_sync_cache(codec); + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); @@ -541,18 +563,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; }
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- This resend fixes a copy-paste bug. cache_bypass flag should be set before snd_soc_write and be clear after the write.
Axel sound/soc/codecs/wm8510.c | 33 ++++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index 55a4c83..fc8bc9c 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c @@ -463,6 +463,26 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8510_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8510_RESET || cache[i] == wm8510_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + /* liam need to make this lower power with dapm */ static int wm8510_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -480,6 +500,8 @@ 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) { + wm8510_sync_cache(codec); + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8510_POWER1, power1 | 0x3); mdelay(100); @@ -541,18 +563,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; }
On Fri, Oct 07, 2011 at 10:40:20AM +0800, Axel Lin wrote:
+static void wm8510_sync_cache(struct snd_soc_codec *codec) +{
- short i;
- u16 *cache;
- if (!codec->cache_sync)
return;
- codec->cache_only = 0;
- codec->cache_bypass = 1;
- /* restore cache */
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
if (i == WM8510_RESET || cache[i] == wm8510_reg[i])
continue;
snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_bypass = 0;
- codec->cache_sync = 0;
The usual trick for avoiding this is to provide a register default value for the reset register and then write that value when the chip is reset. This then means that the write to the reset register is suppressed by the cache restore code when it skips writes of default registers.
Thanks for doing this work.
2011/10/7 Mark Brown broonie@opensource.wolfsonmicro.com:
On Fri, Oct 07, 2011 at 10:40:20AM +0800, Axel Lin wrote:
+static void wm8510_sync_cache(struct snd_soc_codec *codec) +{
- short i;
- u16 *cache;
- if (!codec->cache_sync)
- return;
- codec->cache_only = 0;
- codec->cache_bypass = 1;
- /* restore cache */
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8510_RESET || cache[i] == wm8510_reg[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_bypass = 0;
- codec->cache_sync = 0;
The usual trick for avoiding this is to provide a register default value for the reset register and then write that value when the chip is reset. This then means that the write to the reset register is suppressed by the cache restore code when it skips writes of default registers.
Nice trick. Then we can use snd_soc_cache_sync() to replace the customized xxxx_sync_cache() calls.
I'll send a v3 soon.
Thanks for doing this work.
And thanks for your valuable review.
Regards, Axel
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8711.c | 33 ++++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index 47c7fd5..f4c15ea 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c @@ -287,6 +287,25 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; }
+static void wm8711_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8711_RESET || cache[i] == wm8711_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +}
static int wm8711_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -300,6 +319,9 @@ 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) + wm8711_sync_cache(codec); + snd_soc_write(codec, WM8711_PWR, reg | 0x0040); break; case SND_SOC_BIAS_OFF: @@ -346,18 +368,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 codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8731.c | 35 ++++++++++++++++++++++------------- 1 files changed, 22 insertions(+), 13 deletions(-)
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index f76b6fc..853aed1 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c @@ -423,13 +423,31 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai, return 0; }
+static void wm8731_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8731_RESET || cache[i] == wm8731_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + 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,16 +462,7 @@ 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); - } + wm8731_sync_cache(codec); }
/* Clear PWROFF, gate CLKOUT, everything else as-is */
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8750.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 862c520..8b5a41b 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c @@ -602,6 +602,26 @@ static int wm8750_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8750_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8750_RESET || cache[i] == wm8750_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + static int wm8750_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -616,6 +636,8 @@ 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) { + wm8750_sync_cache(codec); + /* Set VMID to 5k */ snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
@@ -673,21 +695,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; }
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8776.c | 36 ++++++++++++++++++++++-------------- 1 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 00d8846..9d488e6 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c @@ -298,6 +298,26 @@ static int wm8776_set_sysclk(struct snd_soc_dai *dai, return 0; }
+static void wm8776_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8776_RESET || cache[i] == wm8776_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + static int wm8776_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -308,6 +328,8 @@ 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) { + wm8776_sync_cache(codec); + /* Disable the global powerdown; DAPM does the rest */ snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); } @@ -379,21 +401,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
Convert codec->hw_write to snd_soc_cache_sync
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)
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8960.c | 34 ++++++++++++++++++++++++---------- 1 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 831c20f..c043722 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -555,6 +555,26 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8960_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8960_RESET || cache[i] == wm8960_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -574,6 +594,8 @@ 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) { + wm8960_sync_cache(codec); + /* Enable anti-pop features */ snd_soc_write(codec, WM8960_APOP1, WM8960_POBCTRL | WM8960_SOFT_ST | @@ -629,6 +651,8 @@ 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: + wm8960_sync_cache(codec); + /* 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;
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8971.c | 35 +++++++++++++++++++++++------------ 1 files changed, 23 insertions(+), 12 deletions(-)
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 08ea6f8..2265e00 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c @@ -533,6 +533,26 @@ static int wm8971_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8971_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8971_RESET || cache[i] == wm8971_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + static int wm8971_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -546,6 +566,9 @@ 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) + wm8971_sync_cache(codec); + /* mute dac and set vmid to 500k, enable VREF */ snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140); break; @@ -605,20 +628,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 */
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8974.c | 33 ++++++++++++++++++++++----------- 1 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index ca646a8..7db3808 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -513,6 +513,26 @@ static int wm8974_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8974_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8974_RESET || cache[i] == wm8974_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + /* liam need to make this lower power with dapm */ static int wm8974_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) @@ -530,6 +550,8 @@ 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) { + wm8974_sync_cache(codec); + /* Initial cap charge at VMID 5k */ snd_soc_write(codec, WM8974_POWER1, power1 | 0x3); mdelay(100); @@ -589,18 +611,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; }
Convert codec->hw_write to snd_soc_write
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8988.c | 37 ++++++++++++++++++++++--------------- 1 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 1c6f8bf..33584e0 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c @@ -55,7 +55,6 @@ struct wm8988_priv { struct snd_pcm_hw_constraint_list *sysclk_constraints; };
- #define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
/* @@ -660,6 +659,26 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute) return 0; }
+static void wm8988_sync_cache(struct snd_soc_codec *codec) +{ + short i; + u16 *cache; + + if (!codec->cache_sync) + return; + codec->cache_only = 0; + codec->cache_bypass = 1; + /* restore cache */ + cache = codec->reg_cache; + for (i = 0; i < codec->driver->reg_cache_size; i++) { + if (i == WM8988_RESET || cache[i] == wm8988_reg[i]) + continue; + snd_soc_write(codec, i, cache[i]); + } + codec->cache_bypass = 0; + codec->cache_sync = 0; +} + static int wm8988_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { @@ -676,6 +695,8 @@ 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) { + wm8988_sync_cache(codec); + /* VREF, VMID=2x5k */ snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -736,21 +757,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; }
Convert codec->hw_write to snd_soc_cache_sync
Signed-off-by: Axel Lin axel.lin@gmail.com --- sound/soc/codecs/wm8990.c | 32 +++++++++++++++++++------------- 1 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 100aeee..48e9dd9 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c @@ -36,6 +36,17 @@ struct wm8990_priv { unsigned int pcmclk; };
+static int wm8990_volatile_register(struct snd_soc_codec *codec, + unsigned int reg) +{ + switch (reg) { + case WM8990_RESET: + return 1; + default: + return 0; + } +} + /* * wm8990 register cache. Note that register 0 is not included in the * cache. @@ -1156,6 +1167,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute) static int wm8990_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { + int ret; u16 val;
switch (level) { @@ -1171,6 +1183,12 @@ static int wm8990_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; + } + /* Enable all output discharge bits */ snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE | WM8990_DIS_RLINE | WM8990_DIS_OUT3 | @@ -1319,19 +1337,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8990_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(wm8990_reg); i++) { - if (i + 1 == WM8990_RESET) - continue; - data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001); - data[1] = cache[i] & 0x00ff; - codec->hw_write(codec->control_data, data, 2); - } - wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } @@ -1392,6 +1397,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = { .reg_cache_size = ARRAY_SIZE(wm8990_reg), .reg_word_size = sizeof(u16), .reg_cache_default = wm8990_reg, + .volatile_register = wm8990_volatile_register, };
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
On Fri, Oct 07, 2011 at 07:56:53AM +0800, Axel Lin wrote:
Convert codec->hw_write to snd_soc_cache_sync
This doesn't apply against current code, mostly due to a version of the patch already having been applied and a conflict with your subsequent patch updating the comments.
participants (2)
-
Axel Lin
-
Mark Brown