summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-01 19:46:10 +0100
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-03 19:03:37 +0100
commit8c961bcca1d10be4f2c06375eb561679167653a0 (patch)
tree568e0371807f25bf09d5948db1b798eb1ec49e01
parentASoC: fix compilation breakage in sound/soc/sh/fsi.c (diff)
downloadlinux-8c961bcca1d10be4f2c06375eb561679167653a0.tar.xz
linux-8c961bcca1d10be4f2c06375eb561679167653a0.zip
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>
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-cache.c26
2 files changed, 25 insertions, 2 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 4bbeb9f83ece..4e8f14bc8ed3 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 097e33510a7a..84b6916db87d 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;