diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-26 11:20:17 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-10-26 11:37:37 -0400 |
commit | 7dea7c01dac9b74faa9afa93fc9bb5f2d37521dc (patch) | |
tree | 33042b2c48bc0186695b46f9acbda53e965b8d68 /sound/soc/codecs/wm8731.c | |
parent | 7a1fecf57f435e50ed86851cbb701f4b28e65135 (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.c | 51 |
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 @@ | |||
33 | static struct snd_soc_codec *wm8731_codec; | 34 | static struct snd_soc_codec *wm8731_codec; |
34 | struct snd_soc_codec_device soc_codec_dev_wm8731; | 35 | struct snd_soc_codec_device soc_codec_dev_wm8731; |
35 | 36 | ||
37 | #define WM8731_NUM_SUPPLIES 4 | ||
38 | static 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 */ |
37 | struct wm8731_priv { | 46 | struct 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); | |||
512 | static int wm8731_register(struct wm8731_priv *wm8731, | 532 | static 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 | ||
582 | err_codec: | 619 | err_codec: |
583 | snd_soc_unregister_codec(codec); | 620 | snd_soc_unregister_codec(codec); |
621 | err_regulator_enable: | ||
622 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
623 | err_regulator_get: | ||
624 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
584 | err: | 625 | err: |
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 | } |