aboutsummaryrefslogtreecommitdiffstats
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.c98
1 files changed, 51 insertions, 47 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d3fd4f28d96e..e7c6bf163185 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -18,7 +18,9 @@
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/slab.h>
21#include <linux/platform_device.h> 22#include <linux/platform_device.h>
23#include <linux/regulator/consumer.h>
22#include <linux/spi/spi.h> 24#include <linux/spi/spi.h>
23#include <sound/core.h> 25#include <sound/core.h>
24#include <sound/pcm.h> 26#include <sound/pcm.h>
@@ -33,9 +35,18 @@
33static struct snd_soc_codec *wm8731_codec; 35static struct snd_soc_codec *wm8731_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8731; 36struct snd_soc_codec_device soc_codec_dev_wm8731;
35 37
38#define WM8731_NUM_SUPPLIES 4
39static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
40 "AVDD",
41 "HPVDD",
42 "DCVDD",
43 "DBVDD",
44};
45
36/* codec private data */ 46/* codec private data */
37struct wm8731_priv { 47struct wm8731_priv {
38 struct snd_soc_codec codec; 48 struct snd_soc_codec codec;
49 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
39 u16 reg_cache[WM8731_CACHEREGNUM]; 50 u16 reg_cache[WM8731_CACHEREGNUM];
40 unsigned int sysclk; 51 unsigned int sysclk;
41}; 52};
@@ -149,7 +160,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
149 160
150 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 161 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
151 162
152 snd_soc_dapm_new_widgets(codec);
153 return 0; 163 return 0;
154} 164}
155 165
@@ -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,18 +445,28 @@ 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++) {
460 if (cache[i] == wm8731_reg[i])
461 continue;
462
441 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 463 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
442 data[1] = cache[i] & 0x00ff; 464 data[1] = cache[i] & 0x00ff;
443 codec->hw_write(codec->control_data, data, 2); 465 codec->hw_write(codec->control_data, data, 2);
444 } 466 }
445 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 467 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
446 wm8731_set_bias_level(codec, codec->suspend_bias_level); 468 wm8731_set_bias_level(codec, codec->suspend_bias_level);
469
447 return 0; 470 return 0;
448} 471}
449#else 472#else
@@ -475,17 +498,9 @@ static int wm8731_probe(struct platform_device *pdev)
475 snd_soc_add_controls(codec, wm8731_snd_controls, 498 snd_soc_add_controls(codec, wm8731_snd_controls,
476 ARRAY_SIZE(wm8731_snd_controls)); 499 ARRAY_SIZE(wm8731_snd_controls));
477 wm8731_add_widgets(codec); 500 wm8731_add_widgets(codec);
478 ret = snd_soc_init_card(socdev);
479 if (ret < 0) {
480 dev_err(codec->dev, "failed to register card: %d\n", ret);
481 goto card_err;
482 }
483 501
484 return ret; 502 return ret;
485 503
486card_err:
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489pcm_err: 504pcm_err:
490 return ret; 505 return ret;
491} 506}
@@ -512,7 +527,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
512static int wm8731_register(struct wm8731_priv *wm8731, 527static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control) 528 enum snd_soc_control_type control)
514{ 529{
515 int ret; 530 int ret, i;
516 struct snd_soc_codec *codec = &wm8731->codec; 531 struct snd_soc_codec *codec = &wm8731->codec;
517 532
518 if (wm8731_codec) { 533 if (wm8731_codec) {
@@ -543,10 +558,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
543 goto err; 558 goto err;
544 } 559 }
545 560
561 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
562 wm8731->supplies[i].supply = wm8731_supply_names[i];
563
564 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
565 wm8731->supplies);
566 if (ret != 0) {
567 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
568 goto err;
569 }
570
571 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
572 wm8731->supplies);
573 if (ret != 0) {
574 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
575 goto err_regulator_get;
576 }
577
546 ret = wm8731_reset(codec); 578 ret = wm8731_reset(codec);
547 if (ret < 0) { 579 if (ret < 0) {
548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 580 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
549 goto err; 581 goto err_regulator_enable;
550 } 582 }
551 583
552 wm8731_dai.dev = codec->dev; 584 wm8731_dai.dev = codec->dev;
@@ -567,7 +599,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
567 ret = snd_soc_register_codec(codec); 599 ret = snd_soc_register_codec(codec);
568 if (ret != 0) { 600 if (ret != 0) {
569 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 601 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
570 goto err; 602 goto err_regulator_enable;
571 } 603 }
572 604
573 ret = snd_soc_register_dai(&wm8731_dai); 605 ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +613,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
581 613
582err_codec: 614err_codec:
583 snd_soc_unregister_codec(codec); 615 snd_soc_unregister_codec(codec);
616err_regulator_enable:
617 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
618err_regulator_get:
619 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
584err: 620err:
585 kfree(wm8731); 621 kfree(wm8731);
586 return ret; 622 return ret;
@@ -591,6 +627,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
591 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 627 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
592 snd_soc_unregister_dai(&wm8731_dai); 628 snd_soc_unregister_dai(&wm8731_dai);
593 snd_soc_unregister_codec(&wm8731->codec); 629 snd_soc_unregister_codec(&wm8731->codec);
630 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
631 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
594 kfree(wm8731); 632 kfree(wm8731);
595 wm8731_codec = NULL; 633 wm8731_codec = NULL;
596} 634}
@@ -623,21 +661,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
623 return 0; 661 return 0;
624} 662}
625 663
626#ifdef CONFIG_PM
627static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
628{
629 return snd_soc_suspend_device(&spi->dev);
630}
631
632static int wm8731_spi_resume(struct spi_device *spi)
633{
634 return snd_soc_resume_device(&spi->dev);
635}
636#else
637#define wm8731_spi_suspend NULL
638#define wm8731_spi_resume NULL
639#endif
640
641static struct spi_driver wm8731_spi_driver = { 664static struct spi_driver wm8731_spi_driver = {
642 .driver = { 665 .driver = {
643 .name = "wm8731", 666 .name = "wm8731",
@@ -645,8 +668,6 @@ static struct spi_driver wm8731_spi_driver = {
645 .owner = THIS_MODULE, 668 .owner = THIS_MODULE,
646 }, 669 },
647 .probe = wm8731_spi_probe, 670 .probe = wm8731_spi_probe,
648 .suspend = wm8731_spi_suspend,
649 .resume = wm8731_spi_resume,
650 .remove = __devexit_p(wm8731_spi_remove), 671 .remove = __devexit_p(wm8731_spi_remove),
651}; 672};
652#endif /* CONFIG_SPI_MASTER */ 673#endif /* CONFIG_SPI_MASTER */
@@ -679,21 +700,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
679 return 0; 700 return 0;
680} 701}
681 702
682#ifdef CONFIG_PM
683static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
684{
685 return snd_soc_suspend_device(&i2c->dev);
686}
687
688static int wm8731_i2c_resume(struct i2c_client *i2c)
689{
690 return snd_soc_resume_device(&i2c->dev);
691}
692#else
693#define wm8731_i2c_suspend NULL
694#define wm8731_i2c_resume NULL
695#endif
696
697static const struct i2c_device_id wm8731_i2c_id[] = { 703static const struct i2c_device_id wm8731_i2c_id[] = {
698 { "wm8731", 0 }, 704 { "wm8731", 0 },
699 { } 705 { }
@@ -707,8 +713,6 @@ static struct i2c_driver wm8731_i2c_driver = {
707 }, 713 },
708 .probe = wm8731_i2c_probe, 714 .probe = wm8731_i2c_probe,
709 .remove = __devexit_p(wm8731_i2c_remove), 715 .remove = __devexit_p(wm8731_i2c_remove),
710 .suspend = wm8731_i2c_suspend,
711 .resume = wm8731_i2c_resume,
712 .id_table = wm8731_i2c_id, 716 .id_table = wm8731_i2c_id,
713}; 717};
714#endif 718#endif