diff options
Diffstat (limited to 'sound/soc/codecs/adau1701.c')
-rw-r--r-- | sound/soc/codecs/adau1701.c | 126 |
1 files changed, 110 insertions, 16 deletions
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index d4e219b6b98f..ff7f846e3b76 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_gpio.h> | 17 | #include <linux/of_gpio.h> |
18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
19 | #include <linux/regulator/consumer.h> | ||
19 | #include <linux/regmap.h> | 20 | #include <linux/regmap.h> |
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -101,6 +102,10 @@ | |||
101 | 102 | ||
102 | #define ADAU1701_FIRMWARE "adau1701.bin" | 103 | #define ADAU1701_FIRMWARE "adau1701.bin" |
103 | 104 | ||
105 | static const char * const supply_names[] = { | ||
106 | "dvdd", "avdd" | ||
107 | }; | ||
108 | |||
104 | struct adau1701 { | 109 | struct adau1701 { |
105 | int gpio_nreset; | 110 | int gpio_nreset; |
106 | int gpio_pll_mode[2]; | 111 | int gpio_pll_mode[2]; |
@@ -112,6 +117,7 @@ struct adau1701 { | |||
112 | u8 pin_config[12]; | 117 | u8 pin_config[12]; |
113 | 118 | ||
114 | struct sigmadsp *sigmadsp; | 119 | struct sigmadsp *sigmadsp; |
120 | struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; | ||
115 | }; | 121 | }; |
116 | 122 | ||
117 | static const struct snd_kcontrol_new adau1701_controls[] = { | 123 | static const struct snd_kcontrol_new adau1701_controls[] = { |
@@ -565,7 +571,6 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec, | |||
565 | break; | 571 | break; |
566 | } | 572 | } |
567 | 573 | ||
568 | codec->dapm.bias_level = level; | ||
569 | return 0; | 574 | return 0; |
570 | } | 575 | } |
571 | 576 | ||
@@ -669,6 +674,13 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
669 | if (ret) | 674 | if (ret) |
670 | return ret; | 675 | return ret; |
671 | 676 | ||
677 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
678 | adau1701->supplies); | ||
679 | if (ret < 0) { | ||
680 | dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); | ||
681 | return ret; | ||
682 | } | ||
683 | |||
672 | /* | 684 | /* |
673 | * Let the pll_clkdiv variable default to something that won't happen | 685 | * Let the pll_clkdiv variable default to something that won't happen |
674 | * at runtime. That way, we can postpone the firmware download from | 686 | * at runtime. That way, we can postpone the firmware download from |
@@ -680,7 +692,7 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
680 | /* initalize with pre-configured pll mode settings */ | 692 | /* initalize with pre-configured pll mode settings */ |
681 | ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); | 693 | ret = adau1701_reset(codec, adau1701->pll_clkdiv, 0); |
682 | if (ret < 0) | 694 | if (ret < 0) |
683 | return ret; | 695 | goto exit_regulators_disable; |
684 | 696 | ||
685 | /* set up pin config */ | 697 | /* set up pin config */ |
686 | val = 0; | 698 | val = 0; |
@@ -696,10 +708,60 @@ static int adau1701_probe(struct snd_soc_codec *codec) | |||
696 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); | 708 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); |
697 | 709 | ||
698 | return 0; | 710 | return 0; |
711 | |||
712 | exit_regulators_disable: | ||
713 | |||
714 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
715 | return ret; | ||
699 | } | 716 | } |
700 | 717 | ||
718 | static int adau1701_remove(struct snd_soc_codec *codec) | ||
719 | { | ||
720 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
721 | |||
722 | if (gpio_is_valid(adau1701->gpio_nreset)) | ||
723 | gpio_set_value_cansleep(adau1701->gpio_nreset, 0); | ||
724 | |||
725 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | #ifdef CONFIG_PM | ||
731 | static int adau1701_suspend(struct snd_soc_codec *codec) | ||
732 | { | ||
733 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
734 | |||
735 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), | ||
736 | adau1701->supplies); | ||
737 | |||
738 | return 0; | ||
739 | } | ||
740 | |||
741 | static int adau1701_resume(struct snd_soc_codec *codec) | ||
742 | { | ||
743 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
744 | int ret; | ||
745 | |||
746 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
747 | adau1701->supplies); | ||
748 | if (ret < 0) { | ||
749 | dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); | ||
750 | return ret; | ||
751 | } | ||
752 | |||
753 | return adau1701_reset(codec, adau1701->pll_clkdiv, 0); | ||
754 | } | ||
755 | #else | ||
756 | #define adau1701_resume NULL | ||
757 | #define adau1701_suspend NULL | ||
758 | #endif /* CONFIG_PM */ | ||
759 | |||
701 | static struct snd_soc_codec_driver adau1701_codec_drv = { | 760 | static struct snd_soc_codec_driver adau1701_codec_drv = { |
702 | .probe = adau1701_probe, | 761 | .probe = adau1701_probe, |
762 | .remove = adau1701_remove, | ||
763 | .resume = adau1701_resume, | ||
764 | .suspend = adau1701_suspend, | ||
703 | .set_bias_level = adau1701_set_bias_level, | 765 | .set_bias_level = adau1701_set_bias_level, |
704 | .idle_bias_off = true, | 766 | .idle_bias_off = true, |
705 | 767 | ||
@@ -730,32 +792,58 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
730 | struct device *dev = &client->dev; | 792 | struct device *dev = &client->dev; |
731 | int gpio_nreset = -EINVAL; | 793 | int gpio_nreset = -EINVAL; |
732 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; | 794 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; |
733 | int ret; | 795 | int ret, i; |
734 | 796 | ||
735 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); | 797 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); |
736 | if (!adau1701) | 798 | if (!adau1701) |
737 | return -ENOMEM; | 799 | return -ENOMEM; |
738 | 800 | ||
801 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | ||
802 | adau1701->supplies[i].supply = supply_names[i]; | ||
803 | |||
804 | ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(adau1701->supplies), | ||
805 | adau1701->supplies); | ||
806 | if (ret < 0) { | ||
807 | dev_err(dev, "Failed to get regulators: %d\n", ret); | ||
808 | return ret; | ||
809 | } | ||
810 | |||
811 | ret = regulator_bulk_enable(ARRAY_SIZE(adau1701->supplies), | ||
812 | adau1701->supplies); | ||
813 | if (ret < 0) { | ||
814 | dev_err(dev, "Failed to enable regulators: %d\n", ret); | ||
815 | return ret; | ||
816 | } | ||
817 | |||
739 | adau1701->client = client; | 818 | adau1701->client = client; |
740 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | 819 | adau1701->regmap = devm_regmap_init(dev, NULL, client, |
741 | &adau1701_regmap); | 820 | &adau1701_regmap); |
742 | if (IS_ERR(adau1701->regmap)) | 821 | if (IS_ERR(adau1701->regmap)) { |
743 | return PTR_ERR(adau1701->regmap); | 822 | ret = PTR_ERR(adau1701->regmap); |
823 | goto exit_regulators_disable; | ||
824 | } | ||
825 | |||
744 | 826 | ||
745 | if (dev->of_node) { | 827 | if (dev->of_node) { |
746 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); | 828 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); |
747 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) | 829 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) { |
748 | return gpio_nreset; | 830 | ret = gpio_nreset; |
831 | goto exit_regulators_disable; | ||
832 | } | ||
749 | 833 | ||
750 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, | 834 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, |
751 | "adi,pll-mode-gpios", 0); | 835 | "adi,pll-mode-gpios", 0); |
752 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) | 836 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) { |
753 | return gpio_pll_mode[0]; | 837 | ret = gpio_pll_mode[0]; |
838 | goto exit_regulators_disable; | ||
839 | } | ||
754 | 840 | ||
755 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, | 841 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, |
756 | "adi,pll-mode-gpios", 1); | 842 | "adi,pll-mode-gpios", 1); |
757 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) | 843 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) { |
758 | return gpio_pll_mode[1]; | 844 | ret = gpio_pll_mode[1]; |
845 | goto exit_regulators_disable; | ||
846 | } | ||
759 | 847 | ||
760 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", | 848 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", |
761 | &adau1701->pll_clkdiv); | 849 | &adau1701->pll_clkdiv); |
@@ -769,7 +857,7 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
769 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, | 857 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, |
770 | "ADAU1701 Reset"); | 858 | "ADAU1701 Reset"); |
771 | if (ret < 0) | 859 | if (ret < 0) |
772 | return ret; | 860 | goto exit_regulators_disable; |
773 | } | 861 | } |
774 | 862 | ||
775 | if (gpio_is_valid(gpio_pll_mode[0]) && | 863 | if (gpio_is_valid(gpio_pll_mode[0]) && |
@@ -778,13 +866,13 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
778 | GPIOF_OUT_INIT_LOW, | 866 | GPIOF_OUT_INIT_LOW, |
779 | "ADAU1701 PLL mode 0"); | 867 | "ADAU1701 PLL mode 0"); |
780 | if (ret < 0) | 868 | if (ret < 0) |
781 | return ret; | 869 | goto exit_regulators_disable; |
782 | 870 | ||
783 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], | 871 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], |
784 | GPIOF_OUT_INIT_LOW, | 872 | GPIOF_OUT_INIT_LOW, |
785 | "ADAU1701 PLL mode 1"); | 873 | "ADAU1701 PLL mode 1"); |
786 | if (ret < 0) | 874 | if (ret < 0) |
787 | return ret; | 875 | goto exit_regulators_disable; |
788 | } | 876 | } |
789 | 877 | ||
790 | adau1701->gpio_nreset = gpio_nreset; | 878 | adau1701->gpio_nreset = gpio_nreset; |
@@ -795,11 +883,17 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
795 | 883 | ||
796 | adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, | 884 | adau1701->sigmadsp = devm_sigmadsp_init_i2c(client, |
797 | &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); | 885 | &adau1701_sigmadsp_ops, ADAU1701_FIRMWARE); |
798 | if (IS_ERR(adau1701->sigmadsp)) | 886 | if (IS_ERR(adau1701->sigmadsp)) { |
799 | return PTR_ERR(adau1701->sigmadsp); | 887 | ret = PTR_ERR(adau1701->sigmadsp); |
888 | goto exit_regulators_disable; | ||
889 | } | ||
800 | 890 | ||
801 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 891 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
802 | &adau1701_dai, 1); | 892 | &adau1701_dai, 1); |
893 | |||
894 | exit_regulators_disable: | ||
895 | |||
896 | regulator_bulk_disable(ARRAY_SIZE(adau1701->supplies), adau1701->supplies); | ||
803 | return ret; | 897 | return ret; |
804 | } | 898 | } |
805 | 899 | ||