diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 992a7f23df5c3d653cf41d0aceed627c26384655..dc782c43a7cba9b6923217015bf0c70992d946a9 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c @@ -2033,11 +2033,37 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute) 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: @@ -2065,18 +2091,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, 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, @@ -2112,6 +2127,15 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec, 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; @@ -2365,6 +2389,8 @@ static int wm8904_register(struct wm8904_priv *wm8904, 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));