diff options
Diffstat (limited to 'sound/soc/codecs/sta32x.c')
-rw-r--r-- | sound/soc/codecs/sta32x.c | 151 |
1 files changed, 96 insertions, 55 deletions
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..0935bfe62471 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/delay.h> | 24 | #include <linux/delay.h> |
25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
26 | #include <linux/i2c.h> | 26 | #include <linux/i2c.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <linux/regulator/consumer.h> | 28 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
29 | #include <linux/workqueue.h> | 30 | #include <linux/workqueue.h> |
@@ -55,12 +56,50 @@ | |||
55 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) | 56 | SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE) |
56 | 57 | ||
57 | /* Power-up register defaults */ | 58 | /* Power-up register defaults */ |
58 | static const u8 sta32x_regs[STA32X_REGISTER_COUNT] = { | 59 | static const struct reg_default sta32x_regs[] = { |
59 | 0x63, 0x80, 0xc2, 0x40, 0xc2, 0x5c, 0x10, 0xff, 0x60, 0x60, | 60 | { 0x0, 0x63 }, |
60 | 0x60, 0x80, 0x00, 0x00, 0x00, 0x40, 0x80, 0x77, 0x6a, 0x69, | 61 | { 0x1, 0x80 }, |
61 | 0x6a, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 62 | { 0x2, 0xc2 }, |
62 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, | 63 | { 0x3, 0x40 }, |
63 | 0xc0, 0xf3, 0x33, 0x00, 0x0c, | 64 | { 0x4, 0xc2 }, |
65 | { 0x5, 0x5c }, | ||
66 | { 0x6, 0x10 }, | ||
67 | { 0x7, 0xff }, | ||
68 | { 0x8, 0x60 }, | ||
69 | { 0x9, 0x60 }, | ||
70 | { 0xa, 0x60 }, | ||
71 | { 0xb, 0x80 }, | ||
72 | { 0xc, 0x00 }, | ||
73 | { 0xd, 0x00 }, | ||
74 | { 0xe, 0x00 }, | ||
75 | { 0xf, 0x40 }, | ||
76 | { 0x10, 0x80 }, | ||
77 | { 0x11, 0x77 }, | ||
78 | { 0x12, 0x6a }, | ||
79 | { 0x13, 0x69 }, | ||
80 | { 0x14, 0x6a }, | ||
81 | { 0x15, 0x69 }, | ||
82 | { 0x16, 0x00 }, | ||
83 | { 0x17, 0x00 }, | ||
84 | { 0x18, 0x00 }, | ||
85 | { 0x19, 0x00 }, | ||
86 | { 0x1a, 0x00 }, | ||
87 | { 0x1b, 0x00 }, | ||
88 | { 0x1c, 0x00 }, | ||
89 | { 0x1d, 0x00 }, | ||
90 | { 0x1e, 0x00 }, | ||
91 | { 0x1f, 0x00 }, | ||
92 | { 0x20, 0x00 }, | ||
93 | { 0x21, 0x00 }, | ||
94 | { 0x22, 0x00 }, | ||
95 | { 0x23, 0x00 }, | ||
96 | { 0x24, 0x00 }, | ||
97 | { 0x25, 0x00 }, | ||
98 | { 0x26, 0x00 }, | ||
99 | { 0x27, 0x2d }, | ||
100 | { 0x28, 0xc0 }, | ||
101 | { 0x2b, 0x00 }, | ||
102 | { 0x2c, 0x0c }, | ||
64 | }; | 103 | }; |
65 | 104 | ||
66 | /* regulator power supply names */ | 105 | /* regulator power supply names */ |
@@ -72,6 +111,7 @@ static const char *sta32x_supply_names[] = { | |||
72 | 111 | ||
73 | /* codec private data */ | 112 | /* codec private data */ |
74 | struct sta32x_priv { | 113 | struct sta32x_priv { |
114 | struct regmap *regmap; | ||
75 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; | 115 | struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)]; |
76 | struct snd_soc_codec *codec; | 116 | struct snd_soc_codec *codec; |
77 | struct sta32x_platform_data *pdata; | 117 | struct sta32x_platform_data *pdata; |
@@ -291,17 +331,15 @@ static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec) | |||
291 | 331 | ||
292 | static int sta32x_cache_sync(struct snd_soc_codec *codec) | 332 | static int sta32x_cache_sync(struct snd_soc_codec *codec) |
293 | { | 333 | { |
334 | struct sta32x_priv *sta32x = codec->control_data; | ||
294 | unsigned int mute; | 335 | unsigned int mute; |
295 | int rc; | 336 | int rc; |
296 | 337 | ||
297 | if (!codec->cache_sync) | ||
298 | return 0; | ||
299 | |||
300 | /* mute during register sync */ | 338 | /* mute during register sync */ |
301 | mute = snd_soc_read(codec, STA32X_MMUTE); | 339 | mute = snd_soc_read(codec, STA32X_MMUTE); |
302 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); | 340 | snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE); |
303 | sta32x_sync_coef_shadow(codec); | 341 | sta32x_sync_coef_shadow(codec); |
304 | rc = snd_soc_cache_sync(codec); | 342 | rc = regcache_sync(sta32x->regmap); |
305 | snd_soc_write(codec, STA32X_MMUTE, mute); | 343 | snd_soc_write(codec, STA32X_MMUTE, mute); |
306 | return rc; | 344 | return rc; |
307 | } | 345 | } |
@@ -316,11 +354,11 @@ static void sta32x_watchdog(struct work_struct *work) | |||
316 | 354 | ||
317 | /* check if sta32x has reset itself */ | 355 | /* check if sta32x has reset itself */ |
318 | confa_cached = snd_soc_read(codec, STA32X_CONFA); | 356 | confa_cached = snd_soc_read(codec, STA32X_CONFA); |
319 | codec->cache_bypass = 1; | 357 | regcache_cache_bypass(sta32x->regmap, true); |
320 | confa = snd_soc_read(codec, STA32X_CONFA); | 358 | confa = snd_soc_read(codec, STA32X_CONFA); |
321 | codec->cache_bypass = 0; | 359 | regcache_cache_bypass(sta32x->regmap, false); |
322 | if (confa != confa_cached) { | 360 | if (confa != confa_cached) { |
323 | codec->cache_sync = 1; | 361 | regcache_mark_dirty(sta32x->regmap); |
324 | sta32x_cache_sync(codec); | 362 | sta32x_cache_sync(codec); |
325 | } | 363 | } |
326 | 364 | ||
@@ -825,31 +863,21 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
825 | sta32x->codec = codec; | 863 | sta32x->codec = codec; |
826 | sta32x->pdata = dev_get_platdata(codec->dev); | 864 | sta32x->pdata = dev_get_platdata(codec->dev); |
827 | 865 | ||
828 | /* regulators */ | ||
829 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
830 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
831 | |||
832 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sta32x->supplies), | ||
833 | sta32x->supplies); | ||
834 | if (ret != 0) { | ||
835 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
836 | goto err; | ||
837 | } | ||
838 | |||
839 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), | 866 | ret = regulator_bulk_enable(ARRAY_SIZE(sta32x->supplies), |
840 | sta32x->supplies); | 867 | sta32x->supplies); |
841 | if (ret != 0) { | 868 | if (ret != 0) { |
842 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 869 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
843 | goto err_get; | 870 | return ret; |
844 | } | 871 | } |
845 | 872 | ||
846 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will | 873 | /* Tell ASoC what kind of I/O to use to read the registers. ASoC will |
847 | * then do the I2C transactions itself. | 874 | * then do the I2C transactions itself. |
848 | */ | 875 | */ |
849 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | 876 | codec->control_data = sta32x->regmap; |
877 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
850 | if (ret < 0) { | 878 | if (ret < 0) { |
851 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); | 879 | dev_err(codec->dev, "failed to set cache I/O (ret=%i)\n", ret); |
852 | return ret; | 880 | goto err; |
853 | } | 881 | } |
854 | 882 | ||
855 | /* Chip documentation explicitly requires that the reset values | 883 | /* Chip documentation explicitly requires that the reset values |
@@ -858,13 +886,15 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
858 | * so the write to the these registers are suppressed by the cache | 886 | * so the write to the these registers are suppressed by the cache |
859 | * restore code when it skips writes of default registers. | 887 | * restore code when it skips writes of default registers. |
860 | */ | 888 | */ |
861 | snd_soc_cache_write(codec, STA32X_CONFC, 0xc2); | 889 | regcache_cache_only(sta32x->regmap, true); |
862 | snd_soc_cache_write(codec, STA32X_CONFE, 0xc2); | 890 | snd_soc_write(codec, STA32X_CONFC, 0xc2); |
863 | snd_soc_cache_write(codec, STA32X_CONFF, 0x5c); | 891 | snd_soc_write(codec, STA32X_CONFE, 0xc2); |
864 | snd_soc_cache_write(codec, STA32X_MMUTE, 0x10); | 892 | snd_soc_write(codec, STA32X_CONFF, 0x5c); |
865 | snd_soc_cache_write(codec, STA32X_AUTO1, 0x60); | 893 | snd_soc_write(codec, STA32X_MMUTE, 0x10); |
866 | snd_soc_cache_write(codec, STA32X_AUTO3, 0x00); | 894 | snd_soc_write(codec, STA32X_AUTO1, 0x60); |
867 | snd_soc_cache_write(codec, STA32X_C3CFG, 0x40); | 895 | snd_soc_write(codec, STA32X_AUTO3, 0x00); |
896 | snd_soc_write(codec, STA32X_C3CFG, 0x40); | ||
897 | regcache_cache_only(sta32x->regmap, false); | ||
868 | 898 | ||
869 | /* set thermal warning adjustment and recovery */ | 899 | /* set thermal warning adjustment and recovery */ |
870 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) | 900 | if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE)) |
@@ -915,9 +945,8 @@ static int sta32x_probe(struct snd_soc_codec *codec) | |||
915 | 945 | ||
916 | return 0; | 946 | return 0; |
917 | 947 | ||
918 | err_get: | ||
919 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
920 | err: | 948 | err: |
949 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
921 | return ret; | 950 | return ret; |
922 | } | 951 | } |
923 | 952 | ||
@@ -928,13 +957,11 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
928 | sta32x_watchdog_stop(sta32x); | 957 | sta32x_watchdog_stop(sta32x); |
929 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | 958 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); |
930 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 959 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
931 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
932 | 960 | ||
933 | return 0; | 961 | return 0; |
934 | } | 962 | } |
935 | 963 | ||
936 | static int sta32x_reg_is_volatile(struct snd_soc_codec *codec, | 964 | static bool sta32x_reg_is_volatile(struct device *dev, unsigned int reg) |
937 | unsigned int reg) | ||
938 | { | 965 | { |
939 | switch (reg) { | 966 | switch (reg) { |
940 | case STA32X_CONFA ... STA32X_L2ATRT: | 967 | case STA32X_CONFA ... STA32X_L2ATRT: |
@@ -949,10 +976,6 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
949 | .remove = sta32x_remove, | 976 | .remove = sta32x_remove, |
950 | .suspend = sta32x_suspend, | 977 | .suspend = sta32x_suspend, |
951 | .resume = sta32x_resume, | 978 | .resume = sta32x_resume, |
952 | .reg_cache_size = STA32X_REGISTER_COUNT, | ||
953 | .reg_word_size = sizeof(u8), | ||
954 | .reg_cache_default = sta32x_regs, | ||
955 | .volatile_register = sta32x_reg_is_volatile, | ||
956 | .set_bias_level = sta32x_set_bias_level, | 979 | .set_bias_level = sta32x_set_bias_level, |
957 | .controls = sta32x_snd_controls, | 980 | .controls = sta32x_snd_controls, |
958 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), | 981 | .num_controls = ARRAY_SIZE(sta32x_snd_controls), |
@@ -962,17 +985,45 @@ static const struct snd_soc_codec_driver sta32x_codec = { | |||
962 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), | 985 | .num_dapm_routes = ARRAY_SIZE(sta32x_dapm_routes), |
963 | }; | 986 | }; |
964 | 987 | ||
988 | static const struct regmap_config sta32x_regmap = { | ||
989 | .reg_bits = 8, | ||
990 | .val_bits = 8, | ||
991 | .max_register = STA32X_FDRC2, | ||
992 | .reg_defaults = sta32x_regs, | ||
993 | .num_reg_defaults = ARRAY_SIZE(sta32x_regs), | ||
994 | .cache_type = REGCACHE_RBTREE, | ||
995 | .volatile_reg = sta32x_reg_is_volatile, | ||
996 | }; | ||
997 | |||
965 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | 998 | static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, |
966 | const struct i2c_device_id *id) | 999 | const struct i2c_device_id *id) |
967 | { | 1000 | { |
968 | struct sta32x_priv *sta32x; | 1001 | struct sta32x_priv *sta32x; |
969 | int ret; | 1002 | int ret, i; |
970 | 1003 | ||
971 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), | 1004 | sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv), |
972 | GFP_KERNEL); | 1005 | GFP_KERNEL); |
973 | if (!sta32x) | 1006 | if (!sta32x) |
974 | return -ENOMEM; | 1007 | return -ENOMEM; |
975 | 1008 | ||
1009 | /* regulators */ | ||
1010 | for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++) | ||
1011 | sta32x->supplies[i].supply = sta32x_supply_names[i]; | ||
1012 | |||
1013 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(sta32x->supplies), | ||
1014 | sta32x->supplies); | ||
1015 | if (ret != 0) { | ||
1016 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
1017 | return ret; | ||
1018 | } | ||
1019 | |||
1020 | sta32x->regmap = devm_regmap_init_i2c(i2c, &sta32x_regmap); | ||
1021 | if (IS_ERR(sta32x->regmap)) { | ||
1022 | ret = PTR_ERR(sta32x->regmap); | ||
1023 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | ||
1024 | return ret; | ||
1025 | } | ||
1026 | |||
976 | i2c_set_clientdata(i2c, sta32x); | 1027 | i2c_set_clientdata(i2c, sta32x); |
977 | 1028 | ||
978 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); | 1029 | ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1); |
@@ -1006,17 +1057,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
1006 | .id_table = sta32x_i2c_id, | 1057 | .id_table = sta32x_i2c_id, |
1007 | }; | 1058 | }; |
1008 | 1059 | ||
1009 | static int __init sta32x_init(void) | 1060 | module_i2c_driver(sta32x_i2c_driver); |
1010 | { | ||
1011 | return i2c_add_driver(&sta32x_i2c_driver); | ||
1012 | } | ||
1013 | module_init(sta32x_init); | ||
1014 | |||
1015 | static void __exit sta32x_exit(void) | ||
1016 | { | ||
1017 | i2c_del_driver(&sta32x_i2c_driver); | ||
1018 | } | ||
1019 | module_exit(sta32x_exit); | ||
1020 | 1061 | ||
1021 | MODULE_DESCRIPTION("ASoC STA32X driver"); | 1062 | MODULE_DESCRIPTION("ASoC STA32X driver"); |
1022 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | 1063 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); |