aboutsummaryrefslogtreecommitdiff
path: root/sound/soc/codecs/wm8731.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r--sound/soc/codecs/wm8731.c97
1 files changed, 50 insertions, 47 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d3fd4f28d96..5a2619dbf28 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -33,9 +34,18 @@
static struct snd_soc_codec *wm8731_codec;
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 */
struct wm8731_priv {
struct snd_soc_codec codec;
+ struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
u16 reg_cache[WM8731_CACHEREGNUM];
unsigned int sysclk;
};
@@ -149,7 +159,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
- snd_soc_dapm_new_widgets(codec);
return 0;
}
@@ -422,9 +431,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_codec *codec = socdev->card->codec;
+ struct wm8731_priv *wm8731 = codec->private_data;
snd_soc_write(codec, WM8731_ACTIVE, 0x0);
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
+ wm8731->supplies);
return 0;
}
@@ -432,18 +444,28 @@ static int wm8731_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->card->codec;
- int i;
+ struct wm8731_priv *wm8731 = codec->private_data;
+ int i, ret;
u8 data[2];
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 */
for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
+ if (cache[i] == wm8731_reg[i])
+ continue;
+
data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
data[1] = cache[i] & 0x00ff;
codec->hw_write(codec->control_data, data, 2);
}
wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8731_set_bias_level(codec, codec->suspend_bias_level);
+
return 0;
}
#else
@@ -475,17 +497,9 @@ static int wm8731_probe(struct platform_device *pdev)
snd_soc_add_controls(codec, wm8731_snd_controls,
ARRAY_SIZE(wm8731_snd_controls));
wm8731_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
- if (ret < 0) {
- dev_err(codec->dev, "failed to register card: %d\n", ret);
- goto card_err;
- }
return ret;
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
pcm_err:
return ret;
}
@@ -512,7 +526,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
static int wm8731_register(struct wm8731_priv *wm8731,
enum snd_soc_control_type control)
{
- int ret;
+ int ret, i;
struct snd_soc_codec *codec = &wm8731->codec;
if (wm8731_codec) {
@@ -543,10 +557,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
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);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
- goto err;
+ goto err_regulator_enable;
}
wm8731_dai.dev = codec->dev;
@@ -567,7 +598,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
ret = snd_soc_register_codec(codec);
if (ret != 0) {
dev_err(codec->dev, "Failed to register codec: %d\n", ret);
- goto err;
+ goto err_regulator_enable;
}
ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +612,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
err_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:
kfree(wm8731);
return ret;
@@ -591,6 +626,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
snd_soc_unregister_dai(&wm8731_dai);
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);
wm8731_codec = NULL;
}
@@ -623,21 +660,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
return 0;
}
-#ifdef CONFIG_PM
-static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
-{
- return snd_soc_suspend_device(&spi->dev);
-}
-
-static int wm8731_spi_resume(struct spi_device *spi)
-{
- return snd_soc_resume_device(&spi->dev);
-}
-#else
-#define wm8731_spi_suspend NULL
-#define wm8731_spi_resume NULL
-#endif
-
static struct spi_driver wm8731_spi_driver = {
.driver = {
.name = "wm8731",
@@ -645,8 +667,6 @@ static struct spi_driver wm8731_spi_driver = {
.owner = THIS_MODULE,
},
.probe = wm8731_spi_probe,
- .suspend = wm8731_spi_suspend,
- .resume = wm8731_spi_resume,
.remove = __devexit_p(wm8731_spi_remove),
};
#endif /* CONFIG_SPI_MASTER */
@@ -679,21 +699,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
return 0;
}
-#ifdef CONFIG_PM
-static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
-{
- return snd_soc_suspend_device(&i2c->dev);
-}
-
-static int wm8731_i2c_resume(struct i2c_client *i2c)
-{
- return snd_soc_resume_device(&i2c->dev);
-}
-#else
-#define wm8731_i2c_suspend NULL
-#define wm8731_i2c_resume NULL
-#endif
-
static const struct i2c_device_id wm8731_i2c_id[] = {
{ "wm8731", 0 },
{ }
@@ -707,8 +712,6 @@ static struct i2c_driver wm8731_i2c_driver = {
},
.probe = wm8731_i2c_probe,
.remove = __devexit_p(wm8731_i2c_remove),
- .suspend = wm8731_i2c_suspend,
- .resume = wm8731_i2c_resume,
.id_table = wm8731_i2c_id,
};
#endif