Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Daniel Mack and committed by
Mark Brown
c46af312 7171511e

+63 -9
+5
Documentation/devicetree/bindings/sound/ti,tas5086.txt
··· 31 31 32 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 + 34 37 Examples: 35 38 36 39 i2c_bus { ··· 42 39 reg = <0x1b>; 43 40 reset-gpio = <&gpio 23 0>; 44 41 ti,charge-period = <156000>; 42 + avdd-supply = <&vdd_3v3_reg>; 43 + dvdd-supply = <&vdd_3v3_reg>; 45 44 }; 46 45 };
+58 -9
sound/soc/codecs/tas5086.c
··· 36 36 #include <linux/gpio.h> 37 37 #include <linux/i2c.h> 38 38 #include <linux/regmap.h> 39 + #include <linux/regulator/consumer.h> 39 40 #include <linux/spi/spi.h> 40 41 #include <linux/of.h> 41 42 #include <linux/of_device.h> ··· 241 240 return 0; 242 241 } 243 242 243 + static const char * const supply_names[] = { 244 + "dvdd", "avdd" 245 + }; 246 + 244 247 struct tas5086_private { 245 248 struct regmap *regmap; 246 249 unsigned int mclk, sclk; ··· 256 251 int rate; 257 252 /* GPIO driving Reset pin, if any */ 258 253 int gpio_nreset; 254 + struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)]; 259 255 }; 260 256 261 257 static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; ··· 779 773 if (ret < 0) 780 774 return ret; 781 775 776 + regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); 777 + 782 778 return 0; 783 779 } 784 780 ··· 788 780 { 789 781 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 790 782 int ret; 783 + 784 + ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); 785 + if (ret < 0) 786 + return ret; 791 787 792 788 tas5086_reset(priv); 793 789 regcache_mark_dirty(priv->regmap); ··· 824 812 struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); 825 813 int i, ret; 826 814 815 + ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); 816 + if (ret < 0) { 817 + dev_err(codec->dev, "Failed to enable regulators: %d\n", ret); 818 + return ret; 819 + } 820 + 827 821 priv->pwm_start_mid_z = 0; 828 822 priv->charge_period = 1300000; /* hardware default is 1300 ms */ 829 823 ··· 850 832 } 851 833 } 852 834 835 + tas5086_reset(priv); 853 836 ret = tas5086_init(codec->dev, priv); 854 837 if (ret < 0) 855 - return ret; 838 + goto exit_disable_regulators; 856 839 857 840 /* set master volume to 0 dB */ 858 841 ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30); 859 842 if (ret < 0) 860 - return ret; 843 + goto exit_disable_regulators; 861 844 862 845 return 0; 846 + 847 + exit_disable_regulators: 848 + regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); 849 + 850 + return ret; 863 851 } 864 852 865 853 static int tas5086_remove(struct snd_soc_codec *codec) ··· 875 851 if (gpio_is_valid(priv->gpio_nreset)) 876 852 /* Set codec to the reset state */ 877 853 gpio_set_value(priv->gpio_nreset, 0); 854 + 855 + regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); 878 856 879 857 return 0; 880 858 }; ··· 926 900 if (!priv) 927 901 return -ENOMEM; 928 902 903 + for (i = 0; i < ARRAY_SIZE(supply_names); i++) 904 + priv->supplies[i].supply = supply_names[i]; 905 + 906 + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies), 907 + priv->supplies); 908 + if (ret < 0) { 909 + dev_err(dev, "Failed to get regulators: %d\n", ret); 910 + return ret; 911 + } 912 + 929 913 priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); 930 914 if (IS_ERR(priv->regmap)) { 931 915 ret = PTR_ERR(priv->regmap); ··· 955 919 gpio_nreset = -EINVAL; 956 920 957 921 priv->gpio_nreset = gpio_nreset; 922 + 923 + ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies); 924 + if (ret < 0) { 925 + dev_err(dev, "Failed to enable regulators: %d\n", ret); 926 + return ret; 927 + } 928 + 958 929 tas5086_reset(priv); 959 930 960 931 /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */ 961 932 ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i); 962 - if (ret < 0) 963 - return ret; 964 - 965 - if (i != 0x3) { 933 + if (ret == 0 && i != 0x3) { 966 934 dev_err(dev, 967 935 "Failed to identify TAS5086 codec (got %02x)\n", i); 968 - return -ENODEV; 936 + ret = -ENODEV; 969 937 } 970 938 971 - return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, 972 - &tas5086_dai, 1); 939 + /* 940 + * The chip has been identified, so we can turn off the power 941 + * again until the dai link is set up. 942 + */ 943 + regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); 944 + 945 + if (ret == 0) 946 + ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_tas5086, 947 + &tas5086_dai, 1); 948 + 949 + return ret; 973 950 } 974 951 975 952 static int tas5086_i2c_remove(struct i2c_client *i2c)