[alsa-devel] [PATCH 1/2] ASoC: Allow CODECs to ask soc-cache to suppress physical writes
Currently the soc-cache code will always write to the device, meaning that we need the device to be powered and active at pretty much all times the system is active. Allowing cache only writes lays some groundwork for future enhancements to allow devices to be put into a full off state when the audio subsystem is idle.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com Acked-by: Liam Girdwood lrg@slimlogic.co.uk --- include/sound/soc.h | 1 + sound/soc/soc-cache.c | 26 ++++++++++++++++++++++++-- 2 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 4bbeb9f..4e8f14b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -423,6 +423,7 @@ struct snd_soc_codec { short reg_cache_step;
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ + unsigned int cache_only:1; /* Suppress writes to hardware */
/* dapm */ u32 pop_time; diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 097e335..84b6916 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -38,6 +38,10 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
if (reg < codec->reg_cache_size) cache[reg] = value; + + if (codec->cache_only) + return 0; + ret = codec->hw_write(codec->control_data, data, 2); if (ret == 2) return 0; @@ -100,6 +104,10 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
if (reg < codec->reg_cache_size) cache[reg] = value; + + if (codec->cache_only) + return 0; + ret = codec->hw_write(codec->control_data, data, 2); if (ret == 2) return 0; @@ -153,6 +161,9 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < codec->reg_cache_size) cache[reg] = value;
+ if (codec->cache_only) + return 0; + if (codec->hw_write(codec->control_data, data, 2) == 2) return 0; else @@ -181,6 +192,9 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, if (!snd_soc_codec_volatile_register(codec, reg)) reg_cache[reg] = value;
+ if (codec->cache_only) + return 0; + if (codec->hw_write(codec->control_data, data, 3) == 3) return 0; else @@ -193,10 +207,14 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, u16 *cache = codec->reg_cache;
if (reg >= codec->reg_cache_size || - snd_soc_codec_volatile_register(codec, reg)) + snd_soc_codec_volatile_register(codec, reg)) { + if (codec->cache_only) + return -EINVAL; + return codec->hw_read(codec, reg); - else + } else { return cache[reg]; + } }
#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE)) @@ -294,6 +312,10 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, reg &= 0xff; if (reg < codec->reg_cache_size) cache[reg] = value; + + if (codec->cache_only) + return 0; + ret = codec->hw_write(codec->control_data, data, 3); if (ret == 3) return 0;
Add a bit to the CODEC structure indicating if a cache sync is required. By default this will be set if a cache only write is done to a soc-cache register cache. This allows us to avoid syncing the cache back after using cache only writes if there were no changes.
Signed-off-by: Mark Brown broonie@opensource.wolfsonmicro.com Acked-by: Liam Girdwood lrg@slimlogic.co.uk
SQUASH CACHE SYNC --- include/sound/soc.h | 1 + sound/soc/soc-cache.c | 20 +++++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h index 4e8f14b..e6a6d10 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -424,6 +424,7 @@ struct snd_soc_codec {
unsigned int idle_bias_off:1; /* Use BIAS_OFF instead of STANDBY */ unsigned int cache_only:1; /* Suppress writes to hardware */ + unsigned int cache_sync:1; /* Cache needs to be synced to hardware */
/* dapm */ u32 pop_time; diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 84b6916..5869dc3 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c @@ -39,8 +39,10 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < codec->reg_cache_size) cache[reg] = value;
- if (codec->cache_only) + if (codec->cache_only) { + codec->cache_sync = 1; return 0; + }
ret = codec->hw_write(codec->control_data, data, 2); if (ret == 2) @@ -105,8 +107,10 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < codec->reg_cache_size) cache[reg] = value;
- if (codec->cache_only) + if (codec->cache_only) { + codec->cache_sync = 1; return 0; + }
ret = codec->hw_write(codec->control_data, data, 2); if (ret == 2) @@ -161,8 +165,10 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < codec->reg_cache_size) cache[reg] = value;
- if (codec->cache_only) + if (codec->cache_only) { + codec->cache_sync = 1; return 0; + }
if (codec->hw_write(codec->control_data, data, 2) == 2) return 0; @@ -192,8 +198,10 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, if (!snd_soc_codec_volatile_register(codec, reg)) reg_cache[reg] = value;
- if (codec->cache_only) + if (codec->cache_only) { + codec->cache_sync = 1; return 0; + }
if (codec->hw_write(codec->control_data, data, 3) == 3) return 0; @@ -313,8 +321,10 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, if (reg < codec->reg_cache_size) cache[reg] = value;
- if (codec->cache_only) + if (codec->cache_only) { + codec->cache_sync = 1; return 0; + }
ret = codec->hw_write(codec->control_data, data, 3); if (ret == 3)
participants (1)
-
Mark Brown