aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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