aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Mack <zonque@gmail.com>2014-07-03 10:56:43 -0400
committerMark Brown <broonie@linaro.org>2014-07-03 11:09:42 -0400
commitc46af3124b05ccb37d1311e442f191bb5c1d888e (patch)
treebadc98c3da5fff36ec11026724ef33927a1722af
parent7171511eaec5bf23fb06078f59784a3a0626b38f (diff)
ASoC: tas5086: add regulator consumer support
The TAS5086 has two power domains, DVDD and AVDD. Enable them both as long as the codec is in use. Also, switch on the power to identify the chip at device probe level, and switch it off again afterwards. The codec level will take care for power handling later. Signed-off-by: Daniel Mack <zonque@gmail.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--Documentation/devicetree/bindings/sound/ti,tas5086.txt5
-rw-r--r--sound/soc/codecs/tas5086.c67
2 files changed, 63 insertions, 9 deletions
diff --git a/Documentation/devicetree/bindings/sound/ti,tas5086.txt b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
index d2866a0d6a26..234dad296da7 100644
--- a/Documentation/devicetree/bindings/sound/ti,tas5086.txt
+++ b/Documentation/devicetree/bindings/sound/ti,tas5086.txt
@@ -31,6 +31,9 @@ Optional properties:
31 31
32 Most systems should not set any of these properties. 32 Most systems should not set any of these properties.
33 33
34 - avdd-supply: Power supply for AVDD, providing 3.3V
35 - dvdd-supply: Power supply for DVDD, providing 3.3V
36
34Examples: 37Examples:
35 38
36 i2c_bus { 39 i2c_bus {
@@ -39,5 +42,7 @@ Examples:
39 reg = <0x1b>; 42 reg = <0x1b>;
40 reset-gpio = <&gpio 23 0>; 43 reset-gpio = <&gpio 23 0>;
41 ti,charge-period = <156000>; 44 ti,charge-period = <156000>;
45 avdd-supply = <&vdd_3v3_reg>;
46 dvdd-supply = <&vdd_3v3_reg>;
42 }; 47 };
43 }; 48 };
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index d48491a4a19d..be7194b43b7a 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -36,6 +36,7 @@
36#include <linux/gpio.h> 36#include <linux/gpio.h>
37#include <linux/i2c.h> 37#include <linux/i2c.h>
38#include <linux/regmap.h> 38#include <linux/regmap.h>
39#include <linux/regulator/consumer.h>
39#include <linux/spi/spi.h> 40#include <linux/spi/spi.h>
40#include <linux/of.h> 41#include <linux/of.h>
41#include <linux/of_device.h> 42#include <linux/of_device.h>
@@ -240,6 +241,10 @@ static int tas5086_reg_read(void *context, unsigned int reg,
240 return 0; 241 return 0;
241} 242}
242 243
244static const char * const supply_names[] = {
245 "dvdd", "avdd"
246};
247
243struct tas5086_private { 248struct tas5086_private {
244 struct regmap *regmap; 249 struct regmap *regmap;
245 unsigned int mclk, sclk; 250 unsigned int mclk, sclk;
@@ -251,6 +256,7 @@ struct tas5086_private {
251 int rate; 256 int rate;
252 /* GPIO driving Reset pin, if any */ 257 /* GPIO driving Reset pin, if any */
253 int gpio_nreset; 258 int gpio_nreset;
259 struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
254}; 260};
255 261
256static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; 262static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
@@ -773,6 +779,8 @@ static int tas5086_soc_suspend(struct snd_soc_codec *codec)
773 if (ret < 0) 779 if (ret < 0)
774 return ret; 780 return ret;
775 781
782 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
783
776 return 0; 784 return 0;
777} 785}
778 786
@@ -781,6 +789,10 @@ static int tas5086_soc_resume(struct snd_soc_codec *codec)
781 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 789 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
782 int ret; 790 int ret;
783 791
792 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
793 if (ret < 0)
794 return ret;
795
784 tas5086_reset(priv); 796 tas5086_reset(priv);
785 regcache_mark_dirty(priv->regmap); 797 regcache_mark_dirty(priv->regmap);
786 798
@@ -812,6 +824,12 @@ static int tas5086_probe(struct snd_soc_codec *codec)
812 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 824 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec);
813 int i, ret; 825 int i, ret;
814 826
827 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
828 if (ret < 0) {
829 dev_err(codec->dev, "Failed to enable regulators: %d\n", ret);
830 return ret;
831 }
832
815 priv->pwm_start_mid_z = 0; 833 priv->pwm_start_mid_z = 0;
816 priv->charge_period = 1300000; /* hardware default is 1300 ms */ 834 priv->charge_period = 1300000; /* hardware default is 1300 ms */
817 835
@@ -832,16 +850,22 @@ static int tas5086_probe(struct snd_soc_codec *codec)
832 } 850 }
833 } 851 }
834 852
853 tas5086_reset(priv);
835 ret = tas5086_init(codec->dev, priv); 854 ret = tas5086_init(codec->dev, priv);
836 if (ret < 0) 855 if (ret < 0)
837 return ret; 856 goto exit_disable_regulators;
838 857
839 /* set master volume to 0 dB */ 858 /* set master volume to 0 dB */
840 ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30); 859 ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
841 if (ret < 0) 860 if (ret < 0)
842 return ret; 861 goto exit_disable_regulators;
843 862
844 return 0; 863 return 0;
864
865exit_disable_regulators:
866 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
867
868 return ret;
845} 869}
846 870
847static int tas5086_remove(struct snd_soc_codec *codec) 871static int tas5086_remove(struct snd_soc_codec *codec)
@@ -852,6 +876,8 @@ static int tas5086_remove(struct snd_soc_codec *codec)
852 /* Set codec to the reset state */ 876 /* Set codec to the reset state */
853 gpio_set_value(priv->gpio_nreset, 0); 877 gpio_set_value(priv->gpio_nreset, 0);
854 878
879 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
880
855 return 0; 881 return 0;
856}; 882};
857 883
@@ -900,6 +926,16 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
900 if (!priv) 926 if (!priv)
901 return -ENOMEM; 927 return -ENOMEM;
902 928
929 for (i = 0; i < ARRAY_SIZE(supply_names); i++)
930 priv->supplies[i].supply = supply_names[i];
931
932 ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
933 priv->supplies);
934 if (ret < 0) {
935 dev_err(dev, "Failed to get regulators: %d\n", ret);
936 return ret;
937 }
938
903 priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); 939 priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
904 if (IS_ERR(priv->regmap)) { 940 if (IS_ERR(priv->regmap)) {
905 ret = PTR_ERR(priv->regmap); 941 ret = PTR_ERR(priv->regmap);
@@ -919,21 +955,34 @@ static int tas5086_i2c_probe(struct i2c_client *i2c,
919 gpio_nreset = -EINVAL; 955 gpio_nreset = -EINVAL;
920 956
921 priv->gpio_nreset = gpio_nreset; 957 priv->gpio_nreset = gpio_nreset;
958
959 ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
960 if (ret < 0) {
961 dev_err(dev, "Failed to enable regulators: %d\n", ret);
962 return ret;
963 }
964
922 tas5086_reset(priv); 965 tas5086_reset(priv);
923 966
924 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ 967 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
925 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); 968 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
926 if (ret < 0) 969 if (ret == 0 && i != 0x3) {
927 return ret;
928
929 if (i != 0x3) {
930 dev_err(dev, 970 dev_err(dev,
931 "Failed to identify TAS5086 codec (got %02x)\n", i); 971 "Failed to identify TAS5086 codec (got %02x)\n", i);
932 return -ENODEV; 972 ret = -ENODEV;
933 } 973 }
934 974
935 return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, 975 /*
936 &tas5086_dai, 1); 976 * The chip has been identified, so we can turn off the power
977 * again until the dai link is set up.
978 */
979 regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
980
981 if (ret == 0)
982 ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086,
983 &tas5086_dai, 1);
984
985 return ret;
937} 986}
938 987
939static int tas5086_i2c_remove(struct i2c_client *i2c) 988static int tas5086_i2c_remove(struct i2c_client *i2c)