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>
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 41c8e45..35a1e63 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1869,23 +1869,28 @@
 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 1f55ded..31a06b2 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -197,21 +197,28 @@
 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 c8610cb..39ba507 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -140,6 +140,7 @@
 
 	case SND_SOC_REGMAP:
 		/* Device has made its own regmap arrangements */
+		codec->using_regmap = true;
 		break;
 
 	default: