diff options
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 86c4b24db817..97b9ed95d289 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/consumer.h> | ||
28 | |||
27 | #include <sound/core.h> | 29 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
29 | #include <sound/pcm_params.h> | 31 | #include <sound/pcm_params.h> |
@@ -187,15 +189,22 @@ struct pll_state { | |||
187 | unsigned int out; | 189 | unsigned int out; |
188 | }; | 190 | }; |
189 | 191 | ||
192 | #define WM8580_NUM_SUPPLIES 3 | ||
193 | static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | ||
194 | "AVDD", | ||
195 | "DVDD", | ||
196 | "PVDD", | ||
197 | }; | ||
198 | |||
190 | /* codec private data */ | 199 | /* codec private data */ |
191 | struct wm8580_priv { | 200 | struct wm8580_priv { |
192 | struct snd_soc_codec codec; | 201 | struct snd_soc_codec codec; |
202 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | ||
193 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; | 203 | u16 reg_cache[WM8580_MAX_REGISTER + 1]; |
194 | struct pll_state a; | 204 | struct pll_state a; |
195 | struct pll_state b; | 205 | struct pll_state b; |
196 | }; | 206 | }; |
197 | 207 | ||
198 | |||
199 | /* | 208 | /* |
200 | * read wm8580 register cache | 209 | * read wm8580 register cache |
201 | */ | 210 | */ |
@@ -922,11 +931,28 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
922 | 931 | ||
923 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); | 932 | memcpy(codec->reg_cache, wm8580_reg, sizeof(wm8580_reg)); |
924 | 933 | ||
934 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
935 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
936 | |||
937 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), | ||
938 | wm8580->supplies); | ||
939 | if (ret != 0) { | ||
940 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
941 | goto err; | ||
942 | } | ||
943 | |||
944 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | ||
945 | wm8580->supplies); | ||
946 | if (ret != 0) { | ||
947 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
948 | goto err_regulator_get; | ||
949 | } | ||
950 | |||
925 | /* Get the codec into a known state */ | 951 | /* Get the codec into a known state */ |
926 | ret = wm8580_write(codec, WM8580_RESET, 0); | 952 | ret = wm8580_write(codec, WM8580_RESET, 0); |
927 | if (ret != 0) { | 953 | if (ret != 0) { |
928 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); | 954 | dev_err(codec->dev, "Failed to reset codec: %d\n", ret); |
929 | goto err; | 955 | goto err_regulator_enable; |
930 | } | 956 | } |
931 | 957 | ||
932 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) | 958 | for (i = 0; i < ARRAY_SIZE(wm8580_dai); i++) |
@@ -939,7 +965,7 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
939 | ret = snd_soc_register_codec(codec); | 965 | ret = snd_soc_register_codec(codec); |
940 | if (ret != 0) { | 966 | if (ret != 0) { |
941 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 967 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); |
942 | goto err; | 968 | goto err_regulator_enable; |
943 | } | 969 | } |
944 | 970 | ||
945 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 971 | ret = snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); |
@@ -952,6 +978,10 @@ static int wm8580_register(struct wm8580_priv *wm8580) | |||
952 | 978 | ||
953 | err_codec: | 979 | err_codec: |
954 | snd_soc_unregister_codec(codec); | 980 | snd_soc_unregister_codec(codec); |
981 | err_regulator_enable: | ||
982 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
983 | err_regulator_get: | ||
984 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
955 | err: | 985 | err: |
956 | kfree(wm8580); | 986 | kfree(wm8580); |
957 | return ret; | 987 | return ret; |
@@ -962,6 +992,8 @@ static void wm8580_unregister(struct wm8580_priv *wm8580) | |||
962 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); | 992 | wm8580_set_bias_level(&wm8580->codec, SND_SOC_BIAS_OFF); |
963 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 993 | snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai)); |
964 | snd_soc_unregister_codec(&wm8580->codec); | 994 | snd_soc_unregister_codec(&wm8580->codec); |
995 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
996 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
965 | kfree(wm8580); | 997 | kfree(wm8580); |
966 | wm8580_codec = NULL; | 998 | wm8580_codec = NULL; |
967 | } | 999 | } |
@@ -995,6 +1027,21 @@ static int wm8580_i2c_remove(struct i2c_client *client) | |||
995 | return 0; | 1027 | return 0; |
996 | } | 1028 | } |
997 | 1029 | ||
1030 | #ifdef CONFIG_PM | ||
1031 | static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg) | ||
1032 | { | ||
1033 | return snd_soc_suspend_device(&client->dev); | ||
1034 | } | ||
1035 | |||
1036 | static int wm8580_i2c_resume(struct i2c_client *client) | ||
1037 | { | ||
1038 | return snd_soc_resume_device(&client->dev); | ||
1039 | } | ||
1040 | #else | ||
1041 | #define wm8580_i2c_suspend NULL | ||
1042 | #define wm8580_i2c_resume NULL | ||
1043 | #endif | ||
1044 | |||
998 | static const struct i2c_device_id wm8580_i2c_id[] = { | 1045 | static const struct i2c_device_id wm8580_i2c_id[] = { |
999 | { "wm8580", 0 }, | 1046 | { "wm8580", 0 }, |
1000 | { } | 1047 | { } |
@@ -1008,6 +1055,8 @@ static struct i2c_driver wm8580_i2c_driver = { | |||
1008 | }, | 1055 | }, |
1009 | .probe = wm8580_i2c_probe, | 1056 | .probe = wm8580_i2c_probe, |
1010 | .remove = wm8580_i2c_remove, | 1057 | .remove = wm8580_i2c_remove, |
1058 | .suspend = wm8580_i2c_suspend, | ||
1059 | .resume = wm8580_i2c_resume, | ||
1011 | .id_table = wm8580_i2c_id, | 1060 | .id_table = wm8580_i2c_id, |
1012 | }; | 1061 | }; |
1013 | #endif | 1062 | #endif |