diff options
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 97 |
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 |