diff options
Diffstat (limited to 'sound/soc/codecs/tas5086.c')
-rw-r--r-- | sound/soc/codecs/tas5086.c | 75 |
1 files changed, 62 insertions, 13 deletions
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d48491a4a19d..249ef5c4c762 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 | ||
244 | static const char * const supply_names[] = { | ||
245 | "dvdd", "avdd" | ||
246 | }; | ||
247 | |||
243 | struct tas5086_private { | 248 | struct 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 | ||
256 | static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; | 262 | static int tas5086_deemph[] = { 0, 32000, 44100, 48000 }; |
@@ -419,14 +425,14 @@ static int tas5086_hw_params(struct snd_pcm_substream *substream, | |||
419 | } | 425 | } |
420 | 426 | ||
421 | /* ... then add the offset for the sample bit depth. */ | 427 | /* ... then add the offset for the sample bit depth. */ |
422 | switch (params_format(params)) { | 428 | switch (params_width(params)) { |
423 | case SNDRV_PCM_FORMAT_S16_LE: | 429 | case 16: |
424 | val += 0; | 430 | val += 0; |
425 | break; | 431 | break; |
426 | case SNDRV_PCM_FORMAT_S20_3LE: | 432 | case 20: |
427 | val += 1; | 433 | val += 1; |
428 | break; | 434 | break; |
429 | case SNDRV_PCM_FORMAT_S24_3LE: | 435 | case 24: |
430 | val += 2; | 436 | val += 2; |
431 | break; | 437 | break; |
432 | default: | 438 | default: |
@@ -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 | |||
865 | exit_disable_regulators: | ||
866 | regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
867 | |||
868 | return ret; | ||
845 | } | 869 | } |
846 | 870 | ||
847 | static int tas5086_remove(struct snd_soc_codec *codec) | 871 | static 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 | ||
939 | static int tas5086_i2c_remove(struct i2c_client *i2c) | 988 | static int tas5086_i2c_remove(struct i2c_client *i2c) |