aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8993.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-03 12:55:55 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-02-04 05:41:54 -0500
commitcf56f62746c3e2f70bfad3d6fd051427a0022368 (patch)
tree5bd6c2fb2d7112d180892caec28e1835253e5334 /sound/soc/codecs/wm8993.c
parentb37e399bfc7fcb5b523e3e2e74686c8cc95c0cba (diff)
ASoC: Disable WM8993 regulators when turning bias off
While the regulators are disabled we cache all register writes. Currently we assume that the regulator disable actually takes effect, after the merge with the regulator tree in 2.6.34 the regulator API will be able to notify us if the power is actually removed (due to constraints or regulator sharing it may not be). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/codecs/wm8993.c')
-rw-r--r--sound/soc/codecs/wm8993.c54
1 files changed, 45 insertions, 9 deletions
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index e97b3f45b24b..bf022f68b84f 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -923,10 +923,33 @@ static const struct snd_soc_dapm_route routes[] = {
923 { "Right Headphone Mux", "DAC", "DACR" }, 923 { "Right Headphone Mux", "DAC", "DACR" },
924}; 924};
925 925
926static void wm8993_cache_restore(struct snd_soc_codec *codec)
927{
928 u16 *cache = codec->reg_cache;
929 int i;
930
931 if (!codec->cache_sync)
932 return;
933
934 /* Reenable hardware writes */
935 codec->cache_only = 0;
936
937 /* Restore the register settings */
938 for (i = 1; i < WM8993_MAX_REGISTER; i++) {
939 if (cache[i] == wm8993_reg_defaults[i])
940 continue;
941 snd_soc_write(codec, i, cache[i]);
942 }
943
944 /* We're in sync again */
945 codec->cache_sync = 0;
946}
947
926static int wm8993_set_bias_level(struct snd_soc_codec *codec, 948static int wm8993_set_bias_level(struct snd_soc_codec *codec,
927 enum snd_soc_bias_level level) 949 enum snd_soc_bias_level level)
928{ 950{
929 struct wm8993_priv *wm8993 = codec->private_data; 951 struct wm8993_priv *wm8993 = codec->private_data;
952 int ret;
930 953
931 switch (level) { 954 switch (level) {
932 case SND_SOC_BIAS_ON: 955 case SND_SOC_BIAS_ON:
@@ -940,6 +963,13 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
940 963
941 case SND_SOC_BIAS_STANDBY: 964 case SND_SOC_BIAS_STANDBY:
942 if (codec->bias_level == SND_SOC_BIAS_OFF) { 965 if (codec->bias_level == SND_SOC_BIAS_OFF) {
966 ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
967 wm8993->supplies);
968 if (ret != 0)
969 return ret;
970
971 wm8993_cache_restore(codec);
972
943 /* Tune DC servo configuration */ 973 /* Tune DC servo configuration */
944 snd_soc_write(codec, 0x44, 3); 974 snd_soc_write(codec, 0x44, 3);
945 snd_soc_write(codec, 0x56, 3); 975 snd_soc_write(codec, 0x56, 3);
@@ -992,6 +1022,18 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
992 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1, 1022 snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_1,
993 WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA, 1023 WM8993_VMID_SEL_MASK | WM8993_BIAS_ENA,
994 0); 1024 0);
1025
1026#ifdef CONFIG_REGULATOR
1027 /* Post 2.6.34 we will be able to get a callback when
1028 * the regulators are disabled which we can use but
1029 * for now just assume that the power will be cut if
1030 * the regulator API is in use.
1031 */
1032 codec->cache_sync = 1;
1033#endif
1034
1035 regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
1036 wm8993->supplies);
995 break; 1037 break;
996 } 1038 }
997 1039
@@ -1460,15 +1502,7 @@ static int wm8993_resume(struct platform_device *pdev)
1460 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1502 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1461 struct snd_soc_codec *codec = socdev->card->codec; 1503 struct snd_soc_codec *codec = socdev->card->codec;
1462 struct wm8993_priv *wm8993 = codec->private_data; 1504 struct wm8993_priv *wm8993 = codec->private_data;
1463 u16 *cache = wm8993->reg_cache; 1505 int ret;
1464 int i, ret;
1465
1466 /* Restore the register settings */
1467 for (i = 1; i < WM8993_MAX_REGISTER; i++) {
1468 if (cache[i] == wm8993_reg_defaults[i])
1469 continue;
1470 snd_soc_write(codec, i, cache[i]);
1471 }
1472 1506
1473 wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1507 wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1474 1508
@@ -1584,6 +1618,8 @@ static int wm8993_i2c_probe(struct i2c_client *i2c,
1584 if (ret != 0) 1618 if (ret != 0)
1585 goto err_enable; 1619 goto err_enable;
1586 1620
1621 codec->cache_only = 1;
1622
1587 /* By default we're using the output mixers */ 1623 /* By default we're using the output mixers */
1588 wm8993->class_w_users = 2; 1624 wm8993->class_w_users = 2;
1589 1625