aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarkus Pargmann <mpa@pengutronix.de>2014-02-20 12:22:59 -0500
committerMark Brown <broonie@linaro.org>2014-02-22 22:59:31 -0500
commit239b669b2dedc46d5e6b07d87c3d1dedf8d9477c (patch)
treeb150ff9d9af91974b7bff8ba8f24b454a9fc45e4
parent98b664e2ceddd40120e8cd2aa56f7eb9a51870cf (diff)
ASoC: tlv320aic32x4: Support for regulators
Support regulators to power up the codec. This patch also enables the AVDD LDO if no AV regulator was found. Signed-off-by: Markus Pargmann <mpa@pengutronix.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/tlv320aic32x4.txt8
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c126
2 files changed, 133 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
index 352be7b1f7e2..5e2741af27be 100644
--- a/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
+++ b/Documentation/devicetree/bindings/sound/tlv320aic32x4.txt
@@ -5,6 +5,14 @@ The tlv320aic32x4 serial control bus communicates through I2C protocols
5Required properties: 5Required properties:
6 - compatible: Should be "ti,tlv320aic32x4" 6 - compatible: Should be "ti,tlv320aic32x4"
7 - reg: I2C slave address 7 - reg: I2C slave address
8 - supply-*: Required supply regulators are:
9 "iov" - digital IO power supply
10 "ldoin" - LDO power supply
11 "dv" - Digital core power supply
12 "av" - Analog core power supply
13 If you supply ldoin, dv and av are optional. Otherwise they are required
14 See regulator/regulator.txt for more information about the detailed binding
15 format.
8 16
9Optional properties: 17Optional properties:
10 - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt 18 - reset-gpios: Reset-GPIO phandle with args as described in gpio/gpio.txt
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index 643fa53beaab..d69c61ffcda8 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -34,6 +34,7 @@
34#include <linux/cdev.h> 34#include <linux/cdev.h>
35#include <linux/slab.h> 35#include <linux/slab.h>
36#include <linux/clk.h> 36#include <linux/clk.h>
37#include <linux/regulator/consumer.h>
37 38
38#include <sound/tlv320aic32x4.h> 39#include <sound/tlv320aic32x4.h>
39#include <sound/core.h> 40#include <sound/core.h>
@@ -69,6 +70,11 @@ struct aic32x4_priv {
69 bool swapdacs; 70 bool swapdacs;
70 int rstn_gpio; 71 int rstn_gpio;
71 struct clk *mclk; 72 struct clk *mclk;
73
74 struct regulator *supply_ldo;
75 struct regulator *supply_iov;
76 struct regulator *supply_dv;
77 struct regulator *supply_av;
72}; 78};
73 79
74/* 0dB min, 0.5dB steps */ 80/* 0dB min, 0.5dB steps */
@@ -695,6 +701,106 @@ static int aic32x4_parse_dt(struct aic32x4_priv *aic32x4,
695 return 0; 701 return 0;
696} 702}
697 703
704static void aic32x4_disable_regulators(struct aic32x4_priv *aic32x4)
705{
706 regulator_disable(aic32x4->supply_iov);
707
708 if (!IS_ERR(aic32x4->supply_ldo))
709 regulator_disable(aic32x4->supply_ldo);
710
711 if (!IS_ERR(aic32x4->supply_dv))
712 regulator_disable(aic32x4->supply_dv);
713
714 if (!IS_ERR(aic32x4->supply_av))
715 regulator_disable(aic32x4->supply_av);
716}
717
718static int aic32x4_setup_regulators(struct device *dev,
719 struct aic32x4_priv *aic32x4)
720{
721 int ret = 0;
722
723 aic32x4->supply_ldo = devm_regulator_get_optional(dev, "ldoin");
724 aic32x4->supply_iov = devm_regulator_get(dev, "iov");
725 aic32x4->supply_dv = devm_regulator_get_optional(dev, "dv");
726 aic32x4->supply_av = devm_regulator_get_optional(dev, "av");
727
728 /* Check if the regulator requirements are fulfilled */
729
730 if (IS_ERR(aic32x4->supply_iov)) {
731 dev_err(dev, "Missing supply 'iov'\n");
732 return PTR_ERR(aic32x4->supply_iov);
733 }
734
735 if (IS_ERR(aic32x4->supply_ldo)) {
736 if (PTR_ERR(aic32x4->supply_ldo) == -EPROBE_DEFER)
737 return -EPROBE_DEFER;
738
739 if (IS_ERR(aic32x4->supply_dv)) {
740 dev_err(dev, "Missing supply 'dv' or 'ldoin'\n");
741 return PTR_ERR(aic32x4->supply_dv);
742 }
743 if (IS_ERR(aic32x4->supply_av)) {
744 dev_err(dev, "Missing supply 'av' or 'ldoin'\n");
745 return PTR_ERR(aic32x4->supply_av);
746 }
747 } else {
748 if (IS_ERR(aic32x4->supply_dv) &&
749 PTR_ERR(aic32x4->supply_dv) == -EPROBE_DEFER)
750 return -EPROBE_DEFER;
751 if (IS_ERR(aic32x4->supply_av) &&
752 PTR_ERR(aic32x4->supply_av) == -EPROBE_DEFER)
753 return -EPROBE_DEFER;
754 }
755
756 ret = regulator_enable(aic32x4->supply_iov);
757 if (ret) {
758 dev_err(dev, "Failed to enable regulator iov\n");
759 return ret;
760 }
761
762 if (!IS_ERR(aic32x4->supply_ldo)) {
763 ret = regulator_enable(aic32x4->supply_ldo);
764 if (ret) {
765 dev_err(dev, "Failed to enable regulator ldo\n");
766 goto error_ldo;
767 }
768 }
769
770 if (!IS_ERR(aic32x4->supply_dv)) {
771 ret = regulator_enable(aic32x4->supply_dv);
772 if (ret) {
773 dev_err(dev, "Failed to enable regulator dv\n");
774 goto error_dv;
775 }
776 }
777
778 if (!IS_ERR(aic32x4->supply_av)) {
779 ret = regulator_enable(aic32x4->supply_av);
780 if (ret) {
781 dev_err(dev, "Failed to enable regulator av\n");
782 goto error_av;
783 }
784 }
785
786 if (!IS_ERR(aic32x4->supply_ldo) && IS_ERR(aic32x4->supply_av))
787 aic32x4->power_cfg |= AIC32X4_PWR_AIC32X4_LDO_ENABLE;
788
789 return 0;
790
791error_av:
792 if (!IS_ERR(aic32x4->supply_dv))
793 regulator_disable(aic32x4->supply_dv);
794
795error_dv:
796 if (!IS_ERR(aic32x4->supply_ldo))
797 regulator_disable(aic32x4->supply_ldo);
798
799error_ldo:
800 regulator_disable(aic32x4->supply_iov);
801 return ret;
802}
803
698static int aic32x4_i2c_probe(struct i2c_client *i2c, 804static int aic32x4_i2c_probe(struct i2c_client *i2c,
699 const struct i2c_device_id *id) 805 const struct i2c_device_id *id)
700{ 806{
@@ -745,13 +851,31 @@ static int aic32x4_i2c_probe(struct i2c_client *i2c,
745 return ret; 851 return ret;
746 } 852 }
747 853
854 ret = aic32x4_setup_regulators(&i2c->dev, aic32x4);
855 if (ret) {
856 dev_err(&i2c->dev, "Failed to setup regulators\n");
857 return ret;
858 }
859
748 ret = snd_soc_register_codec(&i2c->dev, 860 ret = snd_soc_register_codec(&i2c->dev,
749 &soc_codec_dev_aic32x4, &aic32x4_dai, 1); 861 &soc_codec_dev_aic32x4, &aic32x4_dai, 1);
750 return ret; 862 if (ret) {
863 dev_err(&i2c->dev, "Failed to register codec\n");
864 aic32x4_disable_regulators(aic32x4);
865 return ret;
866 }
867
868 i2c_set_clientdata(i2c, aic32x4);
869
870 return 0;
751} 871}
752 872
753static int aic32x4_i2c_remove(struct i2c_client *client) 873static int aic32x4_i2c_remove(struct i2c_client *client)
754{ 874{
875 struct aic32x4_priv *aic32x4 = i2c_get_clientdata(client);
876
877 aic32x4_disable_regulators(aic32x4);
878
755 snd_soc_unregister_codec(&client->dev); 879 snd_soc_unregister_codec(&client->dev);
756 return 0; 880 return 0;
757} 881}