return 0;
 }
 
+static void wm8904_sync_cache(struct snd_soc_codec *codec)
+{
+       struct wm8904_priv *wm8904 = codec->private_data;
+       int i;
+
+       if (!codec->cache_sync)
+               return;
+
+       codec->cache_only = 0;
+
+       /* Sync back cached values if they're different from the
+        * hardware default.
+        */
+       for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) {
+               if (!wm8904_access[i].writable)
+                       continue;
+
+               if (wm8904->reg_cache[i] == wm8904_reg[i])
+                       continue;
+
+               snd_soc_write(codec, i, wm8904->reg_cache[i]);
+       }
+
+       codec->cache_sync = 0;
+}
+
 static int wm8904_set_bias_level(struct snd_soc_codec *codec,
                                 enum snd_soc_bias_level level)
 {
        struct wm8904_priv *wm8904 = codec->private_data;
-       int ret, i;
+       int ret;
 
        switch (level) {
        case SND_SOC_BIAS_ON:
                                return ret;
                        }
 
-                       /* Sync back cached values if they're
-                        * different from the hardware default.
-                        */
-                       for (i = 1; i < ARRAY_SIZE(wm8904->reg_cache); i++) {
-                               if (!wm8904_access[i].writable)
-                                       continue;
-
-                               if (wm8904->reg_cache[i] == wm8904_reg[i])
-                                       continue;
-
-                               snd_soc_write(codec, i, wm8904->reg_cache[i]);
-                       }
+                       wm8904_sync_cache(codec);
 
                        /* Enable bias */
                        snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
                snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
                                    WM8904_BIAS_ENA, 0);
 
+#ifdef CONFIG_REGULATOR
+               /* Post 2.6.34 we will be able to get a callback when
+                * the regulators are disabled which we can use but
+                * for now just assume that the power will be cut if
+                * the regulator API is in use.
+                */
+               codec->cache_sync = 1;
+#endif
+
                regulator_bulk_disable(ARRAY_SIZE(wm8904->supplies),
                                       wm8904->supplies);
                break;
        codec->reg_cache_size = WM8904_MAX_REGISTER;
        codec->reg_cache = &wm8904->reg_cache;
        codec->volatile_register = wm8904_volatile_register;
+       codec->cache_sync = 1;
+       codec->idle_bias_off = 1;
 
        memcpy(codec->reg_cache, wm8904_reg, sizeof(wm8904_reg));