Commit 7dea7c01 authored by Mark Brown's avatar Mark Brown

ASoC: Add regulator support for WM8731

Signed-off-by: default avatarMark Brown <broonie@opensource.wolfsonmicro.com>
parent 7a1fecf5
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <sound/core.h> #include <sound/core.h>
#include <sound/pcm.h> #include <sound/pcm.h>
...@@ -33,9 +34,18 @@ ...@@ -33,9 +34,18 @@
static struct snd_soc_codec *wm8731_codec; static struct snd_soc_codec *wm8731_codec;
struct snd_soc_codec_device soc_codec_dev_wm8731; struct snd_soc_codec_device soc_codec_dev_wm8731;
#define WM8731_NUM_SUPPLIES 4
static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
"AVDD",
"HPVDD",
"DCVDD",
"DBVDD",
};
/* codec private data */ /* codec private data */
struct wm8731_priv { struct wm8731_priv {
struct snd_soc_codec codec; struct snd_soc_codec codec;
struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
u16 reg_cache[WM8731_CACHEREGNUM]; u16 reg_cache[WM8731_CACHEREGNUM];
unsigned int sysclk; unsigned int sysclk;
}; };
...@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) ...@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
struct wm8731_priv *wm8731 = codec->private_data;
snd_soc_write(codec, WM8731_ACTIVE, 0x0); snd_soc_write(codec, WM8731_ACTIVE, 0x0);
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
return 0; return 0;
} }
...@@ -432,10 +445,16 @@ static int wm8731_resume(struct platform_device *pdev) ...@@ -432,10 +445,16 @@ static int wm8731_resume(struct platform_device *pdev)
{ {
struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec; struct snd_soc_codec *codec = socdev->card->codec;
int i; struct wm8731_priv *wm8731 = codec->private_data;
int i, ret;
u8 data[2]; u8 data[2];
u16 *cache = codec->reg_cache; u16 *cache = codec->reg_cache;
ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0)
return ret;
/* Sync reg_cache with the hardware */ /* Sync reg_cache with the hardware */
for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
...@@ -444,6 +463,7 @@ static int wm8731_resume(struct platform_device *pdev) ...@@ -444,6 +463,7 @@ static int wm8731_resume(struct platform_device *pdev)
} }
wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8731_set_bias_level(codec, codec->suspend_bias_level); wm8731_set_bias_level(codec, codec->suspend_bias_level);
return 0; return 0;
} }
#else #else
...@@ -512,7 +532,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); ...@@ -512,7 +532,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
static int wm8731_register(struct wm8731_priv *wm8731, static int wm8731_register(struct wm8731_priv *wm8731,
enum snd_soc_control_type control) enum snd_soc_control_type control)
{ {
int ret; int ret, i;
struct snd_soc_codec *codec = &wm8731->codec; struct snd_soc_codec *codec = &wm8731->codec;
if (wm8731_codec) { if (wm8731_codec) {
...@@ -543,10 +563,27 @@ static int wm8731_register(struct wm8731_priv *wm8731, ...@@ -543,10 +563,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
goto err; goto err;
} }
for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
wm8731->supplies[i].supply = wm8731_supply_names[i];
ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
goto err;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
if (ret != 0) {
dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
goto err_regulator_get;
}
ret = wm8731_reset(codec); ret = wm8731_reset(codec);
if (ret < 0) { if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret); dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
goto err; goto err_regulator_enable;
} }
wm8731_dai.dev = codec->dev; wm8731_dai.dev = codec->dev;
...@@ -567,7 +604,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, ...@@ -567,7 +604,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
ret = snd_soc_register_codec(codec); ret = snd_soc_register_codec(codec);
if (ret != 0) { if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret); dev_err(codec->dev, "Failed to register codec: %d\n", ret);
goto err; goto err_regulator_enable;
} }
ret = snd_soc_register_dai(&wm8731_dai); ret = snd_soc_register_dai(&wm8731_dai);
...@@ -581,6 +618,10 @@ static int wm8731_register(struct wm8731_priv *wm8731, ...@@ -581,6 +618,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
err_codec: err_codec:
snd_soc_unregister_codec(codec); snd_soc_unregister_codec(codec);
err_regulator_enable:
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
err_regulator_get:
regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
err: err:
kfree(wm8731); kfree(wm8731);
return ret; return ret;
...@@ -591,6 +632,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) ...@@ -591,6 +632,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
snd_soc_unregister_dai(&wm8731_dai); snd_soc_unregister_dai(&wm8731_dai);
snd_soc_unregister_codec(&wm8731->codec); snd_soc_unregister_codec(&wm8731->codec);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
kfree(wm8731); kfree(wm8731);
wm8731_codec = NULL; wm8731_codec = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment