ASoC: Use regmap update bits operation for drivers using regmap
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 3 Dec 2011 12:33:55 +0000 (12:33 +0000)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Sat, 21 Jan 2012 21:15:38 +0000 (21:15 +0000)
If a driver is using regmap directly ensure that we're coherent with
non-ASoC register updates by using the regmap API directly to do our
read/modify/write cycles. This will bypass the ASoC cache but drivers
using regmap directly should not be using the ASoC cache.

Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
include/sound/soc.h
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/soc/soc-io.c

index 55381fca6e0d5cfd35dc5c746accc63927d0bbce..2f687edd4fde4eab517ab27bbc8191d030853a10 100644 (file)
@@ -560,6 +560,7 @@ struct snd_soc_codec {
        unsigned int ac97_created:1; /* Codec has been created by SoC */
        unsigned int sysfs_registered:1; /* codec has been sysfs registered */
        unsigned int cache_init:1; /* codec cache has been initialized */
+       unsigned int using_regmap:1; /* using regmap access */
        u32 cache_only;  /* Suppress writes to hardware */
        u32 cache_sync; /* Cache needs to be synced to hardware */
 
index 41c8e45a23e2ec0b143e581b758e15aaefc11537..35a1e639d7f93030763d05771475484e9722fd2d 100644 (file)
@@ -1869,23 +1869,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
 int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
                                unsigned int mask, unsigned int value)
 {
-       int change;
+       bool change;
        unsigned int old, new;
        int ret;
 
-       ret = snd_soc_read(codec, reg);
-       if (ret < 0)
-               return ret;
-
-       old = ret;
-       new = (old & ~mask) | (value & mask);
-       change = old != new;
-       if (change) {
-               ret = snd_soc_write(codec, reg, new);
+       if (codec->using_regmap) {
+               ret = regmap_update_bits_check(codec->control_data, reg,
+                                              mask, value, &change);
+       } else {
+               ret = snd_soc_read(codec, reg);
                if (ret < 0)
                        return ret;
+
+               old = ret;
+               new = (old & ~mask) | (value & mask);
+               change = old != new;
+               if (change)
+                       ret = snd_soc_write(codec, reg, new);
        }
 
+       if (ret < 0)
+               return ret;
+
        return change;
 }
 EXPORT_SYMBOL_GPL(snd_soc_update_bits);
index 1f55ded4047f03b9a538af971c01018f0fb5df10..31a06b2b444255989341c2f4a5cc0360bcc21510 100644 (file)
@@ -197,21 +197,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
 static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
        unsigned short reg, unsigned int mask, unsigned int value)
 {
-       int change;
+       bool change;
        unsigned int old, new;
        int ret;
 
-       ret = soc_widget_read(w, reg);
-       if (ret < 0)
-               return ret;
-
-       old = ret;
-       new = (old & ~mask) | (value & mask);
-       change = old != new;
-       if (change) {
-               ret = soc_widget_write(w, reg, new);
+       if (w->codec && w->codec->using_regmap) {
+               ret = regmap_update_bits_check(w->codec->control_data,
+                                              reg, mask, value, &change);
+               if (ret != 0)
+                       return ret;
+       } else {
+               ret = soc_widget_read(w, reg);
                if (ret < 0)
                        return ret;
+
+               old = ret;
+               new = (old & ~mask) | (value & mask);
+               change = old != new;
+               if (change) {
+                       ret = soc_widget_write(w, reg, new);
+                       if (ret < 0)
+                               return ret;
+               }
        }
 
        return change;
index c8610cbf34a51cf9f2e856cc847a730f64a1d016..39ba5070ff92609d45f2e5223221d2b040ecc027 100644 (file)
@@ -140,6 +140,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
 
        case SND_SOC_REGMAP:
                /* Device has made its own regmap arrangements */
+               codec->using_regmap = true;
                break;
 
        default: