diff options
Diffstat (limited to 'sound/soc/codecs')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 38 |
1 files changed, 35 insertions, 3 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 261ef101d4fc..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 | } |