ASoC: Allow CODECs to ask soc-cache to suppress physical writes
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 1 Feb 2010 18:46:10 +0000 (18:46 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Wed, 3 Feb 2010 18:03:37 +0000 (18:03 +0000)
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
sound/soc/soc-cache.c

index 4bbeb9f83ece42fec88e7c48cae0a9caf57223d7..4e8f14bc8ed3011eaa6020c11978b1a54b9142c3 100644 (file)
@@ -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;
index 097e33510a7a0120e3b6cc4474a75ac0a5e72766..84b6916db87d4c090c1d78a2c6a60e9156eb3d49 100644 (file)
@@ -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;