aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8731.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-10-26 11:20:17 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-10-26 11:37:37 -0400
commit7dea7c01dac9b74faa9afa93fc9bb5f2d37521dc (patch)
tree33042b2c48bc0186695b46f9acbda53e965b8d68 /sound/soc/codecs/wm8731.c
parent7a1fecf57f435e50ed86851cbb701f4b28e65135 (diff)
ASoC: Add regulator support for WM8731
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r--sound/soc/codecs/wm8731.c51
1 files changed, 47 insertions, 4 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 0e59219a59f4..bb95af950971 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/regulator/consumer.h>
22#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -33,9 +34,18 @@
33static struct snd_soc_codec *wm8731_codec; 34static struct snd_soc_codec *wm8731_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8731; 35struct snd_soc_codec_device soc_codec_dev_wm8731;
35 36
37#define WM8731_NUM_SUPPLIES 4
38static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
39 "AVDD",
40 "HPVDD",
41 "DCVDD",
42 "DBVDD",
43};
44
36/* codec private data */ 45/* codec private data */
37struct wm8731_priv { 46struct wm8731_priv {
38 struct snd_soc_codec codec; 47 struct snd_soc_codec codec;
48 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
39 u16 reg_cache[WM8731_CACHEREGNUM]; 49 u16 reg_cache[WM8731_CACHEREGNUM];
40 unsigned int sysclk; 50 unsigned int sysclk;
41}; 51};
@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
422{ 432{
423 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 433 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
424 struct snd_soc_codec *codec = socdev->card->codec; 434 struct snd_soc_codec *codec = socdev->card->codec;
435 struct wm8731_priv *wm8731 = codec->private_data;
425 436
426 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 437 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 438 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
439 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
440 wm8731->supplies);
428 return 0; 441 return 0;
429} 442}
430 443
@@ -432,10 +445,16 @@ static int wm8731_resume(struct platform_device *pdev)
432{ 445{
433 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 446 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
434 struct snd_soc_codec *codec = socdev->card->codec; 447 struct snd_soc_codec *codec = socdev->card->codec;
435 int i; 448 struct wm8731_priv *wm8731 = codec->private_data;
449 int i, ret;
436 u8 data[2]; 450 u8 data[2];
437 u16 *cache = codec->reg_cache; 451 u16 *cache = codec->reg_cache;
438 452
453 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
454 wm8731->supplies);
455 if (ret != 0)
456 return ret;
457
439 /* Sync reg_cache with the hardware */ 458 /* Sync reg_cache with the hardware */
440 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { 459 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
441 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 460 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
@@ -444,6 +463,7 @@ static int wm8731_resume(struct platform_device *pdev)
444 } 463 }
445 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 464 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
446 wm8731_set_bias_level(codec, codec->suspend_bias_level); 465 wm8731_set_bias_level(codec, codec->suspend_bias_level);
466
447 return 0; 467 return 0;
448} 468}
449#else 469#else
@@ -512,7 +532,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
512static int wm8731_register(struct wm8731_priv *wm8731, 532static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control) 533 enum snd_soc_control_type control)
514{ 534{
515 int ret; 535 int ret, i;
516 struct snd_soc_codec *codec = &wm8731->codec; 536 struct snd_soc_codec *codec = &wm8731->codec;
517 537
518 if (wm8731_codec) { 538 if (wm8731_codec) {
@@ -543,10 +563,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
543 goto err; 563 goto err;
544 } 564 }
545 565
566 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
567 wm8731->supplies[i].supply = wm8731_supply_names[i];
568
569 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
570 wm8731->supplies);
571 if (ret != 0) {
572 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
573 goto err;
574 }
575
576 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
577 wm8731->supplies);
578 if (ret != 0) {
579 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
580 goto err_regulator_get;
581 }
582
546 ret = wm8731_reset(codec); 583 ret = wm8731_reset(codec);
547 if (ret < 0) { 584 if (ret < 0) {
548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 585 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
549 goto err; 586 goto err_regulator_enable;
550 } 587 }
551 588
552 wm8731_dai.dev = codec->dev; 589 wm8731_dai.dev = codec->dev;
@@ -567,7 +604,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
567 ret = snd_soc_register_codec(codec); 604 ret = snd_soc_register_codec(codec);
568 if (ret != 0) { 605 if (ret != 0) {
569 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 606 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
570 goto err; 607 goto err_regulator_enable;
571 } 608 }
572 609
573 ret = snd_soc_register_dai(&wm8731_dai); 610 ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +618,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
581 618
582err_codec: 619err_codec:
583 snd_soc_unregister_codec(codec); 620 snd_soc_unregister_codec(codec);
621err_regulator_enable:
622 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
623err_regulator_get:
624 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
584err: 625err:
585 kfree(wm8731); 626 kfree(wm8731);
586 return ret; 627 return ret;
@@ -591,6 +632,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
591 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 632 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
592 snd_soc_unregister_dai(&wm8731_dai); 633 snd_soc_unregister_dai(&wm8731_dai);
593 snd_soc_unregister_codec(&wm8731->codec); 634 snd_soc_unregister_codec(&wm8731->codec);
635 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
636 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
594 kfree(wm8731); 637 kfree(wm8731);
595 wm8731_codec = NULL; 638 wm8731_codec = NULL;
596} 639}