diff options
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r-- | sound/soc/codecs/wm8731.c | 94 |
1 files changed, 47 insertions, 47 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index d3fd4f28d96e..3a497810f939 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 | }; |
@@ -149,7 +159,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec) | |||
149 | 159 | ||
150 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | 160 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); |
151 | 161 | ||
152 | snd_soc_dapm_new_widgets(codec); | ||
153 | return 0; | 162 | return 0; |
154 | } | 163 | } |
155 | 164 | ||
@@ -422,9 +431,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state) | |||
422 | { | 431 | { |
423 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 432 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
424 | struct snd_soc_codec *codec = socdev->card->codec; | 433 | struct snd_soc_codec *codec = socdev->card->codec; |
434 | struct wm8731_priv *wm8731 = codec->private_data; | ||
425 | 435 | ||
426 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); | 436 | snd_soc_write(codec, WM8731_ACTIVE, 0x0); |
427 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); | 437 | wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); |
438 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), | ||
439 | wm8731->supplies); | ||
428 | return 0; | 440 | return 0; |
429 | } | 441 | } |
430 | 442 | ||
@@ -432,10 +444,16 @@ static int wm8731_resume(struct platform_device *pdev) | |||
432 | { | 444 | { |
433 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 445 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
434 | struct snd_soc_codec *codec = socdev->card->codec; | 446 | struct snd_soc_codec *codec = socdev->card->codec; |
435 | int i; | 447 | struct wm8731_priv *wm8731 = codec->private_data; |
448 | int i, ret; | ||
436 | u8 data[2]; | 449 | u8 data[2]; |
437 | u16 *cache = codec->reg_cache; | 450 | u16 *cache = codec->reg_cache; |
438 | 451 | ||
452 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
453 | wm8731->supplies); | ||
454 | if (ret != 0) | ||
455 | return ret; | ||
456 | |||
439 | /* Sync reg_cache with the hardware */ | 457 | /* Sync reg_cache with the hardware */ |
440 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { | 458 | for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { |
441 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); | 459 | data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); |
@@ -444,6 +462,7 @@ static int wm8731_resume(struct platform_device *pdev) | |||
444 | } | 462 | } |
445 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 463 | wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
446 | wm8731_set_bias_level(codec, codec->suspend_bias_level); | 464 | wm8731_set_bias_level(codec, codec->suspend_bias_level); |
465 | |||
447 | return 0; | 466 | return 0; |
448 | } | 467 | } |
449 | #else | 468 | #else |
@@ -475,17 +494,9 @@ static int wm8731_probe(struct platform_device *pdev) | |||
475 | snd_soc_add_controls(codec, wm8731_snd_controls, | 494 | snd_soc_add_controls(codec, wm8731_snd_controls, |
476 | ARRAY_SIZE(wm8731_snd_controls)); | 495 | ARRAY_SIZE(wm8731_snd_controls)); |
477 | wm8731_add_widgets(codec); | 496 | 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 | 497 | ||
484 | return ret; | 498 | return ret; |
485 | 499 | ||
486 | card_err: | ||
487 | snd_soc_free_pcms(socdev); | ||
488 | snd_soc_dapm_free(socdev); | ||
489 | pcm_err: | 500 | pcm_err: |
490 | return ret; | 501 | return ret; |
491 | } | 502 | } |
@@ -512,7 +523,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731); | |||
512 | static int wm8731_register(struct wm8731_priv *wm8731, | 523 | static int wm8731_register(struct wm8731_priv *wm8731, |
513 | enum snd_soc_control_type control) | 524 | enum snd_soc_control_type control) |
514 | { | 525 | { |
515 | int ret; | 526 | int ret, i; |
516 | struct snd_soc_codec *codec = &wm8731->codec; | 527 | struct snd_soc_codec *codec = &wm8731->codec; |
517 | 528 | ||
518 | if (wm8731_codec) { | 529 | if (wm8731_codec) { |
@@ -543,10 +554,27 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
543 | goto err; | 554 | goto err; |
544 | } | 555 | } |
545 | 556 | ||
557 | for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++) | ||
558 | wm8731->supplies[i].supply = wm8731_supply_names[i]; | ||
559 | |||
560 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies), | ||
561 | wm8731->supplies); | ||
562 | if (ret != 0) { | ||
563 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
564 | goto err; | ||
565 | } | ||
566 | |||
567 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies), | ||
568 | wm8731->supplies); | ||
569 | if (ret != 0) { | ||
570 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
571 | goto err_regulator_get; | ||
572 | } | ||
573 | |||
546 | ret = wm8731_reset(codec); | 574 | ret = wm8731_reset(codec); |
547 | if (ret < 0) { | 575 | if (ret < 0) { |
548 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 576 | dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
549 | goto err; | 577 | goto err_regulator_enable; |
550 | } | 578 | } |
551 | 579 | ||
552 | wm8731_dai.dev = codec->dev; | 580 | wm8731_dai.dev = codec->dev; |
@@ -567,7 +595,7 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
567 | ret = snd_soc_register_codec(codec); | 595 | ret = snd_soc_register_codec(codec); |
568 | if (ret != 0) { | 596 | if (ret != 0) { |
569 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | 597 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); |
570 | goto err; | 598 | goto err_regulator_enable; |
571 | } | 599 | } |
572 | 600 | ||
573 | ret = snd_soc_register_dai(&wm8731_dai); | 601 | ret = snd_soc_register_dai(&wm8731_dai); |
@@ -581,6 +609,10 @@ static int wm8731_register(struct wm8731_priv *wm8731, | |||
581 | 609 | ||
582 | err_codec: | 610 | err_codec: |
583 | snd_soc_unregister_codec(codec); | 611 | snd_soc_unregister_codec(codec); |
612 | err_regulator_enable: | ||
613 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
614 | err_regulator_get: | ||
615 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
584 | err: | 616 | err: |
585 | kfree(wm8731); | 617 | kfree(wm8731); |
586 | return ret; | 618 | return ret; |
@@ -591,6 +623,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731) | |||
591 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); | 623 | wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); |
592 | snd_soc_unregister_dai(&wm8731_dai); | 624 | snd_soc_unregister_dai(&wm8731_dai); |
593 | snd_soc_unregister_codec(&wm8731->codec); | 625 | snd_soc_unregister_codec(&wm8731->codec); |
626 | regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
627 | regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies); | ||
594 | kfree(wm8731); | 628 | kfree(wm8731); |
595 | wm8731_codec = NULL; | 629 | wm8731_codec = NULL; |
596 | } | 630 | } |
@@ -623,21 +657,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi) | |||
623 | return 0; | 657 | return 0; |
624 | } | 658 | } |
625 | 659 | ||
626 | #ifdef CONFIG_PM | ||
627 | static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg) | ||
628 | { | ||
629 | return snd_soc_suspend_device(&spi->dev); | ||
630 | } | ||
631 | |||
632 | static 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 | |||
641 | static struct spi_driver wm8731_spi_driver = { | 660 | static struct spi_driver wm8731_spi_driver = { |
642 | .driver = { | 661 | .driver = { |
643 | .name = "wm8731", | 662 | .name = "wm8731", |
@@ -645,8 +664,6 @@ static struct spi_driver wm8731_spi_driver = { | |||
645 | .owner = THIS_MODULE, | 664 | .owner = THIS_MODULE, |
646 | }, | 665 | }, |
647 | .probe = wm8731_spi_probe, | 666 | .probe = wm8731_spi_probe, |
648 | .suspend = wm8731_spi_suspend, | ||
649 | .resume = wm8731_spi_resume, | ||
650 | .remove = __devexit_p(wm8731_spi_remove), | 667 | .remove = __devexit_p(wm8731_spi_remove), |
651 | }; | 668 | }; |
652 | #endif /* CONFIG_SPI_MASTER */ | 669 | #endif /* CONFIG_SPI_MASTER */ |
@@ -679,21 +696,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client) | |||
679 | return 0; | 696 | return 0; |
680 | } | 697 | } |
681 | 698 | ||
682 | #ifdef CONFIG_PM | ||
683 | static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg) | ||
684 | { | ||
685 | return snd_soc_suspend_device(&i2c->dev); | ||
686 | } | ||
687 | |||
688 | static 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 | |||
697 | static const struct i2c_device_id wm8731_i2c_id[] = { | 699 | static const struct i2c_device_id wm8731_i2c_id[] = { |
698 | { "wm8731", 0 }, | 700 | { "wm8731", 0 }, |
699 | { } | 701 | { } |
@@ -707,8 +709,6 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
707 | }, | 709 | }, |
708 | .probe = wm8731_i2c_probe, | 710 | .probe = wm8731_i2c_probe, |
709 | .remove = __devexit_p(wm8731_i2c_remove), | 711 | .remove = __devexit_p(wm8731_i2c_remove), |
710 | .suspend = wm8731_i2c_suspend, | ||
711 | .resume = wm8731_i2c_resume, | ||
712 | .id_table = wm8731_i2c_id, | 712 | .id_table = wm8731_i2c_id, |
713 | }; | 713 | }; |
714 | #endif | 714 | #endif |