summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-03 12:33:55 +0000
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-21 21:15:38 +0000
commit8a713da8d1ce9ceaf738b32e2b24f22d4432f886 (patch)
treec0fb13d21f18ed19c82e4d9214d440e34b0c474b
parent278047fd654dde7ed95c8604fcefeeacc5c0bb2b (diff)
ASoC: Use regmap update bits operation for drivers using regmap
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>
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/soc-core.c25
-rw-r--r--sound/soc/soc-dapm.c27
-rw-r--r--sound/soc/soc-io.c1
4 files changed, 34 insertions, 20 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 55381fca6e0d..2f687edd4fde 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -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 */
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 41c8e45a23e2..35a1e639d7f9 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -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);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1f55ded4047f..31a06b2b4442 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -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;
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index c8610cbf34a5..39ba5070ff92 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -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: