diff options
Diffstat (limited to 'sound/soc/codecs/wm8580.c')
-rw-r--r-- | sound/soc/codecs/wm8580.c | 149 |
1 files changed, 105 insertions, 44 deletions
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 7c68226376e4..5e9c40fa7eb2 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * wm8580.c -- WM8580 ALSA Soc Audio driver | 2 | * wm8580.c -- WM8580 ALSA Soc Audio driver |
3 | * | 3 | * |
4 | * Copyright 2008-11 Wolfson Microelectronics PLC. | 4 | * Copyright 2008-12 Wolfson Microelectronics PLC. |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify it | 6 | * This program is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License as published by the | 7 | * under the terms of the GNU General Public License as published by the |
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
24 | #include <linux/pm.h> | 24 | #include <linux/pm.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/regmap.h> | ||
26 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
28 | #include <linux/of_device.h> | 29 | #include <linux/of_device.h> |
@@ -157,23 +158,72 @@ | |||
157 | * We can't read the WM8580 register space when we | 158 | * We can't read the WM8580 register space when we |
158 | * are using 2 wire for device control, so we cache them instead. | 159 | * are using 2 wire for device control, so we cache them instead. |
159 | */ | 160 | */ |
160 | static const u16 wm8580_reg[] = { | 161 | static const struct reg_default wm8580_reg_defaults[] = { |
161 | 0x0121, 0x017e, 0x007d, 0x0014, /*R3*/ | 162 | { 0, 0x0121 }, |
162 | 0x0121, 0x017e, 0x007d, 0x0194, /*R7*/ | 163 | { 1, 0x017e }, |
163 | 0x0010, 0x0002, 0x0002, 0x00c2, /*R11*/ | 164 | { 2, 0x007d }, |
164 | 0x0182, 0x0082, 0x000a, 0x0024, /*R15*/ | 165 | { 3, 0x0014 }, |
165 | 0x0009, 0x0000, 0x00ff, 0x0000, /*R19*/ | 166 | { 4, 0x0121 }, |
166 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R23*/ | 167 | { 5, 0x017e }, |
167 | 0x00ff, 0x00ff, 0x00ff, 0x00ff, /*R27*/ | 168 | { 6, 0x007d }, |
168 | 0x01f0, 0x0040, 0x0000, 0x0000, /*R31(0x1F)*/ | 169 | { 7, 0x0194 }, |
169 | 0x0000, 0x0000, 0x0031, 0x000b, /*R35*/ | 170 | { 8, 0x0010 }, |
170 | 0x0039, 0x0000, 0x0010, 0x0032, /*R39*/ | 171 | { 9, 0x0002 }, |
171 | 0x0054, 0x0076, 0x0098, 0x0000, /*R43(0x2B)*/ | 172 | { 10, 0x0002 }, |
172 | 0x0000, 0x0000, 0x0000, 0x0000, /*R47*/ | 173 | { 11, 0x00c2 }, |
173 | 0x0000, 0x0000, 0x005e, 0x003e, /*R51(0x33)*/ | 174 | { 12, 0x0182 }, |
174 | 0x0000, 0x0000 /*R53*/ | 175 | { 13, 0x0082 }, |
176 | { 14, 0x000a }, | ||
177 | { 15, 0x0024 }, | ||
178 | { 16, 0x0009 }, | ||
179 | { 17, 0x0000 }, | ||
180 | { 18, 0x00ff }, | ||
181 | { 19, 0x0000 }, | ||
182 | { 20, 0x00ff }, | ||
183 | { 21, 0x00ff }, | ||
184 | { 22, 0x00ff }, | ||
185 | { 23, 0x00ff }, | ||
186 | { 24, 0x00ff }, | ||
187 | { 25, 0x00ff }, | ||
188 | { 26, 0x00ff }, | ||
189 | { 27, 0x00ff }, | ||
190 | { 28, 0x01f0 }, | ||
191 | { 29, 0x0040 }, | ||
192 | { 30, 0x0000 }, | ||
193 | { 31, 0x0000 }, | ||
194 | { 32, 0x0000 }, | ||
195 | { 33, 0x0000 }, | ||
196 | { 34, 0x0031 }, | ||
197 | { 35, 0x000b }, | ||
198 | { 36, 0x0039 }, | ||
199 | { 37, 0x0000 }, | ||
200 | { 38, 0x0010 }, | ||
201 | { 39, 0x0032 }, | ||
202 | { 40, 0x0054 }, | ||
203 | { 41, 0x0076 }, | ||
204 | { 42, 0x0098 }, | ||
205 | { 43, 0x0000 }, | ||
206 | { 44, 0x0000 }, | ||
207 | { 45, 0x0000 }, | ||
208 | { 46, 0x0000 }, | ||
209 | { 47, 0x0000 }, | ||
210 | { 48, 0x0000 }, | ||
211 | { 49, 0x0000 }, | ||
212 | { 50, 0x005e }, | ||
213 | { 51, 0x003e }, | ||
214 | { 52, 0x0000 }, | ||
175 | }; | 215 | }; |
176 | 216 | ||
217 | static bool wm8580_volatile(struct device *dev, unsigned int reg) | ||
218 | { | ||
219 | switch (reg) { | ||
220 | case WM8580_RESET: | ||
221 | return true; | ||
222 | default: | ||
223 | return false; | ||
224 | } | ||
225 | } | ||
226 | |||
177 | struct pll_state { | 227 | struct pll_state { |
178 | unsigned int in; | 228 | unsigned int in; |
179 | unsigned int out; | 229 | unsigned int out; |
@@ -188,7 +238,7 @@ static const char *wm8580_supply_names[WM8580_NUM_SUPPLIES] = { | |||
188 | 238 | ||
189 | /* codec private data */ | 239 | /* codec private data */ |
190 | struct wm8580_priv { | 240 | struct wm8580_priv { |
191 | enum snd_soc_control_type control_type; | 241 | struct regmap *regmap; |
192 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; | 242 | struct regulator_bulk_data supplies[WM8580_NUM_SUPPLIES]; |
193 | struct pll_state a; | 243 | struct pll_state a; |
194 | struct pll_state b; | 244 | struct pll_state b; |
@@ -203,14 +253,16 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol, | |||
203 | struct soc_mixer_control *mc = | 253 | struct soc_mixer_control *mc = |
204 | (struct soc_mixer_control *)kcontrol->private_value; | 254 | (struct soc_mixer_control *)kcontrol->private_value; |
205 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 255 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
206 | u16 *reg_cache = codec->reg_cache; | 256 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
207 | unsigned int reg = mc->reg; | 257 | unsigned int reg = mc->reg; |
208 | unsigned int reg2 = mc->rreg; | 258 | unsigned int reg2 = mc->rreg; |
209 | int ret; | 259 | int ret; |
210 | 260 | ||
211 | /* Clear the register cache so we write without VU set */ | 261 | /* Clear the register cache VU so we write without VU set */ |
212 | reg_cache[reg] = 0; | 262 | regcache_cache_only(wm8580->regmap, true); |
213 | reg_cache[reg2] = 0; | 263 | regmap_update_bits(wm8580->regmap, reg, 0x100, 0x000); |
264 | regmap_update_bits(wm8580->regmap, reg2, 0x100, 0x000); | ||
265 | regcache_cache_only(wm8580->regmap, false); | ||
214 | 266 | ||
215 | ret = snd_soc_put_volsw(kcontrol, ucontrol); | 267 | ret = snd_soc_put_volsw(kcontrol, ucontrol); |
216 | if (ret < 0) | 268 | if (ret < 0) |
@@ -815,24 +867,14 @@ static struct snd_soc_dai_driver wm8580_dai[] = { | |||
815 | static int wm8580_probe(struct snd_soc_codec *codec) | 867 | static int wm8580_probe(struct snd_soc_codec *codec) |
816 | { | 868 | { |
817 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); | 869 | struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec); |
818 | int ret = 0,i; | 870 | int ret = 0; |
819 | 871 | ||
820 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8580->control_type); | 872 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
821 | if (ret < 0) { | 873 | if (ret < 0) { |
822 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 874 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
823 | return ret; | 875 | return ret; |
824 | } | 876 | } |
825 | 877 | ||
826 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
827 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
828 | |||
829 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8580->supplies), | ||
830 | wm8580->supplies); | ||
831 | if (ret != 0) { | ||
832 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
833 | return ret; | ||
834 | } | ||
835 | |||
836 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), | 878 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8580->supplies), |
837 | wm8580->supplies); | 879 | wm8580->supplies); |
838 | if (ret != 0) { | 880 | if (ret != 0) { |
@@ -854,7 +896,6 @@ static int wm8580_probe(struct snd_soc_codec *codec) | |||
854 | err_regulator_enable: | 896 | err_regulator_enable: |
855 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 897 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
856 | err_regulator_get: | 898 | err_regulator_get: |
857 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
858 | return ret; | 899 | return ret; |
859 | } | 900 | } |
860 | 901 | ||
@@ -866,7 +907,6 @@ static int wm8580_remove(struct snd_soc_codec *codec) | |||
866 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); | 907 | wm8580_set_bias_level(codec, SND_SOC_BIAS_OFF); |
867 | 908 | ||
868 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | 909 | regulator_bulk_disable(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); |
869 | regulator_bulk_free(ARRAY_SIZE(wm8580->supplies), wm8580->supplies); | ||
870 | 910 | ||
871 | return 0; | 911 | return 0; |
872 | } | 912 | } |
@@ -875,9 +915,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
875 | .probe = wm8580_probe, | 915 | .probe = wm8580_probe, |
876 | .remove = wm8580_remove, | 916 | .remove = wm8580_remove, |
877 | .set_bias_level = wm8580_set_bias_level, | 917 | .set_bias_level = wm8580_set_bias_level, |
878 | .reg_cache_size = ARRAY_SIZE(wm8580_reg), | ||
879 | .reg_word_size = sizeof(u16), | ||
880 | .reg_cache_default = wm8580_reg, | ||
881 | 918 | ||
882 | .controls = wm8580_snd_controls, | 919 | .controls = wm8580_snd_controls, |
883 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), | 920 | .num_controls = ARRAY_SIZE(wm8580_snd_controls), |
@@ -892,31 +929,55 @@ static const struct of_device_id wm8580_of_match[] = { | |||
892 | { }, | 929 | { }, |
893 | }; | 930 | }; |
894 | 931 | ||
932 | static const struct regmap_config wm8580_regmap = { | ||
933 | .reg_bits = 7, | ||
934 | .val_bits = 9, | ||
935 | .max_register = WM8580_MAX_REGISTER, | ||
936 | |||
937 | .reg_defaults = wm8580_reg_defaults, | ||
938 | .num_reg_defaults = ARRAY_SIZE(wm8580_reg_defaults), | ||
939 | .cache_type = REGCACHE_RBTREE, | ||
940 | |||
941 | .volatile_reg = wm8580_volatile, | ||
942 | }; | ||
943 | |||
895 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 944 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
896 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 945 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
897 | const struct i2c_device_id *id) | 946 | const struct i2c_device_id *id) |
898 | { | 947 | { |
899 | struct wm8580_priv *wm8580; | 948 | struct wm8580_priv *wm8580; |
900 | int ret; | 949 | int ret, i; |
901 | 950 | ||
902 | wm8580 = kzalloc(sizeof(struct wm8580_priv), GFP_KERNEL); | 951 | wm8580 = devm_kzalloc(&i2c->dev, sizeof(struct wm8580_priv), |
952 | GFP_KERNEL); | ||
903 | if (wm8580 == NULL) | 953 | if (wm8580 == NULL) |
904 | return -ENOMEM; | 954 | return -ENOMEM; |
905 | 955 | ||
956 | wm8580->regmap = devm_regmap_init_i2c(i2c, &wm8580_regmap); | ||
957 | if (IS_ERR(wm8580->regmap)) | ||
958 | return PTR_ERR(wm8580->regmap); | ||
959 | |||
960 | for (i = 0; i < ARRAY_SIZE(wm8580->supplies); i++) | ||
961 | wm8580->supplies[i].supply = wm8580_supply_names[i]; | ||
962 | |||
963 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8580->supplies), | ||
964 | wm8580->supplies); | ||
965 | if (ret != 0) { | ||
966 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
967 | return ret; | ||
968 | } | ||
969 | |||
906 | i2c_set_clientdata(i2c, wm8580); | 970 | i2c_set_clientdata(i2c, wm8580); |
907 | wm8580->control_type = SND_SOC_I2C; | ||
908 | 971 | ||
909 | ret = snd_soc_register_codec(&i2c->dev, | 972 | ret = snd_soc_register_codec(&i2c->dev, |
910 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); | 973 | &soc_codec_dev_wm8580, wm8580_dai, ARRAY_SIZE(wm8580_dai)); |
911 | if (ret < 0) | 974 | |
912 | kfree(wm8580); | ||
913 | return ret; | 975 | return ret; |
914 | } | 976 | } |
915 | 977 | ||
916 | static int wm8580_i2c_remove(struct i2c_client *client) | 978 | static int wm8580_i2c_remove(struct i2c_client *client) |
917 | { | 979 | { |
918 | snd_soc_unregister_codec(&client->dev); | 980 | snd_soc_unregister_codec(&client->dev); |
919 | kfree(i2c_get_clientdata(client)); | ||
920 | return 0; | 981 | return 0; |
921 | } | 982 | } |
922 | 983 | ||