diff options
Diffstat (limited to 'sound/soc/codecs')
50 files changed, 3222 insertions, 994 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b92759a39361..3a847828932a 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -44,6 +44,7 @@ config SND_SOC_ALL_CODECS | |||
44 | select SND_SOC_LM4857 if I2C | 44 | select SND_SOC_LM4857 if I2C |
45 | select SND_SOC_LM49453 if I2C | 45 | select SND_SOC_LM49453 if I2C |
46 | select SND_SOC_MAX98088 if I2C | 46 | select SND_SOC_MAX98088 if I2C |
47 | select SND_SOC_MAX98090 if I2C | ||
47 | select SND_SOC_MAX98095 if I2C | 48 | select SND_SOC_MAX98095 if I2C |
48 | select SND_SOC_MAX9850 if I2C | 49 | select SND_SOC_MAX9850 if I2C |
49 | select SND_SOC_MAX9768 if I2C | 50 | select SND_SOC_MAX9768 if I2C |
@@ -54,6 +55,7 @@ config SND_SOC_ALL_CODECS | |||
54 | select SND_SOC_PCM3008 | 55 | select SND_SOC_PCM3008 |
55 | select SND_SOC_RT5631 if I2C | 56 | select SND_SOC_RT5631 if I2C |
56 | select SND_SOC_SGTL5000 if I2C | 57 | select SND_SOC_SGTL5000 if I2C |
58 | select SND_SOC_SI476X if MFD_SI476X_CORE | ||
57 | select SND_SOC_SN95031 if INTEL_SCU_IPC | 59 | select SND_SOC_SN95031 if INTEL_SCU_IPC |
58 | select SND_SOC_SPDIF | 60 | select SND_SOC_SPDIF |
59 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI | 61 | select SND_SOC_SSM2602 if SND_SOC_I2C_AND_SPI |
@@ -146,6 +148,13 @@ config SND_SOC_WM_HUBS | |||
146 | default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y | 148 | default y if SND_SOC_WM8993=y || SND_SOC_WM8994=y |
147 | default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m | 149 | default m if SND_SOC_WM8993=m || SND_SOC_WM8994=m |
148 | 150 | ||
151 | config SND_SOC_WM_ADSP | ||
152 | tristate | ||
153 | default y if SND_SOC_WM5102=y | ||
154 | default y if SND_SOC_WM2200=y | ||
155 | default m if SND_SOC_WM5102=m | ||
156 | default m if SND_SOC_WM2200=m | ||
157 | |||
149 | config SND_SOC_AB8500_CODEC | 158 | config SND_SOC_AB8500_CODEC |
150 | tristate | 159 | tristate |
151 | 160 | ||
@@ -229,6 +238,7 @@ config SND_SOC_CX20442 | |||
229 | tristate | 238 | tristate |
230 | 239 | ||
231 | config SND_SOC_JZ4740_CODEC | 240 | config SND_SOC_JZ4740_CODEC |
241 | select REGMAP_MMIO | ||
232 | tristate | 242 | tristate |
233 | 243 | ||
234 | config SND_SOC_L3 | 244 | config SND_SOC_L3 |
@@ -258,6 +268,9 @@ config SND_SOC_LM49453 | |||
258 | config SND_SOC_MAX98088 | 268 | config SND_SOC_MAX98088 |
259 | tristate | 269 | tristate |
260 | 270 | ||
271 | config SND_SOC_MAX98090 | ||
272 | tristate | ||
273 | |||
261 | config SND_SOC_MAX98095 | 274 | config SND_SOC_MAX98095 |
262 | tristate | 275 | tristate |
263 | 276 | ||
@@ -277,6 +290,9 @@ config SND_SOC_RT5631 | |||
277 | config SND_SOC_SGTL5000 | 290 | config SND_SOC_SGTL5000 |
278 | tristate | 291 | tristate |
279 | 292 | ||
293 | config SND_SOC_SI476X | ||
294 | tristate | ||
295 | |||
280 | config SND_SOC_SIGMADSP | 296 | config SND_SOC_SIGMADSP |
281 | tristate | 297 | tristate |
282 | select CRC32 | 298 | select CRC32 |
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 9bd4d95aab4f..f6e8e36cceb7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -34,6 +34,7 @@ snd-soc-lm4857-objs := lm4857.o | |||
34 | snd-soc-lm49453-objs := lm49453.o | 34 | snd-soc-lm49453-objs := lm49453.o |
35 | snd-soc-max9768-objs := max9768.o | 35 | snd-soc-max9768-objs := max9768.o |
36 | snd-soc-max98088-objs := max98088.o | 36 | snd-soc-max98088-objs := max98088.o |
37 | snd-soc-max98090-objs := max98090.o | ||
37 | snd-soc-max98095-objs := max98095.o | 38 | snd-soc-max98095-objs := max98095.o |
38 | snd-soc-max9850-objs := max9850.o | 39 | snd-soc-max9850-objs := max9850.o |
39 | snd-soc-mc13783-objs := mc13783.o | 40 | snd-soc-mc13783-objs := mc13783.o |
@@ -45,6 +46,7 @@ snd-soc-sgtl5000-objs := sgtl5000.o | |||
45 | snd-soc-alc5623-objs := alc5623.o | 46 | snd-soc-alc5623-objs := alc5623.o |
46 | snd-soc-alc5632-objs := alc5632.o | 47 | snd-soc-alc5632-objs := alc5632.o |
47 | snd-soc-sigmadsp-objs := sigmadsp.o | 48 | snd-soc-sigmadsp-objs := sigmadsp.o |
49 | snd-soc-si476x-objs := si476x.o | ||
48 | snd-soc-sn95031-objs := sn95031.o | 50 | snd-soc-sn95031-objs := sn95031.o |
49 | snd-soc-spdif-tx-objs := spdif_transciever.o | 51 | snd-soc-spdif-tx-objs := spdif_transciever.o |
50 | snd-soc-spdif-rx-objs := spdif_receiver.o | 52 | snd-soc-spdif-rx-objs := spdif_receiver.o |
@@ -62,6 +64,7 @@ snd-soc-twl6040-objs := twl6040.o | |||
62 | snd-soc-uda134x-objs := uda134x.o | 64 | snd-soc-uda134x-objs := uda134x.o |
63 | snd-soc-uda1380-objs := uda1380.o | 65 | snd-soc-uda1380-objs := uda1380.o |
64 | snd-soc-wl1273-objs := wl1273.o | 66 | snd-soc-wl1273-objs := wl1273.o |
67 | snd-soc-wm-adsp-objs := wm_adsp.o | ||
65 | snd-soc-wm0010-objs := wm0010.o | 68 | snd-soc-wm0010-objs := wm0010.o |
66 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o | 69 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o |
67 | snd-soc-wm2000-objs := wm2000.o | 70 | snd-soc-wm2000-objs := wm2000.o |
@@ -155,6 +158,7 @@ obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o | |||
155 | obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o | 158 | obj-$(CONFIG_SND_SOC_LM49453) += snd-soc-lm49453.o |
156 | obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o | 159 | obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o |
157 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 160 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
161 | obj-$(CONFIG_SND_SOC_MAX98090) += snd-soc-max98090.o | ||
158 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | 162 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o |
159 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 163 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
160 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o | 164 | obj-$(CONFIG_SND_SOC_MC13783) += snd-soc-mc13783.o |
@@ -164,6 +168,7 @@ obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o | |||
164 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o | 168 | obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o |
165 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o | 169 | obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o |
166 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o | 170 | obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o |
171 | obj-$(CONFIG_SND_SOC_SI476X) += snd-soc-si476x.o | ||
167 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o | 172 | obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o |
168 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o | 173 | obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif-rx.o snd-soc-spdif-tx.o |
169 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o | 174 | obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o |
@@ -229,6 +234,7 @@ obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o | |||
229 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o | 234 | obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o |
230 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o | 235 | obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o |
231 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o | 236 | obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o |
237 | obj-$(CONFIG_SND_SOC_WM_ADSP) += snd-soc-wm-adsp.o | ||
232 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o | 238 | obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o |
233 | 239 | ||
234 | # Amp | 240 | # Amp |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index af547490b4f7..4d96090db662 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -2356,7 +2356,7 @@ static int ab8500_codec_set_dai_tdm_slot(struct snd_soc_dai *dai, | |||
2356 | return 0; | 2356 | return 0; |
2357 | } | 2357 | } |
2358 | 2358 | ||
2359 | struct snd_soc_dai_driver ab8500_codec_dai[] = { | 2359 | static struct snd_soc_dai_driver ab8500_codec_dai[] = { |
2360 | { | 2360 | { |
2361 | .name = "ab8500-codec-dai.0", | 2361 | .name = "ab8500-codec-dai.0", |
2362 | .id = 0, | 2362 | .id = 0, |
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c index 31d4483245d0..4b11b82b2273 100644 --- a/sound/soc/codecs/ak4104.c +++ b/sound/soc/codecs/ak4104.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <sound/soc.h> | 15 | #include <sound/soc.h> |
16 | #include <sound/initval.h> | 16 | #include <sound/initval.h> |
17 | #include <linux/spi/spi.h> | 17 | #include <linux/spi/spi.h> |
18 | #include <linux/of_device.h> | ||
19 | #include <linux/of_gpio.h> | ||
18 | #include <sound/asoundef.h> | 20 | #include <sound/asoundef.h> |
19 | 21 | ||
20 | /* AK4104 registers addresses */ | 22 | /* AK4104 registers addresses */ |
@@ -98,14 +100,32 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream, | |||
98 | val = 0; | 100 | val = 0; |
99 | 101 | ||
100 | switch (params_rate(params)) { | 102 | switch (params_rate(params)) { |
103 | case 22050: | ||
104 | val |= IEC958_AES3_CON_FS_22050; | ||
105 | break; | ||
106 | case 24000: | ||
107 | val |= IEC958_AES3_CON_FS_24000; | ||
108 | break; | ||
109 | case 32000: | ||
110 | val |= IEC958_AES3_CON_FS_32000; | ||
111 | break; | ||
101 | case 44100: | 112 | case 44100: |
102 | val |= IEC958_AES3_CON_FS_44100; | 113 | val |= IEC958_AES3_CON_FS_44100; |
103 | break; | 114 | break; |
104 | case 48000: | 115 | case 48000: |
105 | val |= IEC958_AES3_CON_FS_48000; | 116 | val |= IEC958_AES3_CON_FS_48000; |
106 | break; | 117 | break; |
107 | case 32000: | 118 | case 88200: |
108 | val |= IEC958_AES3_CON_FS_32000; | 119 | val |= IEC958_AES3_CON_FS_88200; |
120 | break; | ||
121 | case 96000: | ||
122 | val |= IEC958_AES3_CON_FS_96000; | ||
123 | break; | ||
124 | case 176400: | ||
125 | val |= IEC958_AES3_CON_FS_176400; | ||
126 | break; | ||
127 | case 192000: | ||
128 | val |= IEC958_AES3_CON_FS_192000; | ||
109 | break; | 129 | break; |
110 | default: | 130 | default: |
111 | dev_err(codec->dev, "unsupported sampling rate\n"); | 131 | dev_err(codec->dev, "unsupported sampling rate\n"); |
@@ -186,6 +206,7 @@ static const struct regmap_config ak4104_regmap = { | |||
186 | 206 | ||
187 | static int ak4104_spi_probe(struct spi_device *spi) | 207 | static int ak4104_spi_probe(struct spi_device *spi) |
188 | { | 208 | { |
209 | struct device_node *np = spi->dev.of_node; | ||
189 | struct ak4104_private *ak4104; | 210 | struct ak4104_private *ak4104; |
190 | unsigned int val; | 211 | unsigned int val; |
191 | int ret; | 212 | int ret; |
@@ -201,49 +222,59 @@ static int ak4104_spi_probe(struct spi_device *spi) | |||
201 | if (ak4104 == NULL) | 222 | if (ak4104 == NULL) |
202 | return -ENOMEM; | 223 | return -ENOMEM; |
203 | 224 | ||
204 | ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap); | 225 | ak4104->regmap = devm_regmap_init_spi(spi, &ak4104_regmap); |
205 | if (IS_ERR(ak4104->regmap)) { | 226 | if (IS_ERR(ak4104->regmap)) { |
206 | ret = PTR_ERR(ak4104->regmap); | 227 | ret = PTR_ERR(ak4104->regmap); |
207 | return ret; | 228 | return ret; |
208 | } | 229 | } |
209 | 230 | ||
231 | if (np) { | ||
232 | enum of_gpio_flags flags; | ||
233 | int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); | ||
234 | |||
235 | if (gpio_is_valid(gpio)) { | ||
236 | ret = devm_gpio_request_one(&spi->dev, gpio, | ||
237 | flags & OF_GPIO_ACTIVE_LOW ? | ||
238 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | ||
239 | "ak4104 reset"); | ||
240 | if (ret < 0) | ||
241 | return ret; | ||
242 | } | ||
243 | } | ||
244 | |||
210 | /* read the 'reserved' register - according to the datasheet, it | 245 | /* read the 'reserved' register - according to the datasheet, it |
211 | * should contain 0x5b. Not a good way to verify the presence of | 246 | * should contain 0x5b. Not a good way to verify the presence of |
212 | * the device, but there is no hardware ID register. */ | 247 | * the device, but there is no hardware ID register. */ |
213 | ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val); | 248 | ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val); |
214 | if (ret != 0) | 249 | if (ret != 0) |
215 | goto err; | 250 | return ret; |
216 | if (val != AK4104_RESERVED_VAL) { | 251 | if (val != AK4104_RESERVED_VAL) |
217 | ret = -ENODEV; | 252 | return -ENODEV; |
218 | goto err; | ||
219 | } | ||
220 | 253 | ||
221 | spi_set_drvdata(spi, ak4104); | 254 | spi_set_drvdata(spi, ak4104); |
222 | 255 | ||
223 | ret = snd_soc_register_codec(&spi->dev, | 256 | ret = snd_soc_register_codec(&spi->dev, |
224 | &soc_codec_device_ak4104, &ak4104_dai, 1); | 257 | &soc_codec_device_ak4104, &ak4104_dai, 1); |
225 | if (ret != 0) | ||
226 | goto err; | ||
227 | |||
228 | return 0; | ||
229 | |||
230 | err: | ||
231 | regmap_exit(ak4104->regmap); | ||
232 | return ret; | 258 | return ret; |
233 | } | 259 | } |
234 | 260 | ||
235 | static int __devexit ak4104_spi_remove(struct spi_device *spi) | 261 | static int __devexit ak4104_spi_remove(struct spi_device *spi) |
236 | { | 262 | { |
237 | struct ak4104_private *ak4101 = spi_get_drvdata(spi); | ||
238 | regmap_exit(ak4101->regmap); | ||
239 | snd_soc_unregister_codec(&spi->dev); | 263 | snd_soc_unregister_codec(&spi->dev); |
240 | return 0; | 264 | return 0; |
241 | } | 265 | } |
242 | 266 | ||
267 | static const struct of_device_id ak4104_of_match[] = { | ||
268 | { .compatible = "asahi-kasei,ak4104", }, | ||
269 | { } | ||
270 | }; | ||
271 | MODULE_DEVICE_TABLE(of, ak4104_of_match); | ||
272 | |||
243 | static struct spi_driver ak4104_spi_driver = { | 273 | static struct spi_driver ak4104_spi_driver = { |
244 | .driver = { | 274 | .driver = { |
245 | .name = DRV_NAME, | 275 | .name = DRV_NAME, |
246 | .owner = THIS_MODULE, | 276 | .owner = THIS_MODULE, |
277 | .of_match_table = ak4104_of_match, | ||
247 | }, | 278 | }, |
248 | .probe = ak4104_spi_probe, | 279 | .probe = ak4104_spi_probe, |
249 | .remove = __devexit_p(ak4104_spi_remove), | 280 | .remove = __devexit_p(ak4104_spi_remove), |
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c index 618fdc30f73e..fc5581063b2d 100644 --- a/sound/soc/codecs/ak4535.c +++ b/sound/soc/codecs/ak4535.c | |||
@@ -447,7 +447,7 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, | |||
447 | if (ak4535 == NULL) | 447 | if (ak4535 == NULL) |
448 | return -ENOMEM; | 448 | return -ENOMEM; |
449 | 449 | ||
450 | ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap); | 450 | ak4535->regmap = devm_regmap_init_i2c(i2c, &ak4535_regmap); |
451 | if (IS_ERR(ak4535->regmap)) { | 451 | if (IS_ERR(ak4535->regmap)) { |
452 | ret = PTR_ERR(ak4535->regmap); | 452 | ret = PTR_ERR(ak4535->regmap); |
453 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | 453 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); |
@@ -458,18 +458,13 @@ static __devinit int ak4535_i2c_probe(struct i2c_client *i2c, | |||
458 | 458 | ||
459 | ret = snd_soc_register_codec(&i2c->dev, | 459 | ret = snd_soc_register_codec(&i2c->dev, |
460 | &soc_codec_dev_ak4535, &ak4535_dai, 1); | 460 | &soc_codec_dev_ak4535, &ak4535_dai, 1); |
461 | if (ret != 0) | ||
462 | regmap_exit(ak4535->regmap); | ||
463 | 461 | ||
464 | return ret; | 462 | return ret; |
465 | } | 463 | } |
466 | 464 | ||
467 | static __devexit int ak4535_i2c_remove(struct i2c_client *client) | 465 | static __devexit int ak4535_i2c_remove(struct i2c_client *client) |
468 | { | 466 | { |
469 | struct ak4535_priv *ak4535 = i2c_get_clientdata(client); | ||
470 | |||
471 | snd_soc_unregister_codec(&client->dev); | 467 | snd_soc_unregister_codec(&client->dev); |
472 | regmap_exit(ak4535->regmap); | ||
473 | return 0; | 468 | return 0; |
474 | } | 469 | } |
475 | 470 | ||
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c index b3e24f289421..546466abb77f 100644 --- a/sound/soc/codecs/ak4642.c +++ b/sound/soc/codecs/ak4642.c | |||
@@ -194,12 +194,6 @@ static const struct snd_soc_dapm_route ak4642_intercon[] = { | |||
194 | {"LINEOUT Mixer", "DACL", "DAC"}, | 194 | {"LINEOUT Mixer", "DACL", "DAC"}, |
195 | }; | 195 | }; |
196 | 196 | ||
197 | /* codec private data */ | ||
198 | struct ak4642_priv { | ||
199 | unsigned int sysclk; | ||
200 | enum snd_soc_control_type control_type; | ||
201 | }; | ||
202 | |||
203 | /* | 197 | /* |
204 | * ak4642 register cache | 198 | * ak4642 register cache |
205 | */ | 199 | */ |
@@ -468,10 +462,9 @@ static int ak4642_resume(struct snd_soc_codec *codec) | |||
468 | 462 | ||
469 | static int ak4642_probe(struct snd_soc_codec *codec) | 463 | static int ak4642_probe(struct snd_soc_codec *codec) |
470 | { | 464 | { |
471 | struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec); | ||
472 | int ret; | 465 | int ret; |
473 | 466 | ||
474 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type); | 467 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); |
475 | if (ret < 0) { | 468 | if (ret < 0) { |
476 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 469 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
477 | return ret; | 470 | return ret; |
@@ -523,21 +516,9 @@ static struct snd_soc_codec_driver soc_codec_dev_ak4648 = { | |||
523 | static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, | 516 | static __devinit int ak4642_i2c_probe(struct i2c_client *i2c, |
524 | const struct i2c_device_id *id) | 517 | const struct i2c_device_id *id) |
525 | { | 518 | { |
526 | struct ak4642_priv *ak4642; | 519 | return snd_soc_register_codec(&i2c->dev, |
527 | int ret; | ||
528 | |||
529 | ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv), | ||
530 | GFP_KERNEL); | ||
531 | if (!ak4642) | ||
532 | return -ENOMEM; | ||
533 | |||
534 | i2c_set_clientdata(i2c, ak4642); | ||
535 | ak4642->control_type = SND_SOC_I2C; | ||
536 | |||
537 | ret = snd_soc_register_codec(&i2c->dev, | ||
538 | (struct snd_soc_codec_driver *)id->driver_data, | 520 | (struct snd_soc_codec_driver *)id->driver_data, |
539 | &ak4642_dai, 1); | 521 | &ak4642_dai, 1); |
540 | return ret; | ||
541 | } | 522 | } |
542 | 523 | ||
543 | static __devexit int ak4642_i2c_remove(struct i2c_client *client) | 524 | static __devexit int ak4642_i2c_remove(struct i2c_client *client) |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 054967d8bac2..adf397b9d0e6 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -226,6 +226,31 @@ EXPORT_SYMBOL_GPL(arizona_mixer_values); | |||
226 | const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); | 226 | const DECLARE_TLV_DB_SCALE(arizona_mixer_tlv, -3200, 100, 0); |
227 | EXPORT_SYMBOL_GPL(arizona_mixer_tlv); | 227 | EXPORT_SYMBOL_GPL(arizona_mixer_tlv); |
228 | 228 | ||
229 | static const char *arizona_vol_ramp_text[] = { | ||
230 | "0ms/6dB", "0.5ms/6dB", "1ms/6dB", "2ms/6dB", "4ms/6dB", "8ms/6dB", | ||
231 | "15ms/6dB", "30ms/6dB", | ||
232 | }; | ||
233 | |||
234 | const struct soc_enum arizona_in_vd_ramp = | ||
235 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | ||
236 | ARIZONA_IN_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | ||
237 | EXPORT_SYMBOL_GPL(arizona_in_vd_ramp); | ||
238 | |||
239 | const struct soc_enum arizona_in_vi_ramp = | ||
240 | SOC_ENUM_SINGLE(ARIZONA_INPUT_VOLUME_RAMP, | ||
241 | ARIZONA_IN_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | ||
242 | EXPORT_SYMBOL_GPL(arizona_in_vi_ramp); | ||
243 | |||
244 | const struct soc_enum arizona_out_vd_ramp = | ||
245 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | ||
246 | ARIZONA_OUT_VD_RAMP_SHIFT, 7, arizona_vol_ramp_text); | ||
247 | EXPORT_SYMBOL_GPL(arizona_out_vd_ramp); | ||
248 | |||
249 | const struct soc_enum arizona_out_vi_ramp = | ||
250 | SOC_ENUM_SINGLE(ARIZONA_OUTPUT_VOLUME_RAMP, | ||
251 | ARIZONA_OUT_VI_RAMP_SHIFT, 7, arizona_vol_ramp_text); | ||
252 | EXPORT_SYMBOL_GPL(arizona_out_vi_ramp); | ||
253 | |||
229 | static const char *arizona_lhpf_mode_text[] = { | 254 | static const char *arizona_lhpf_mode_text[] = { |
230 | "Low-pass", "High-pass" | 255 | "Low-pass", "High-pass" |
231 | }; | 256 | }; |
@@ -380,6 +405,18 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
380 | case 49152000: | 405 | case 49152000: |
381 | val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; | 406 | val |= 3 << ARIZONA_SYSCLK_FREQ_SHIFT; |
382 | break; | 407 | break; |
408 | case 67737600: | ||
409 | case 73728000: | ||
410 | val |= 4 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
411 | break; | ||
412 | case 90316800: | ||
413 | case 98304000: | ||
414 | val |= 5 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
415 | break; | ||
416 | case 135475200: | ||
417 | case 147456000: | ||
418 | val |= 6 << ARIZONA_SYSCLK_FREQ_SHIFT; | ||
419 | break; | ||
383 | default: | 420 | default: |
384 | return -EINVAL; | 421 | return -EINVAL; |
385 | } | 422 | } |
@@ -737,6 +774,9 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | |||
737 | return -EBUSY; | 774 | return -EBUSY; |
738 | } | 775 | } |
739 | 776 | ||
777 | dev_dbg(codec->dev, "Setting AIF%d to %s\n", dai->id + 1, | ||
778 | arizona_dai_clk_str(clk_id)); | ||
779 | |||
740 | memset(&routes, 0, sizeof(routes)); | 780 | memset(&routes, 0, sizeof(routes)); |
741 | routes[0].sink = dai->driver->capture.stream_name; | 781 | routes[0].sink = dai->driver->capture.stream_name; |
742 | routes[1].sink = dai->driver->playback.stream_name; | 782 | routes[1].sink = dai->driver->playback.stream_name; |
@@ -749,6 +789,8 @@ static int arizona_dai_set_sysclk(struct snd_soc_dai *dai, | |||
749 | routes[1].source = arizona_dai_clk_str(clk_id); | 789 | routes[1].source = arizona_dai_clk_str(clk_id); |
750 | snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); | 790 | snd_soc_dapm_add_routes(&codec->dapm, routes, ARRAY_SIZE(routes)); |
751 | 791 | ||
792 | dai_priv->clk = clk_id; | ||
793 | |||
752 | return snd_soc_dapm_sync(&codec->dapm); | 794 | return snd_soc_dapm_sync(&codec->dapm); |
753 | } | 795 | } |
754 | 796 | ||
@@ -925,6 +967,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
925 | bool ena; | 967 | bool ena; |
926 | int ret; | 968 | int ret; |
927 | 969 | ||
970 | if (fll->fref == Fref && fll->fout == Fout) | ||
971 | return 0; | ||
972 | |||
928 | ret = regmap_read(arizona->regmap, fll->base + 1, ®); | 973 | ret = regmap_read(arizona->regmap, fll->base + 1, ®); |
929 | if (ret != 0) { | 974 | if (ret != 0) { |
930 | arizona_fll_err(fll, "Failed to read current state: %d\n", | 975 | arizona_fll_err(fll, "Failed to read current state: %d\n", |
@@ -970,6 +1015,9 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
970 | if (ena) | 1015 | if (ena) |
971 | pm_runtime_put_autosuspend(arizona->dev); | 1016 | pm_runtime_put_autosuspend(arizona->dev); |
972 | 1017 | ||
1018 | fll->fref = Fref; | ||
1019 | fll->fout = Fout; | ||
1020 | |||
973 | return 0; | 1021 | return 0; |
974 | } | 1022 | } |
975 | 1023 | ||
@@ -998,10 +1046,13 @@ int arizona_set_fll(struct arizona_fll *fll, int source, | |||
998 | ARIZONA_FLL1_SYNC_ENA); | 1046 | ARIZONA_FLL1_SYNC_ENA); |
999 | 1047 | ||
1000 | ret = wait_for_completion_timeout(&fll->ok, | 1048 | ret = wait_for_completion_timeout(&fll->ok, |
1001 | msecs_to_jiffies(25)); | 1049 | msecs_to_jiffies(250)); |
1002 | if (ret == 0) | 1050 | if (ret == 0) |
1003 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); | 1051 | arizona_fll_warn(fll, "Timed out waiting for lock\n"); |
1004 | 1052 | ||
1053 | fll->fref = Fref; | ||
1054 | fll->fout = Fout; | ||
1055 | |||
1005 | return 0; | 1056 | return 0; |
1006 | } | 1057 | } |
1007 | EXPORT_SYMBOL_GPL(arizona_set_fll); | 1058 | EXPORT_SYMBOL_GPL(arizona_set_fll); |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 36ec64946120..41dae1ed3b71 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -17,6 +17,8 @@ | |||
17 | 17 | ||
18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | 19 | ||
20 | #include "wm_adsp.h" | ||
21 | |||
20 | #define ARIZONA_CLK_SYSCLK 1 | 22 | #define ARIZONA_CLK_SYSCLK 1 |
21 | #define ARIZONA_CLK_ASYNCCLK 2 | 23 | #define ARIZONA_CLK_ASYNCCLK 2 |
22 | #define ARIZONA_CLK_OPCLK 3 | 24 | #define ARIZONA_CLK_OPCLK 3 |
@@ -46,15 +48,18 @@ | |||
46 | #define ARIZONA_MIXER_VOL_SHIFT 1 | 48 | #define ARIZONA_MIXER_VOL_SHIFT 1 |
47 | #define ARIZONA_MIXER_VOL_WIDTH 7 | 49 | #define ARIZONA_MIXER_VOL_WIDTH 7 |
48 | 50 | ||
49 | #define ARIZONA_MAX_DAI 3 | 51 | #define ARIZONA_MAX_DAI 4 |
52 | #define ARIZONA_MAX_ADSP 4 | ||
50 | 53 | ||
51 | struct arizona; | 54 | struct arizona; |
55 | struct wm_adsp; | ||
52 | 56 | ||
53 | struct arizona_dai_priv { | 57 | struct arizona_dai_priv { |
54 | int clk; | 58 | int clk; |
55 | }; | 59 | }; |
56 | 60 | ||
57 | struct arizona_priv { | 61 | struct arizona_priv { |
62 | struct wm_adsp adsp[ARIZONA_MAX_ADSP]; | ||
58 | struct arizona *arizona; | 63 | struct arizona *arizona; |
59 | int sysclk; | 64 | int sysclk; |
60 | int asyncclk; | 65 | int asyncclk; |
@@ -89,19 +94,30 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
89 | const struct snd_kcontrol_new name##_mux = \ | 94 | const struct snd_kcontrol_new name##_mux = \ |
90 | SOC_DAPM_VALUE_ENUM("Route", name##_enum) | 95 | SOC_DAPM_VALUE_ENUM("Route", name##_enum) |
91 | 96 | ||
97 | #define ARIZONA_MUX_ENUMS(name, base_reg) \ | ||
98 | static ARIZONA_MUX_ENUM_DECL(name##_enum, base_reg); \ | ||
99 | static ARIZONA_MUX_CTL_DECL(name) | ||
100 | |||
92 | #define ARIZONA_MIXER_ENUMS(name, base_reg) \ | 101 | #define ARIZONA_MIXER_ENUMS(name, base_reg) \ |
93 | static ARIZONA_MUX_ENUM_DECL(name##_in1_enum, base_reg); \ | 102 | ARIZONA_MUX_ENUMS(name##_in1, base_reg); \ |
94 | static ARIZONA_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \ | 103 | ARIZONA_MUX_ENUMS(name##_in2, base_reg + 2); \ |
95 | static ARIZONA_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \ | 104 | ARIZONA_MUX_ENUMS(name##_in3, base_reg + 4); \ |
96 | static ARIZONA_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \ | 105 | ARIZONA_MUX_ENUMS(name##_in4, base_reg + 6) |
97 | static ARIZONA_MUX_CTL_DECL(name##_in1); \ | 106 | |
98 | static ARIZONA_MUX_CTL_DECL(name##_in2); \ | 107 | #define ARIZONA_DSP_AUX_ENUMS(name, base_reg) \ |
99 | static ARIZONA_MUX_CTL_DECL(name##_in3); \ | 108 | ARIZONA_MUX_ENUMS(name##_aux1, base_reg); \ |
100 | static ARIZONA_MUX_CTL_DECL(name##_in4) | 109 | ARIZONA_MUX_ENUMS(name##_aux2, base_reg + 8); \ |
110 | ARIZONA_MUX_ENUMS(name##_aux3, base_reg + 16); \ | ||
111 | ARIZONA_MUX_ENUMS(name##_aux4, base_reg + 24); \ | ||
112 | ARIZONA_MUX_ENUMS(name##_aux5, base_reg + 32); \ | ||
113 | ARIZONA_MUX_ENUMS(name##_aux6, base_reg + 40) | ||
101 | 114 | ||
102 | #define ARIZONA_MUX(name, ctrl) \ | 115 | #define ARIZONA_MUX(name, ctrl) \ |
103 | SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) | 116 | SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl) |
104 | 117 | ||
118 | #define ARIZONA_MUX_WIDGETS(name, name_str) \ | ||
119 | ARIZONA_MUX(name_str " Input", &name##_mux) | ||
120 | |||
105 | #define ARIZONA_MIXER_WIDGETS(name, name_str) \ | 121 | #define ARIZONA_MIXER_WIDGETS(name, name_str) \ |
106 | ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \ | 122 | ARIZONA_MUX(name_str " Input 1", &name##_in1_mux), \ |
107 | ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \ | 123 | ARIZONA_MUX(name_str " Input 2", &name##_in2_mux), \ |
@@ -109,6 +125,19 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
109 | ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \ | 125 | ARIZONA_MUX(name_str " Input 4", &name##_in4_mux), \ |
110 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) | 126 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) |
111 | 127 | ||
128 | #define ARIZONA_DSP_WIDGETS(name, name_str) \ | ||
129 | ARIZONA_MIXER_WIDGETS(name##L, name_str "L"), \ | ||
130 | ARIZONA_MIXER_WIDGETS(name##R, name_str "R"), \ | ||
131 | ARIZONA_MUX(name_str " Aux 1", &name##_aux1_mux), \ | ||
132 | ARIZONA_MUX(name_str " Aux 2", &name##_aux2_mux), \ | ||
133 | ARIZONA_MUX(name_str " Aux 3", &name##_aux3_mux), \ | ||
134 | ARIZONA_MUX(name_str " Aux 4", &name##_aux4_mux), \ | ||
135 | ARIZONA_MUX(name_str " Aux 5", &name##_aux5_mux), \ | ||
136 | ARIZONA_MUX(name_str " Aux 6", &name##_aux6_mux) | ||
137 | |||
138 | #define ARIZONA_MUX_ROUTES(name) \ | ||
139 | ARIZONA_MIXER_INPUT_ROUTES(name " Input") | ||
140 | |||
112 | #define ARIZONA_MIXER_ROUTES(widget, name) \ | 141 | #define ARIZONA_MIXER_ROUTES(widget, name) \ |
113 | { widget, NULL, name " Mixer" }, \ | 142 | { widget, NULL, name " Mixer" }, \ |
114 | { name " Mixer", NULL, name " Input 1" }, \ | 143 | { name " Mixer", NULL, name " Input 1" }, \ |
@@ -120,6 +149,28 @@ extern int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; | |||
120 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ | 149 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 3"), \ |
121 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") | 150 | ARIZONA_MIXER_INPUT_ROUTES(name " Input 4") |
122 | 151 | ||
152 | #define ARIZONA_DSP_ROUTES(name) \ | ||
153 | { name, NULL, name " Aux 1" }, \ | ||
154 | { name, NULL, name " Aux 2" }, \ | ||
155 | { name, NULL, name " Aux 3" }, \ | ||
156 | { name, NULL, name " Aux 4" }, \ | ||
157 | { name, NULL, name " Aux 5" }, \ | ||
158 | { name, NULL, name " Aux 6" }, \ | ||
159 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 1"), \ | ||
160 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 2"), \ | ||
161 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 3"), \ | ||
162 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 4"), \ | ||
163 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 5"), \ | ||
164 | ARIZONA_MIXER_INPUT_ROUTES(name " Aux 6"), \ | ||
165 | ARIZONA_MIXER_ROUTES(name, name "L"), \ | ||
166 | ARIZONA_MIXER_ROUTES(name, name "R") | ||
167 | |||
168 | extern const struct soc_enum arizona_in_vi_ramp; | ||
169 | extern const struct soc_enum arizona_in_vd_ramp; | ||
170 | |||
171 | extern const struct soc_enum arizona_out_vi_ramp; | ||
172 | extern const struct soc_enum arizona_out_vd_ramp; | ||
173 | |||
123 | extern const struct soc_enum arizona_lhpf1_mode; | 174 | extern const struct soc_enum arizona_lhpf1_mode; |
124 | extern const struct soc_enum arizona_lhpf2_mode; | 175 | extern const struct soc_enum arizona_lhpf2_mode; |
125 | extern const struct soc_enum arizona_lhpf3_mode; | 176 | extern const struct soc_enum arizona_lhpf3_mode; |
@@ -146,6 +197,8 @@ struct arizona_fll { | |||
146 | unsigned int vco_mult; | 197 | unsigned int vco_mult; |
147 | struct completion lock; | 198 | struct completion lock; |
148 | struct completion ok; | 199 | struct completion ok; |
200 | unsigned int fref; | ||
201 | unsigned int fout; | ||
149 | 202 | ||
150 | char lock_name[ARIZONA_FLL_NAME_LEN]; | 203 | char lock_name[ARIZONA_FLL_NAME_LEN]; |
151 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; | 204 | char clock_ok_name[ARIZONA_FLL_NAME_LEN]; |
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c index e3f0a7f3131e..6ad3878db8fc 100644 --- a/sound/soc/codecs/cs4271.c +++ b/sound/soc/codecs/cs4271.c | |||
@@ -474,15 +474,25 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
474 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; | 474 | struct cs4271_platform_data *cs4271plat = codec->dev->platform_data; |
475 | int ret; | 475 | int ret; |
476 | int gpio_nreset = -EINVAL; | 476 | int gpio_nreset = -EINVAL; |
477 | int amutec_eq_bmutec = 0; | ||
477 | 478 | ||
478 | #ifdef CONFIG_OF | 479 | #ifdef CONFIG_OF |
479 | if (of_match_device(cs4271_dt_ids, codec->dev)) | 480 | if (of_match_device(cs4271_dt_ids, codec->dev)) { |
480 | gpio_nreset = of_get_named_gpio(codec->dev->of_node, | 481 | gpio_nreset = of_get_named_gpio(codec->dev->of_node, |
481 | "reset-gpio", 0); | 482 | "reset-gpio", 0); |
483 | |||
484 | if (!of_get_property(codec->dev->of_node, | ||
485 | "cirrus,amutec-eq-bmutec", NULL)) | ||
486 | amutec_eq_bmutec = 1; | ||
487 | } | ||
482 | #endif | 488 | #endif |
483 | 489 | ||
484 | if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset)) | 490 | if (cs4271plat) { |
485 | gpio_nreset = cs4271plat->gpio_nreset; | 491 | if (gpio_is_valid(cs4271plat->gpio_nreset)) |
492 | gpio_nreset = cs4271plat->gpio_nreset; | ||
493 | |||
494 | amutec_eq_bmutec = cs4271plat->amutec_eq_bmutec; | ||
495 | } | ||
486 | 496 | ||
487 | if (gpio_nreset >= 0) | 497 | if (gpio_nreset >= 0) |
488 | if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) | 498 | if (devm_gpio_request(codec->dev, gpio_nreset, "CS4271 Reset")) |
@@ -528,6 +538,11 @@ static int cs4271_probe(struct snd_soc_codec *codec) | |||
528 | /* Power-up sequence requires 85 uS */ | 538 | /* Power-up sequence requires 85 uS */ |
529 | udelay(85); | 539 | udelay(85); |
530 | 540 | ||
541 | if (amutec_eq_bmutec) | ||
542 | snd_soc_update_bits(codec, CS4271_MODE2, | ||
543 | CS4271_MODE2_MUTECAEQUB, | ||
544 | CS4271_MODE2_MUTECAEQUB); | ||
545 | |||
531 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, | 546 | return snd_soc_add_codec_controls(codec, cs4271_snd_controls, |
532 | ARRAY_SIZE(cs4271_snd_controls)); | 547 | ARRAY_SIZE(cs4271_snd_controls)); |
533 | } | 548 | } |
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c index af5db7080519..843c1eb72faf 100644 --- a/sound/soc/codecs/da7210.c +++ b/sound/soc/codecs/da7210.c | |||
@@ -1231,7 +1231,7 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | |||
1231 | 1231 | ||
1232 | i2c_set_clientdata(i2c, da7210); | 1232 | i2c_set_clientdata(i2c, da7210); |
1233 | 1233 | ||
1234 | da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap_config_i2c); | 1234 | da7210->regmap = devm_regmap_init_i2c(i2c, &da7210_regmap_config_i2c); |
1235 | if (IS_ERR(da7210->regmap)) { | 1235 | if (IS_ERR(da7210->regmap)) { |
1236 | ret = PTR_ERR(da7210->regmap); | 1236 | ret = PTR_ERR(da7210->regmap); |
1237 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | 1237 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); |
@@ -1245,24 +1245,15 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c, | |||
1245 | 1245 | ||
1246 | ret = snd_soc_register_codec(&i2c->dev, | 1246 | ret = snd_soc_register_codec(&i2c->dev, |
1247 | &soc_codec_dev_da7210, &da7210_dai, 1); | 1247 | &soc_codec_dev_da7210, &da7210_dai, 1); |
1248 | if (ret < 0) { | 1248 | if (ret < 0) |
1249 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1249 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1250 | goto err_regmap; | ||
1251 | } | ||
1252 | return ret; | ||
1253 | |||
1254 | err_regmap: | ||
1255 | regmap_exit(da7210->regmap); | ||
1256 | 1250 | ||
1257 | return ret; | 1251 | return ret; |
1258 | } | 1252 | } |
1259 | 1253 | ||
1260 | static int __devexit da7210_i2c_remove(struct i2c_client *client) | 1254 | static int __devexit da7210_i2c_remove(struct i2c_client *client) |
1261 | { | 1255 | { |
1262 | struct da7210_priv *da7210 = i2c_get_clientdata(client); | ||
1263 | |||
1264 | snd_soc_unregister_codec(&client->dev); | 1256 | snd_soc_unregister_codec(&client->dev); |
1265 | regmap_exit(da7210->regmap); | ||
1266 | return 0; | 1257 | return 0; |
1267 | } | 1258 | } |
1268 | 1259 | ||
@@ -1346,24 +1337,15 @@ static int __devinit da7210_spi_probe(struct spi_device *spi) | |||
1346 | if (ret != 0) | 1337 | if (ret != 0) |
1347 | dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret); | 1338 | dev_warn(&spi->dev, "Failed to apply regmap patch: %d\n", ret); |
1348 | 1339 | ||
1349 | ret = snd_soc_register_codec(&spi->dev, | 1340 | ret = snd_soc_register_codec(&spi->dev, |
1350 | &soc_codec_dev_da7210, &da7210_dai, 1); | 1341 | &soc_codec_dev_da7210, &da7210_dai, 1); |
1351 | if (ret < 0) | ||
1352 | goto err_regmap; | ||
1353 | |||
1354 | return ret; | ||
1355 | |||
1356 | err_regmap: | ||
1357 | regmap_exit(da7210->regmap); | ||
1358 | 1342 | ||
1359 | return ret; | 1343 | return ret; |
1360 | } | 1344 | } |
1361 | 1345 | ||
1362 | static int __devexit da7210_spi_remove(struct spi_device *spi) | 1346 | static int __devexit da7210_spi_remove(struct spi_device *spi) |
1363 | { | 1347 | { |
1364 | struct da7210_priv *da7210 = spi_get_drvdata(spi); | ||
1365 | snd_soc_unregister_codec(&spi->dev); | 1348 | snd_soc_unregister_codec(&spi->dev); |
1366 | regmap_exit(da7210->regmap); | ||
1367 | return 0; | 1349 | return 0; |
1368 | } | 1350 | } |
1369 | 1351 | ||
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c index f379b085c392..d3a6de2e757b 100644 --- a/sound/soc/codecs/da9055.c +++ b/sound/soc/codecs/da9055.c | |||
@@ -173,6 +173,7 @@ | |||
173 | #define DA9055_AIF_FORMAT_I2S_MODE (0 << 0) | 173 | #define DA9055_AIF_FORMAT_I2S_MODE (0 << 0) |
174 | #define DA9055_AIF_FORMAT_LEFT_J (1 << 0) | 174 | #define DA9055_AIF_FORMAT_LEFT_J (1 << 0) |
175 | #define DA9055_AIF_FORMAT_RIGHT_J (2 << 0) | 175 | #define DA9055_AIF_FORMAT_RIGHT_J (2 << 0) |
176 | #define DA9055_AIF_FORMAT_DSP (3 << 0) | ||
176 | #define DA9055_AIF_WORD_S16_LE (0 << 2) | 177 | #define DA9055_AIF_WORD_S16_LE (0 << 2) |
177 | #define DA9055_AIF_WORD_S20_3LE (1 << 2) | 178 | #define DA9055_AIF_WORD_S20_3LE (1 << 2) |
178 | #define DA9055_AIF_WORD_S24_LE (2 << 2) | 179 | #define DA9055_AIF_WORD_S24_LE (2 << 2) |
@@ -752,6 +753,17 @@ static const struct snd_kcontrol_new da9055_dapm_mixoutr_controls[] = { | |||
752 | 6, 1, 0), | 753 | 6, 1, 0), |
753 | }; | 754 | }; |
754 | 755 | ||
756 | /* Headphone Output Enable */ | ||
757 | static const struct snd_kcontrol_new da9055_dapm_hp_l_control = | ||
758 | SOC_DAPM_SINGLE("Switch", DA9055_HP_L_CTRL, 3, 1, 0); | ||
759 | |||
760 | static const struct snd_kcontrol_new da9055_dapm_hp_r_control = | ||
761 | SOC_DAPM_SINGLE("Switch", DA9055_HP_R_CTRL, 3, 1, 0); | ||
762 | |||
763 | /* Lineout Output Enable */ | ||
764 | static const struct snd_kcontrol_new da9055_dapm_lineout_control = | ||
765 | SOC_DAPM_SINGLE("Switch", DA9055_LINE_CTRL, 3, 1, 0); | ||
766 | |||
755 | /* DAPM widgets */ | 767 | /* DAPM widgets */ |
756 | static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = { | 768 | static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = { |
757 | /* Input Side */ | 769 | /* Input Side */ |
@@ -816,6 +828,14 @@ static const struct snd_soc_dapm_widget da9055_dapm_widgets[] = { | |||
816 | &da9055_dapm_mixoutr_controls[0], | 828 | &da9055_dapm_mixoutr_controls[0], |
817 | ARRAY_SIZE(da9055_dapm_mixoutr_controls)), | 829 | ARRAY_SIZE(da9055_dapm_mixoutr_controls)), |
818 | 830 | ||
831 | /* Output Enable Switches */ | ||
832 | SND_SOC_DAPM_SWITCH("Headphone Left Enable", SND_SOC_NOPM, 0, 0, | ||
833 | &da9055_dapm_hp_l_control), | ||
834 | SND_SOC_DAPM_SWITCH("Headphone Right Enable", SND_SOC_NOPM, 0, 0, | ||
835 | &da9055_dapm_hp_r_control), | ||
836 | SND_SOC_DAPM_SWITCH("Lineout Enable", SND_SOC_NOPM, 0, 0, | ||
837 | &da9055_dapm_lineout_control), | ||
838 | |||
819 | /* Output PGAs */ | 839 | /* Output PGAs */ |
820 | SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0), | 840 | SND_SOC_DAPM_PGA("MIXOUT Left", DA9055_MIXOUT_L_CTRL, 7, 0, NULL, 0), |
821 | SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0), | 841 | SND_SOC_DAPM_PGA("MIXOUT Right", DA9055_MIXOUT_R_CTRL, 7, 0, NULL, 0), |
@@ -901,17 +921,20 @@ static const struct snd_soc_dapm_route da9055_audio_map[] = { | |||
901 | {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, | 921 | {"Out Mixer Right", "DAC Right Switch", "DAC Right"}, |
902 | 922 | ||
903 | {"MIXOUT Left", NULL, "Out Mixer Left"}, | 923 | {"MIXOUT Left", NULL, "Out Mixer Left"}, |
904 | {"Headphone Left", NULL, "MIXOUT Left"}, | 924 | {"Headphone Left Enable", "Switch", "MIXOUT Left"}, |
925 | {"Headphone Left", NULL, "Headphone Left Enable"}, | ||
905 | {"Headphone Left", NULL, "Charge Pump"}, | 926 | {"Headphone Left", NULL, "Charge Pump"}, |
906 | {"HPL", NULL, "Headphone Left"}, | 927 | {"HPL", NULL, "Headphone Left"}, |
907 | 928 | ||
908 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | 929 | {"MIXOUT Right", NULL, "Out Mixer Right"}, |
909 | {"Headphone Right", NULL, "MIXOUT Right"}, | 930 | {"Headphone Right Enable", "Switch", "MIXOUT Right"}, |
931 | {"Headphone Right", NULL, "Headphone Right Enable"}, | ||
910 | {"Headphone Right", NULL, "Charge Pump"}, | 932 | {"Headphone Right", NULL, "Charge Pump"}, |
911 | {"HPR", NULL, "Headphone Right"}, | 933 | {"HPR", NULL, "Headphone Right"}, |
912 | 934 | ||
913 | {"MIXOUT Right", NULL, "Out Mixer Right"}, | 935 | {"MIXOUT Right", NULL, "Out Mixer Right"}, |
914 | {"Lineout", NULL, "MIXOUT Right"}, | 936 | {"Lineout Enable", "Switch", "MIXOUT Right"}, |
937 | {"Lineout", NULL, "Lineout Enable"}, | ||
915 | {"LINE", NULL, "Lineout"}, | 938 | {"LINE", NULL, "Lineout"}, |
916 | }; | 939 | }; |
917 | 940 | ||
@@ -1175,6 +1198,9 @@ static int da9055_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) | |||
1175 | case SND_SOC_DAIFMT_RIGHT_J: | 1198 | case SND_SOC_DAIFMT_RIGHT_J: |
1176 | aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J; | 1199 | aif_ctrl = DA9055_AIF_FORMAT_RIGHT_J; |
1177 | break; | 1200 | break; |
1201 | case SND_SOC_DAIFMT_DSP_A: | ||
1202 | aif_ctrl = DA9055_AIF_FORMAT_DSP; | ||
1203 | break; | ||
1178 | default: | 1204 | default: |
1179 | return -EINVAL; | 1205 | return -EINVAL; |
1180 | } | 1206 | } |
@@ -1390,8 +1416,7 @@ static int da9055_probe(struct snd_soc_codec *codec) | |||
1390 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); | 1416 | DA9055_GAIN_RAMPING_EN, DA9055_GAIN_RAMPING_EN); |
1391 | 1417 | ||
1392 | /* | 1418 | /* |
1393 | * There are two separate control bits for input and output mixers as | 1419 | * There are two separate control bits for input and output mixers. |
1394 | * well as headphone and line outs. | ||
1395 | * One to enable corresponding amplifier and other to enable its | 1420 | * One to enable corresponding amplifier and other to enable its |
1396 | * output. As amplifier bits are related to power control, they are | 1421 | * output. As amplifier bits are related to power control, they are |
1397 | * being managed by DAPM while other (non power related) bits are | 1422 | * being managed by DAPM while other (non power related) bits are |
@@ -1407,14 +1432,6 @@ static int da9055_probe(struct snd_soc_codec *codec) | |||
1407 | snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL, | 1432 | snd_soc_update_bits(codec, DA9055_MIXOUT_R_CTRL, |
1408 | DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN); | 1433 | DA9055_MIXOUT_R_MIX_EN, DA9055_MIXOUT_R_MIX_EN); |
1409 | 1434 | ||
1410 | snd_soc_update_bits(codec, DA9055_HP_L_CTRL, | ||
1411 | DA9055_HP_L_AMP_OE, DA9055_HP_L_AMP_OE); | ||
1412 | snd_soc_update_bits(codec, DA9055_HP_R_CTRL, | ||
1413 | DA9055_HP_R_AMP_OE, DA9055_HP_R_AMP_OE); | ||
1414 | |||
1415 | snd_soc_update_bits(codec, DA9055_LINE_CTRL, | ||
1416 | DA9055_LINE_AMP_OE, DA9055_LINE_AMP_OE); | ||
1417 | |||
1418 | /* Set this as per your system configuration */ | 1435 | /* Set this as per your system configuration */ |
1419 | snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ); | 1436 | snd_soc_write(codec, DA9055_PLL_CTRL, DA9055_PLL_INDIV_10_20_MHZ); |
1420 | 1437 | ||
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c index 85d9cabe6d55..9ad1da36887e 100644 --- a/sound/soc/codecs/jz4740.c +++ b/sound/soc/codecs/jz4740.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/platform_device.h> | 16 | #include <linux/platform_device.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <linux/regmap.h> | ||
19 | 20 | ||
20 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
21 | 22 | ||
@@ -24,9 +25,10 @@ | |||
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
25 | #include <sound/initval.h> | 26 | #include <sound/initval.h> |
26 | #include <sound/soc.h> | 27 | #include <sound/soc.h> |
28 | #include <sound/tlv.h> | ||
27 | 29 | ||
28 | #define JZ4740_REG_CODEC_1 0x0 | 30 | #define JZ4740_REG_CODEC_1 0x0 |
29 | #define JZ4740_REG_CODEC_2 0x1 | 31 | #define JZ4740_REG_CODEC_2 0x4 |
30 | 32 | ||
31 | #define JZ4740_CODEC_1_LINE_ENABLE BIT(29) | 33 | #define JZ4740_CODEC_1_LINE_ENABLE BIT(29) |
32 | #define JZ4740_CODEC_1_MIC_ENABLE BIT(28) | 34 | #define JZ4740_CODEC_1_MIC_ENABLE BIT(28) |
@@ -67,43 +69,36 @@ | |||
67 | #define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4 | 69 | #define JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET 4 |
68 | #define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0 | 70 | #define JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET 0 |
69 | 71 | ||
70 | static const uint32_t jz4740_codec_regs[] = { | 72 | static const struct reg_default jz4740_codec_reg_defaults[] = { |
71 | 0x021b2302, 0x00170803, | 73 | { JZ4740_REG_CODEC_1, 0x021b2302 }, |
74 | { JZ4740_REG_CODEC_2, 0x00170803 }, | ||
72 | }; | 75 | }; |
73 | 76 | ||
74 | struct jz4740_codec { | 77 | struct jz4740_codec { |
75 | void __iomem *base; | 78 | struct regmap *regmap; |
76 | struct resource *mem; | ||
77 | }; | 79 | }; |
78 | 80 | ||
79 | static unsigned int jz4740_codec_read(struct snd_soc_codec *codec, | 81 | static const unsigned int jz4740_mic_tlv[] = { |
80 | unsigned int reg) | 82 | TLV_DB_RANGE_HEAD(2), |
81 | { | 83 | 0, 2, TLV_DB_SCALE_ITEM(0, 600, 0), |
82 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); | 84 | 3, 3, TLV_DB_SCALE_ITEM(2000, 0, 0), |
83 | return readl(jz4740_codec->base + (reg << 2)); | 85 | }; |
84 | } | ||
85 | |||
86 | static int jz4740_codec_write(struct snd_soc_codec *codec, unsigned int reg, | ||
87 | unsigned int val) | ||
88 | { | ||
89 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); | ||
90 | u32 *cache = codec->reg_cache; | ||
91 | |||
92 | cache[reg] = val; | ||
93 | writel(val, jz4740_codec->base + (reg << 2)); | ||
94 | 86 | ||
95 | return 0; | 87 | static const DECLARE_TLV_DB_SCALE(jz4740_out_tlv, 0, 200, 0); |
96 | } | 88 | static const DECLARE_TLV_DB_SCALE(jz4740_in_tlv, -3450, 150, 0); |
97 | 89 | ||
98 | static const struct snd_kcontrol_new jz4740_codec_controls[] = { | 90 | static const struct snd_kcontrol_new jz4740_codec_controls[] = { |
99 | SOC_SINGLE("Master Playback Volume", JZ4740_REG_CODEC_2, | 91 | SOC_SINGLE_TLV("Master Playback Volume", JZ4740_REG_CODEC_2, |
100 | JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0), | 92 | JZ4740_CODEC_2_HEADPHONE_VOLUME_OFFSET, 3, 0, |
101 | SOC_SINGLE("Master Capture Volume", JZ4740_REG_CODEC_2, | 93 | jz4740_out_tlv), |
102 | JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0), | 94 | SOC_SINGLE_TLV("Master Capture Volume", JZ4740_REG_CODEC_2, |
95 | JZ4740_CODEC_2_INPUT_VOLUME_OFFSET, 31, 0, | ||
96 | jz4740_in_tlv), | ||
103 | SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1, | 97 | SOC_SINGLE("Master Playback Switch", JZ4740_REG_CODEC_1, |
104 | JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1), | 98 | JZ4740_CODEC_1_HEADPHONE_DISABLE_OFFSET, 1, 1), |
105 | SOC_SINGLE("Mic Capture Volume", JZ4740_REG_CODEC_2, | 99 | SOC_SINGLE_TLV("Mic Capture Volume", JZ4740_REG_CODEC_2, |
106 | JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0), | 100 | JZ4740_CODEC_2_MIC_BOOST_GAIN_OFFSET, 3, 0, |
101 | jz4740_mic_tlv), | ||
107 | }; | 102 | }; |
108 | 103 | ||
109 | static const struct snd_kcontrol_new jz4740_codec_output_controls[] = { | 104 | static const struct snd_kcontrol_new jz4740_codec_output_controls[] = { |
@@ -163,8 +158,8 @@ static const struct snd_soc_dapm_route jz4740_codec_dapm_routes[] = { | |||
163 | static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, | 158 | static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, |
164 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 159 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
165 | { | 160 | { |
161 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(dai->codec); | ||
166 | uint32_t val; | 162 | uint32_t val; |
167 | struct snd_soc_codec *codec = dai->codec; | ||
168 | 163 | ||
169 | switch (params_rate(params)) { | 164 | switch (params_rate(params)) { |
170 | case 8000: | 165 | case 8000: |
@@ -200,7 +195,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream, | |||
200 | 195 | ||
201 | val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET; | 196 | val <<= JZ4740_CODEC_2_SAMPLE_RATE_OFFSET; |
202 | 197 | ||
203 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_2, | 198 | regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_2, |
204 | JZ4740_CODEC_2_SAMPLE_RATE_MASK, val); | 199 | JZ4740_CODEC_2_SAMPLE_RATE_MASK, val); |
205 | 200 | ||
206 | return 0; | 201 | return 0; |
@@ -230,25 +225,23 @@ static struct snd_soc_dai_driver jz4740_codec_dai = { | |||
230 | .symmetric_rates = 1, | 225 | .symmetric_rates = 1, |
231 | }; | 226 | }; |
232 | 227 | ||
233 | static void jz4740_codec_wakeup(struct snd_soc_codec *codec) | 228 | static void jz4740_codec_wakeup(struct regmap *regmap) |
234 | { | 229 | { |
235 | int i; | 230 | regmap_update_bits(regmap, JZ4740_REG_CODEC_1, |
236 | uint32_t *cache = codec->reg_cache; | ||
237 | |||
238 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | ||
239 | JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET); | 231 | JZ4740_CODEC_1_RESET, JZ4740_CODEC_1_RESET); |
240 | udelay(2); | 232 | udelay(2); |
241 | 233 | ||
242 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | 234 | regmap_update_bits(regmap, JZ4740_REG_CODEC_1, |
243 | JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0); | 235 | JZ4740_CODEC_1_SUSPEND | JZ4740_CODEC_1_RESET, 0); |
244 | 236 | ||
245 | for (i = 0; i < ARRAY_SIZE(jz4740_codec_regs); ++i) | 237 | regcache_sync(regmap); |
246 | jz4740_codec_write(codec, i, cache[i]); | ||
247 | } | 238 | } |
248 | 239 | ||
249 | static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | 240 | static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, |
250 | enum snd_soc_bias_level level) | 241 | enum snd_soc_bias_level level) |
251 | { | 242 | { |
243 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); | ||
244 | struct regmap *regmap = jz4740_codec->regmap; | ||
252 | unsigned int mask; | 245 | unsigned int mask; |
253 | unsigned int value; | 246 | unsigned int value; |
254 | 247 | ||
@@ -261,12 +254,12 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
261 | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; | 254 | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; |
262 | value = 0; | 255 | value = 0; |
263 | 256 | ||
264 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); | 257 | regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); |
265 | break; | 258 | break; |
266 | case SND_SOC_BIAS_STANDBY: | 259 | case SND_SOC_BIAS_STANDBY: |
267 | /* The only way to clear the suspend flag is to reset the codec */ | 260 | /* The only way to clear the suspend flag is to reset the codec */ |
268 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) | 261 | if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) |
269 | jz4740_codec_wakeup(codec); | 262 | jz4740_codec_wakeup(regmap); |
270 | 263 | ||
271 | mask = JZ4740_CODEC_1_VREF_DISABLE | | 264 | mask = JZ4740_CODEC_1_VREF_DISABLE | |
272 | JZ4740_CODEC_1_VREF_AMP_DISABLE | | 265 | JZ4740_CODEC_1_VREF_AMP_DISABLE | |
@@ -275,13 +268,14 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
275 | JZ4740_CODEC_1_VREF_AMP_DISABLE | | 268 | JZ4740_CODEC_1_VREF_AMP_DISABLE | |
276 | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; | 269 | JZ4740_CODEC_1_HEADPHONE_POWERDOWN_M; |
277 | 270 | ||
278 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); | 271 | regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); |
279 | break; | 272 | break; |
280 | case SND_SOC_BIAS_OFF: | 273 | case SND_SOC_BIAS_OFF: |
281 | mask = JZ4740_CODEC_1_SUSPEND; | 274 | mask = JZ4740_CODEC_1_SUSPEND; |
282 | value = JZ4740_CODEC_1_SUSPEND; | 275 | value = JZ4740_CODEC_1_SUSPEND; |
283 | 276 | ||
284 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, mask, value); | 277 | regmap_update_bits(regmap, JZ4740_REG_CODEC_1, mask, value); |
278 | regcache_mark_dirty(regmap); | ||
285 | break; | 279 | break; |
286 | default: | 280 | default: |
287 | break; | 281 | break; |
@@ -294,7 +288,9 @@ static int jz4740_codec_set_bias_level(struct snd_soc_codec *codec, | |||
294 | 288 | ||
295 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) | 289 | static int jz4740_codec_dev_probe(struct snd_soc_codec *codec) |
296 | { | 290 | { |
297 | snd_soc_update_bits(codec, JZ4740_REG_CODEC_1, | 291 | struct jz4740_codec *jz4740_codec = snd_soc_codec_get_drvdata(codec); |
292 | |||
293 | regmap_update_bits(jz4740_codec->regmap, JZ4740_REG_CODEC_1, | ||
298 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); | 294 | JZ4740_CODEC_1_SW2_ENABLE, JZ4740_CODEC_1_SW2_ENABLE); |
299 | 295 | ||
300 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 296 | jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
@@ -331,12 +327,7 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { | |||
331 | .remove = jz4740_codec_dev_remove, | 327 | .remove = jz4740_codec_dev_remove, |
332 | .suspend = jz4740_codec_suspend, | 328 | .suspend = jz4740_codec_suspend, |
333 | .resume = jz4740_codec_resume, | 329 | .resume = jz4740_codec_resume, |
334 | .read = jz4740_codec_read, | ||
335 | .write = jz4740_codec_write, | ||
336 | .set_bias_level = jz4740_codec_set_bias_level, | 330 | .set_bias_level = jz4740_codec_set_bias_level, |
337 | .reg_cache_default = jz4740_codec_regs, | ||
338 | .reg_word_size = sizeof(u32), | ||
339 | .reg_cache_size = 2, | ||
340 | 331 | ||
341 | .controls = jz4740_codec_controls, | 332 | .controls = jz4740_codec_controls, |
342 | .num_controls = ARRAY_SIZE(jz4740_codec_controls), | 333 | .num_controls = ARRAY_SIZE(jz4740_codec_controls), |
@@ -346,11 +337,23 @@ static struct snd_soc_codec_driver soc_codec_dev_jz4740_codec = { | |||
346 | .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), | 337 | .num_dapm_routes = ARRAY_SIZE(jz4740_codec_dapm_routes), |
347 | }; | 338 | }; |
348 | 339 | ||
340 | static const struct regmap_config jz4740_codec_regmap_config = { | ||
341 | .reg_bits = 32, | ||
342 | .reg_stride = 4, | ||
343 | .val_bits = 32, | ||
344 | .max_register = JZ4740_REG_CODEC_2, | ||
345 | |||
346 | .reg_defaults = jz4740_codec_reg_defaults, | ||
347 | .num_reg_defaults = ARRAY_SIZE(jz4740_codec_reg_defaults), | ||
348 | .cache_type = REGCACHE_RBTREE, | ||
349 | }; | ||
350 | |||
349 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) | 351 | static int __devinit jz4740_codec_probe(struct platform_device *pdev) |
350 | { | 352 | { |
351 | int ret; | 353 | int ret; |
352 | struct jz4740_codec *jz4740_codec; | 354 | struct jz4740_codec *jz4740_codec; |
353 | struct resource *mem; | 355 | struct resource *mem; |
356 | void __iomem *base; | ||
354 | 357 | ||
355 | jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), | 358 | jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec), |
356 | GFP_KERNEL); | 359 | GFP_KERNEL); |
@@ -358,56 +361,29 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev) | |||
358 | return -ENOMEM; | 361 | return -ENOMEM; |
359 | 362 | ||
360 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 363 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
361 | if (!mem) { | 364 | base = devm_request_and_ioremap(&pdev->dev, mem); |
362 | dev_err(&pdev->dev, "Failed to get mmio memory resource\n"); | 365 | if (!base) |
363 | ret = -ENOENT; | 366 | return -EBUSY; |
364 | goto err_out; | ||
365 | } | ||
366 | |||
367 | mem = request_mem_region(mem->start, resource_size(mem), pdev->name); | ||
368 | if (!mem) { | ||
369 | dev_err(&pdev->dev, "Failed to request mmio memory region\n"); | ||
370 | ret = -EBUSY; | ||
371 | goto err_out; | ||
372 | } | ||
373 | 367 | ||
374 | jz4740_codec->base = ioremap(mem->start, resource_size(mem)); | 368 | jz4740_codec->regmap = devm_regmap_init_mmio(&pdev->dev, base, |
375 | if (!jz4740_codec->base) { | 369 | &jz4740_codec_regmap_config); |
376 | dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); | 370 | if (IS_ERR(jz4740_codec->regmap)) |
377 | ret = -EBUSY; | 371 | return PTR_ERR(jz4740_codec->regmap); |
378 | goto err_release_mem_region; | ||
379 | } | ||
380 | jz4740_codec->mem = mem; | ||
381 | 372 | ||
382 | platform_set_drvdata(pdev, jz4740_codec); | 373 | platform_set_drvdata(pdev, jz4740_codec); |
383 | 374 | ||
384 | ret = snd_soc_register_codec(&pdev->dev, | 375 | ret = snd_soc_register_codec(&pdev->dev, |
385 | &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); | 376 | &soc_codec_dev_jz4740_codec, &jz4740_codec_dai, 1); |
386 | if (ret) { | 377 | if (ret) |
387 | dev_err(&pdev->dev, "Failed to register codec\n"); | 378 | dev_err(&pdev->dev, "Failed to register codec\n"); |
388 | goto err_iounmap; | ||
389 | } | ||
390 | 379 | ||
391 | return 0; | ||
392 | |||
393 | err_iounmap: | ||
394 | iounmap(jz4740_codec->base); | ||
395 | err_release_mem_region: | ||
396 | release_mem_region(mem->start, resource_size(mem)); | ||
397 | err_out: | ||
398 | return ret; | 380 | return ret; |
399 | } | 381 | } |
400 | 382 | ||
401 | static int __devexit jz4740_codec_remove(struct platform_device *pdev) | 383 | static int __devexit jz4740_codec_remove(struct platform_device *pdev) |
402 | { | 384 | { |
403 | struct jz4740_codec *jz4740_codec = platform_get_drvdata(pdev); | ||
404 | struct resource *mem = jz4740_codec->mem; | ||
405 | |||
406 | snd_soc_unregister_codec(&pdev->dev); | 385 | snd_soc_unregister_codec(&pdev->dev); |
407 | 386 | ||
408 | iounmap(jz4740_codec->base); | ||
409 | release_mem_region(mem->start, resource_size(mem)); | ||
410 | |||
411 | platform_set_drvdata(pdev, NULL); | 387 | platform_set_drvdata(pdev, NULL); |
412 | 388 | ||
413 | return 0; | 389 | return 0; |
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index 99b0a9dcff34..096b6aa87f0f 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c | |||
@@ -1497,7 +1497,7 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c, | |||
1497 | 1497 | ||
1498 | i2c_set_clientdata(i2c, lm49453); | 1498 | i2c_set_clientdata(i2c, lm49453); |
1499 | 1499 | ||
1500 | lm49453->regmap = regmap_init_i2c(i2c, &lm49453_regmap_config); | 1500 | lm49453->regmap = devm_regmap_init_i2c(i2c, &lm49453_regmap_config); |
1501 | if (IS_ERR(lm49453->regmap)) { | 1501 | if (IS_ERR(lm49453->regmap)) { |
1502 | ret = PTR_ERR(lm49453->regmap); | 1502 | ret = PTR_ERR(lm49453->regmap); |
1503 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 1503 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -1508,21 +1508,15 @@ static __devinit int lm49453_i2c_probe(struct i2c_client *i2c, | |||
1508 | ret = snd_soc_register_codec(&i2c->dev, | 1508 | ret = snd_soc_register_codec(&i2c->dev, |
1509 | &soc_codec_dev_lm49453, | 1509 | &soc_codec_dev_lm49453, |
1510 | lm49453_dai, ARRAY_SIZE(lm49453_dai)); | 1510 | lm49453_dai, ARRAY_SIZE(lm49453_dai)); |
1511 | if (ret < 0) { | 1511 | if (ret < 0) |
1512 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); | 1512 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1513 | regmap_exit(lm49453->regmap); | ||
1514 | return ret; | ||
1515 | } | ||
1516 | 1513 | ||
1517 | return ret; | 1514 | return ret; |
1518 | } | 1515 | } |
1519 | 1516 | ||
1520 | static int __devexit lm49453_i2c_remove(struct i2c_client *client) | 1517 | static int __devexit lm49453_i2c_remove(struct i2c_client *client) |
1521 | { | 1518 | { |
1522 | struct lm49453_priv *lm49453 = i2c_get_clientdata(client); | ||
1523 | |||
1524 | snd_soc_unregister_codec(&client->dev); | 1519 | snd_soc_unregister_codec(&client->dev); |
1525 | regmap_exit(lm49453->regmap); | ||
1526 | return 0; | 1520 | return 0; |
1527 | } | 1521 | } |
1528 | 1522 | ||
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c index 17b3ec2d05cb..a777de6a1b23 100644 --- a/sound/soc/codecs/max9768.c +++ b/sound/soc/codecs/max9768.c | |||
@@ -187,7 +187,7 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client, | |||
187 | 187 | ||
188 | i2c_set_clientdata(client, max9768); | 188 | i2c_set_clientdata(client, max9768); |
189 | 189 | ||
190 | max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config); | 190 | max9768->regmap = devm_regmap_init_i2c(client, &max9768_i2c_regmap_config); |
191 | if (IS_ERR(max9768->regmap)) { | 191 | if (IS_ERR(max9768->regmap)) { |
192 | err = PTR_ERR(max9768->regmap); | 192 | err = PTR_ERR(max9768->regmap); |
193 | goto err_gpio_free; | 193 | goto err_gpio_free; |
@@ -195,12 +195,10 @@ static int __devinit max9768_i2c_probe(struct i2c_client *client, | |||
195 | 195 | ||
196 | err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0); | 196 | err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0); |
197 | if (err) | 197 | if (err) |
198 | goto err_regmap_free; | 198 | goto err_gpio_free; |
199 | 199 | ||
200 | return 0; | 200 | return 0; |
201 | 201 | ||
202 | err_regmap_free: | ||
203 | regmap_exit(max9768->regmap); | ||
204 | err_gpio_free: | 202 | err_gpio_free: |
205 | if (gpio_is_valid(max9768->shdn_gpio)) | 203 | if (gpio_is_valid(max9768->shdn_gpio)) |
206 | gpio_free(max9768->shdn_gpio); | 204 | gpio_free(max9768->shdn_gpio); |
@@ -215,7 +213,6 @@ static int __devexit max9768_i2c_remove(struct i2c_client *client) | |||
215 | struct max9768 *max9768 = i2c_get_clientdata(client); | 213 | struct max9768 *max9768 = i2c_get_clientdata(client); |
216 | 214 | ||
217 | snd_soc_unregister_codec(&client->dev); | 215 | snd_soc_unregister_codec(&client->dev); |
218 | regmap_exit(max9768->regmap); | ||
219 | 216 | ||
220 | if (gpio_is_valid(max9768->shdn_gpio)) | 217 | if (gpio_is_valid(max9768->shdn_gpio)) |
221 | gpio_free(max9768->shdn_gpio); | 218 | gpio_free(max9768->shdn_gpio); |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index 3264a5169306..b858264235c4 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -2098,13 +2098,13 @@ static const struct i2c_device_id max98088_i2c_id[] = { | |||
2098 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); | 2098 | MODULE_DEVICE_TABLE(i2c, max98088_i2c_id); |
2099 | 2099 | ||
2100 | static struct i2c_driver max98088_i2c_driver = { | 2100 | static struct i2c_driver max98088_i2c_driver = { |
2101 | .driver = { | 2101 | .driver = { |
2102 | .name = "max98088", | 2102 | .name = "max98088", |
2103 | .owner = THIS_MODULE, | 2103 | .owner = THIS_MODULE, |
2104 | }, | 2104 | }, |
2105 | .probe = max98088_i2c_probe, | 2105 | .probe = max98088_i2c_probe, |
2106 | .remove = __devexit_p(max98088_i2c_remove), | 2106 | .remove = max98088_i2c_remove, |
2107 | .id_table = max98088_i2c_id, | 2107 | .id_table = max98088_i2c_id, |
2108 | }; | 2108 | }; |
2109 | 2109 | ||
2110 | module_i2c_driver(max98088_i2c_driver); | 2110 | module_i2c_driver(max98088_i2c_driver); |
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c new file mode 100644 index 000000000000..c9772ca3da4f --- /dev/null +++ b/sound/soc/codecs/max98090.c | |||
@@ -0,0 +1,577 @@ | |||
1 | /* | ||
2 | * max98090.c -- MAX98090 ALSA SoC Audio driver | ||
3 | * based on Rev0p8 datasheet | ||
4 | * | ||
5 | * Copyright (C) 2012 Renesas Solutions Corp. | ||
6 | * Kuninori Morimoto <kuninori.morimoto.gx@renesas.com> | ||
7 | * | ||
8 | * Based on | ||
9 | * | ||
10 | * max98095.c | ||
11 | * Copyright 2011 Maxim Integrated Products | ||
12 | * | ||
13 | * https://github.com/hardkernel/linux/commit/\ | ||
14 | * 3417d7166b17113b3b33b0a337c74d1c7cc313df#sound/soc/codecs/max98090.c | ||
15 | * Copyright 2011 Maxim Integrated Products | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License version 2 as | ||
19 | * published by the Free Software Foundation. | ||
20 | */ | ||
21 | |||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/tlv.h> | ||
27 | |||
28 | /* | ||
29 | * | ||
30 | * MAX98090 Registers Definition | ||
31 | * | ||
32 | */ | ||
33 | |||
34 | /* RESET / STATUS / INTERRUPT REGISTERS */ | ||
35 | #define MAX98090_0x00_SW_RESET 0x00 | ||
36 | #define MAX98090_0x01_INT_STS 0x01 | ||
37 | #define MAX98090_0x02_JACK_STS 0x02 | ||
38 | #define MAX98090_0x03_INT_MASK 0x03 | ||
39 | |||
40 | /* QUICK SETUP REGISTERS */ | ||
41 | #define MAX98090_0x04_SYS_CLK 0x04 | ||
42 | #define MAX98090_0x05_SAMPLE_RATE 0x05 | ||
43 | #define MAX98090_0x06_DAI_IF 0x06 | ||
44 | #define MAX98090_0x07_DAC_PATH 0x07 | ||
45 | #define MAX98090_0x08_MIC_TO_ADC 0x08 | ||
46 | #define MAX98090_0x09_LINE_TO_ADC 0x09 | ||
47 | #define MAX98090_0x0A_ANALOG_MIC_LOOP 0x0A | ||
48 | #define MAX98090_0x0B_ANALOG_LINE_LOOP 0x0B | ||
49 | |||
50 | /* ANALOG INPUT CONFIGURATION REGISTERS */ | ||
51 | #define MAX98090_0x0D_INPUT_CONFIG 0x0D | ||
52 | #define MAX98090_0x0E_LINE_IN_LVL 0x0E | ||
53 | #define MAX98090_0x0F_LINI_IN_CFG 0x0F | ||
54 | #define MAX98090_0x10_MIC1_IN_LVL 0x10 | ||
55 | #define MAX98090_0x11_MIC2_IN_LVL 0x11 | ||
56 | |||
57 | /* MICROPHONE CONFIGURATION REGISTERS */ | ||
58 | #define MAX98090_0x12_MIC_BIAS_VOL 0x12 | ||
59 | #define MAX98090_0x13_DIGITAL_MIC_CFG 0x13 | ||
60 | #define MAX98090_0x14_DIGITAL_MIC_MODE 0x14 | ||
61 | |||
62 | /* ADC PATH AND CONFIGURATION REGISTERS */ | ||
63 | #define MAX98090_0x15_L_ADC_MIX 0x15 | ||
64 | #define MAX98090_0x16_R_ADC_MIX 0x16 | ||
65 | #define MAX98090_0x17_L_ADC_LVL 0x17 | ||
66 | #define MAX98090_0x18_R_ADC_LVL 0x18 | ||
67 | #define MAX98090_0x19_ADC_BIQUAD_LVL 0x19 | ||
68 | #define MAX98090_0x1A_ADC_SIDETONE 0x1A | ||
69 | |||
70 | /* CLOCK CONFIGURATION REGISTERS */ | ||
71 | #define MAX98090_0x1B_SYS_CLK 0x1B | ||
72 | #define MAX98090_0x1C_CLK_MODE 0x1C | ||
73 | #define MAX98090_0x1D_ANY_CLK1 0x1D | ||
74 | #define MAX98090_0x1E_ANY_CLK2 0x1E | ||
75 | #define MAX98090_0x1F_ANY_CLK3 0x1F | ||
76 | #define MAX98090_0x20_ANY_CLK4 0x20 | ||
77 | #define MAX98090_0x21_MASTER_MODE 0x21 | ||
78 | |||
79 | /* INTERFACE CONTROL REGISTERS */ | ||
80 | #define MAX98090_0x22_DAI_IF_FMT 0x22 | ||
81 | #define MAX98090_0x23_DAI_TDM_FMT1 0x23 | ||
82 | #define MAX98090_0x24_DAI_TDM_FMT2 0x24 | ||
83 | #define MAX98090_0x25_DAI_IO_CFG 0x25 | ||
84 | #define MAX98090_0x26_FILTER_CFG 0x26 | ||
85 | #define MAX98090_0x27_DAI_PLAYBACK_LVL 0x27 | ||
86 | #define MAX98090_0x28_EQ_PLAYBACK_LVL 0x28 | ||
87 | |||
88 | /* HEADPHONE CONTROL REGISTERS */ | ||
89 | #define MAX98090_0x29_L_HP_MIX 0x29 | ||
90 | #define MAX98090_0x2A_R_HP_MIX 0x2A | ||
91 | #define MAX98090_0x2B_HP_CTR 0x2B | ||
92 | #define MAX98090_0x2C_L_HP_VOL 0x2C | ||
93 | #define MAX98090_0x2D_R_HP_VOL 0x2D | ||
94 | |||
95 | /* SPEAKER CONFIGURATION REGISTERS */ | ||
96 | #define MAX98090_0x2E_L_SPK_MIX 0x2E | ||
97 | #define MAX98090_0x2F_R_SPK_MIX 0x2F | ||
98 | #define MAX98090_0x30_SPK_CTR 0x30 | ||
99 | #define MAX98090_0x31_L_SPK_VOL 0x31 | ||
100 | #define MAX98090_0x32_R_SPK_VOL 0x32 | ||
101 | |||
102 | /* ALC CONFIGURATION REGISTERS */ | ||
103 | #define MAX98090_0x33_ALC_TIMING 0x33 | ||
104 | #define MAX98090_0x34_ALC_COMPRESSOR 0x34 | ||
105 | #define MAX98090_0x35_ALC_EXPANDER 0x35 | ||
106 | #define MAX98090_0x36_ALC_GAIN 0x36 | ||
107 | |||
108 | /* RECEIVER AND LINE_OUTPUT REGISTERS */ | ||
109 | #define MAX98090_0x37_RCV_LOUT_L_MIX 0x37 | ||
110 | #define MAX98090_0x38_RCV_LOUT_L_CNTL 0x38 | ||
111 | #define MAX98090_0x39_RCV_LOUT_L_VOL 0x39 | ||
112 | #define MAX98090_0x3A_LOUT_R_MIX 0x3A | ||
113 | #define MAX98090_0x3B_LOUT_R_CNTL 0x3B | ||
114 | #define MAX98090_0x3C_LOUT_R_VOL 0x3C | ||
115 | |||
116 | /* JACK DETECT AND ENABLE REGISTERS */ | ||
117 | #define MAX98090_0x3D_JACK_DETECT 0x3D | ||
118 | #define MAX98090_0x3E_IN_ENABLE 0x3E | ||
119 | #define MAX98090_0x3F_OUT_ENABLE 0x3F | ||
120 | #define MAX98090_0x40_LVL_CTR 0x40 | ||
121 | #define MAX98090_0x41_DSP_FILTER_ENABLE 0x41 | ||
122 | |||
123 | /* BIAS AND POWER MODE CONFIGURATION REGISTERS */ | ||
124 | #define MAX98090_0x42_BIAS_CTR 0x42 | ||
125 | #define MAX98090_0x43_DAC_CTR 0x43 | ||
126 | #define MAX98090_0x44_ADC_CTR 0x44 | ||
127 | #define MAX98090_0x45_DEV_SHUTDOWN 0x45 | ||
128 | |||
129 | /* REVISION ID REGISTER */ | ||
130 | #define MAX98090_0xFF_REV_ID 0xFF | ||
131 | |||
132 | #define MAX98090_REG_MAX_CACHED 0x45 | ||
133 | #define MAX98090_REG_END 0xFF | ||
134 | |||
135 | /* | ||
136 | * | ||
137 | * MAX98090 Registers Bit Fields | ||
138 | * | ||
139 | */ | ||
140 | |||
141 | /* MAX98090_0x06_DAI_IF */ | ||
142 | #define MAX98090_DAI_IF_MASK 0x3F | ||
143 | #define MAX98090_RJ_M (1 << 5) | ||
144 | #define MAX98090_RJ_S (1 << 4) | ||
145 | #define MAX98090_LJ_M (1 << 3) | ||
146 | #define MAX98090_LJ_S (1 << 2) | ||
147 | #define MAX98090_I2S_M (1 << 1) | ||
148 | #define MAX98090_I2S_S (1 << 0) | ||
149 | |||
150 | /* MAX98090_0x45_DEV_SHUTDOWN */ | ||
151 | #define MAX98090_SHDNRUN (1 << 7) | ||
152 | |||
153 | /* codec private data */ | ||
154 | struct max98090_priv { | ||
155 | struct regmap *regmap; | ||
156 | }; | ||
157 | |||
158 | static const struct reg_default max98090_reg_defaults[] = { | ||
159 | /* RESET / STATUS / INTERRUPT REGISTERS */ | ||
160 | {MAX98090_0x00_SW_RESET, 0x00}, | ||
161 | {MAX98090_0x01_INT_STS, 0x00}, | ||
162 | {MAX98090_0x02_JACK_STS, 0x00}, | ||
163 | {MAX98090_0x03_INT_MASK, 0x04}, | ||
164 | |||
165 | /* QUICK SETUP REGISTERS */ | ||
166 | {MAX98090_0x04_SYS_CLK, 0x00}, | ||
167 | {MAX98090_0x05_SAMPLE_RATE, 0x00}, | ||
168 | {MAX98090_0x06_DAI_IF, 0x00}, | ||
169 | {MAX98090_0x07_DAC_PATH, 0x00}, | ||
170 | {MAX98090_0x08_MIC_TO_ADC, 0x00}, | ||
171 | {MAX98090_0x09_LINE_TO_ADC, 0x00}, | ||
172 | {MAX98090_0x0A_ANALOG_MIC_LOOP, 0x00}, | ||
173 | {MAX98090_0x0B_ANALOG_LINE_LOOP, 0x00}, | ||
174 | |||
175 | /* ANALOG INPUT CONFIGURATION REGISTERS */ | ||
176 | {MAX98090_0x0D_INPUT_CONFIG, 0x00}, | ||
177 | {MAX98090_0x0E_LINE_IN_LVL, 0x1B}, | ||
178 | {MAX98090_0x0F_LINI_IN_CFG, 0x00}, | ||
179 | {MAX98090_0x10_MIC1_IN_LVL, 0x11}, | ||
180 | {MAX98090_0x11_MIC2_IN_LVL, 0x11}, | ||
181 | |||
182 | /* MICROPHONE CONFIGURATION REGISTERS */ | ||
183 | {MAX98090_0x12_MIC_BIAS_VOL, 0x00}, | ||
184 | {MAX98090_0x13_DIGITAL_MIC_CFG, 0x00}, | ||
185 | {MAX98090_0x14_DIGITAL_MIC_MODE, 0x00}, | ||
186 | |||
187 | /* ADC PATH AND CONFIGURATION REGISTERS */ | ||
188 | {MAX98090_0x15_L_ADC_MIX, 0x00}, | ||
189 | {MAX98090_0x16_R_ADC_MIX, 0x00}, | ||
190 | {MAX98090_0x17_L_ADC_LVL, 0x03}, | ||
191 | {MAX98090_0x18_R_ADC_LVL, 0x03}, | ||
192 | {MAX98090_0x19_ADC_BIQUAD_LVL, 0x00}, | ||
193 | {MAX98090_0x1A_ADC_SIDETONE, 0x00}, | ||
194 | |||
195 | /* CLOCK CONFIGURATION REGISTERS */ | ||
196 | {MAX98090_0x1B_SYS_CLK, 0x00}, | ||
197 | {MAX98090_0x1C_CLK_MODE, 0x00}, | ||
198 | {MAX98090_0x1D_ANY_CLK1, 0x00}, | ||
199 | {MAX98090_0x1E_ANY_CLK2, 0x00}, | ||
200 | {MAX98090_0x1F_ANY_CLK3, 0x00}, | ||
201 | {MAX98090_0x20_ANY_CLK4, 0x00}, | ||
202 | {MAX98090_0x21_MASTER_MODE, 0x00}, | ||
203 | |||
204 | /* INTERFACE CONTROL REGISTERS */ | ||
205 | {MAX98090_0x22_DAI_IF_FMT, 0x00}, | ||
206 | {MAX98090_0x23_DAI_TDM_FMT1, 0x00}, | ||
207 | {MAX98090_0x24_DAI_TDM_FMT2, 0x00}, | ||
208 | {MAX98090_0x25_DAI_IO_CFG, 0x00}, | ||
209 | {MAX98090_0x26_FILTER_CFG, 0x80}, | ||
210 | {MAX98090_0x27_DAI_PLAYBACK_LVL, 0x00}, | ||
211 | {MAX98090_0x28_EQ_PLAYBACK_LVL, 0x00}, | ||
212 | |||
213 | /* HEADPHONE CONTROL REGISTERS */ | ||
214 | {MAX98090_0x29_L_HP_MIX, 0x00}, | ||
215 | {MAX98090_0x2A_R_HP_MIX, 0x00}, | ||
216 | {MAX98090_0x2B_HP_CTR, 0x00}, | ||
217 | {MAX98090_0x2C_L_HP_VOL, 0x1A}, | ||
218 | {MAX98090_0x2D_R_HP_VOL, 0x1A}, | ||
219 | |||
220 | /* SPEAKER CONFIGURATION REGISTERS */ | ||
221 | {MAX98090_0x2E_L_SPK_MIX, 0x00}, | ||
222 | {MAX98090_0x2F_R_SPK_MIX, 0x00}, | ||
223 | {MAX98090_0x30_SPK_CTR, 0x00}, | ||
224 | {MAX98090_0x31_L_SPK_VOL, 0x2C}, | ||
225 | {MAX98090_0x32_R_SPK_VOL, 0x2C}, | ||
226 | |||
227 | /* ALC CONFIGURATION REGISTERS */ | ||
228 | {MAX98090_0x33_ALC_TIMING, 0x00}, | ||
229 | {MAX98090_0x34_ALC_COMPRESSOR, 0x00}, | ||
230 | {MAX98090_0x35_ALC_EXPANDER, 0x00}, | ||
231 | {MAX98090_0x36_ALC_GAIN, 0x00}, | ||
232 | |||
233 | /* RECEIVER AND LINE_OUTPUT REGISTERS */ | ||
234 | {MAX98090_0x37_RCV_LOUT_L_MIX, 0x00}, | ||
235 | {MAX98090_0x38_RCV_LOUT_L_CNTL, 0x00}, | ||
236 | {MAX98090_0x39_RCV_LOUT_L_VOL, 0x15}, | ||
237 | {MAX98090_0x3A_LOUT_R_MIX, 0x00}, | ||
238 | {MAX98090_0x3B_LOUT_R_CNTL, 0x00}, | ||
239 | {MAX98090_0x3C_LOUT_R_VOL, 0x15}, | ||
240 | |||
241 | /* JACK DETECT AND ENABLE REGISTERS */ | ||
242 | {MAX98090_0x3D_JACK_DETECT, 0x00}, | ||
243 | {MAX98090_0x3E_IN_ENABLE, 0x00}, | ||
244 | {MAX98090_0x3F_OUT_ENABLE, 0x00}, | ||
245 | {MAX98090_0x40_LVL_CTR, 0x00}, | ||
246 | {MAX98090_0x41_DSP_FILTER_ENABLE, 0x00}, | ||
247 | |||
248 | /* BIAS AND POWER MODE CONFIGURATION REGISTERS */ | ||
249 | {MAX98090_0x42_BIAS_CTR, 0x00}, | ||
250 | {MAX98090_0x43_DAC_CTR, 0x00}, | ||
251 | {MAX98090_0x44_ADC_CTR, 0x06}, | ||
252 | {MAX98090_0x45_DEV_SHUTDOWN, 0x00}, | ||
253 | }; | ||
254 | |||
255 | static const unsigned int max98090_hp_tlv[] = { | ||
256 | TLV_DB_RANGE_HEAD(5), | ||
257 | 0x0, 0x6, TLV_DB_SCALE_ITEM(-6700, 400, 0), | ||
258 | 0x7, 0xE, TLV_DB_SCALE_ITEM(-4000, 300, 0), | ||
259 | 0xF, 0x15, TLV_DB_SCALE_ITEM(-1700, 200, 0), | ||
260 | 0x16, 0x1B, TLV_DB_SCALE_ITEM(-400, 100, 0), | ||
261 | 0x1C, 0x1F, TLV_DB_SCALE_ITEM(150, 50, 0), | ||
262 | }; | ||
263 | |||
264 | static struct snd_kcontrol_new max98090_snd_controls[] = { | ||
265 | SOC_DOUBLE_R_TLV("Headphone Volume", MAX98090_0x2C_L_HP_VOL, | ||
266 | MAX98090_0x2D_R_HP_VOL, 0, 31, 0, max98090_hp_tlv), | ||
267 | }; | ||
268 | |||
269 | /* Left HeadPhone Mixer Switch */ | ||
270 | static struct snd_kcontrol_new max98090_left_hp_mixer_controls[] = { | ||
271 | SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x29_L_HP_MIX, 1, 1, 0), | ||
272 | SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x29_L_HP_MIX, 0, 1, 0), | ||
273 | }; | ||
274 | |||
275 | /* Right HeadPhone Mixer Switch */ | ||
276 | static struct snd_kcontrol_new max98090_right_hp_mixer_controls[] = { | ||
277 | SOC_DAPM_SINGLE("DACR Switch", MAX98090_0x2A_R_HP_MIX, 1, 1, 0), | ||
278 | SOC_DAPM_SINGLE("DACL Switch", MAX98090_0x2A_R_HP_MIX, 0, 1, 0), | ||
279 | }; | ||
280 | |||
281 | static struct snd_soc_dapm_widget max98090_dapm_widgets[] = { | ||
282 | /* Output */ | ||
283 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
284 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
285 | |||
286 | /* PGA */ | ||
287 | SND_SOC_DAPM_PGA("HPL Out", MAX98090_0x3F_OUT_ENABLE, 7, 0, NULL, 0), | ||
288 | SND_SOC_DAPM_PGA("HPR Out", MAX98090_0x3F_OUT_ENABLE, 6, 0, NULL, 0), | ||
289 | |||
290 | /* Mixer */ | ||
291 | SND_SOC_DAPM_MIXER("HPL Mixer", SND_SOC_NOPM, 0, 0, | ||
292 | max98090_left_hp_mixer_controls, | ||
293 | ARRAY_SIZE(max98090_left_hp_mixer_controls)), | ||
294 | |||
295 | SND_SOC_DAPM_MIXER("HPR Mixer", SND_SOC_NOPM, 0, 0, | ||
296 | max98090_right_hp_mixer_controls, | ||
297 | ARRAY_SIZE(max98090_right_hp_mixer_controls)), | ||
298 | |||
299 | /* DAC */ | ||
300 | SND_SOC_DAPM_DAC("DACL", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 0, 0), | ||
301 | SND_SOC_DAPM_DAC("DACR", "Hifi Playback", MAX98090_0x3F_OUT_ENABLE, 1, 0), | ||
302 | }; | ||
303 | |||
304 | static struct snd_soc_dapm_route max98090_audio_map[] = { | ||
305 | /* Output */ | ||
306 | {"HPL", NULL, "HPL Out"}, | ||
307 | {"HPR", NULL, "HPR Out"}, | ||
308 | |||
309 | /* PGA */ | ||
310 | {"HPL Out", NULL, "HPL Mixer"}, | ||
311 | {"HPR Out", NULL, "HPR Mixer"}, | ||
312 | |||
313 | /* Mixer*/ | ||
314 | {"HPL Mixer", "DACR Switch", "DACR"}, | ||
315 | {"HPL Mixer", "DACL Switch", "DACL"}, | ||
316 | |||
317 | {"HPR Mixer", "DACR Switch", "DACR"}, | ||
318 | {"HPR Mixer", "DACL Switch", "DACL"}, | ||
319 | }; | ||
320 | |||
321 | static bool max98090_volatile(struct device *dev, unsigned int reg) | ||
322 | { | ||
323 | if ((reg == MAX98090_0x01_INT_STS) || | ||
324 | (reg == MAX98090_0x02_JACK_STS) || | ||
325 | (reg > MAX98090_REG_MAX_CACHED)) | ||
326 | return true; | ||
327 | |||
328 | return false; | ||
329 | } | ||
330 | |||
331 | static int max98090_dai_hw_params(struct snd_pcm_substream *substream, | ||
332 | struct snd_pcm_hw_params *params, | ||
333 | struct snd_soc_dai *dai) | ||
334 | { | ||
335 | struct snd_soc_codec *codec = dai->codec; | ||
336 | unsigned int val; | ||
337 | |||
338 | switch (params_rate(params)) { | ||
339 | case 96000: | ||
340 | val = 1 << 5; | ||
341 | break; | ||
342 | case 32000: | ||
343 | val = 1 << 4; | ||
344 | break; | ||
345 | case 48000: | ||
346 | val = 1 << 3; | ||
347 | break; | ||
348 | case 44100: | ||
349 | val = 1 << 2; | ||
350 | break; | ||
351 | case 16000: | ||
352 | val = 1 << 1; | ||
353 | break; | ||
354 | case 8000: | ||
355 | val = 1 << 0; | ||
356 | break; | ||
357 | default: | ||
358 | dev_err(codec->dev, "unsupported rate\n"); | ||
359 | return -EINVAL; | ||
360 | } | ||
361 | snd_soc_update_bits(codec, MAX98090_0x05_SAMPLE_RATE, 0x03F, val); | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int max98090_dai_set_sysclk(struct snd_soc_dai *dai, | ||
367 | int clk_id, unsigned int freq, int dir) | ||
368 | { | ||
369 | struct snd_soc_codec *codec = dai->codec; | ||
370 | unsigned int val; | ||
371 | |||
372 | snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN, | ||
373 | MAX98090_SHDNRUN, 0); | ||
374 | |||
375 | switch (freq) { | ||
376 | case 26000000: | ||
377 | val = 1 << 7; | ||
378 | break; | ||
379 | case 19200000: | ||
380 | val = 1 << 6; | ||
381 | break; | ||
382 | case 13000000: | ||
383 | val = 1 << 5; | ||
384 | break; | ||
385 | case 12288000: | ||
386 | val = 1 << 4; | ||
387 | break; | ||
388 | case 12000000: | ||
389 | val = 1 << 3; | ||
390 | break; | ||
391 | case 11289600: | ||
392 | val = 1 << 2; | ||
393 | break; | ||
394 | default: | ||
395 | dev_err(codec->dev, "Invalid master clock frequency\n"); | ||
396 | return -EINVAL; | ||
397 | } | ||
398 | snd_soc_update_bits(codec, MAX98090_0x04_SYS_CLK, 0xFD, val); | ||
399 | |||
400 | snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN, | ||
401 | MAX98090_SHDNRUN, MAX98090_SHDNRUN); | ||
402 | |||
403 | dev_dbg(dai->dev, "sysclk is %uHz\n", freq); | ||
404 | |||
405 | return 0; | ||
406 | } | ||
407 | |||
408 | static int max98090_dai_set_fmt(struct snd_soc_dai *dai, | ||
409 | unsigned int fmt) | ||
410 | { | ||
411 | struct snd_soc_codec *codec = dai->codec; | ||
412 | int is_master; | ||
413 | u8 val; | ||
414 | |||
415 | /* master/slave mode */ | ||
416 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
417 | case SND_SOC_DAIFMT_CBM_CFM: | ||
418 | is_master = 1; | ||
419 | break; | ||
420 | case SND_SOC_DAIFMT_CBS_CFS: | ||
421 | is_master = 0; | ||
422 | break; | ||
423 | default: | ||
424 | dev_err(codec->dev, "unsupported clock\n"); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | /* format */ | ||
429 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
430 | case SND_SOC_DAIFMT_I2S: | ||
431 | val = (is_master) ? MAX98090_I2S_M : MAX98090_I2S_S; | ||
432 | break; | ||
433 | case SND_SOC_DAIFMT_RIGHT_J: | ||
434 | val = (is_master) ? MAX98090_RJ_M : MAX98090_RJ_S; | ||
435 | break; | ||
436 | case SND_SOC_DAIFMT_LEFT_J: | ||
437 | val = (is_master) ? MAX98090_LJ_M : MAX98090_LJ_S; | ||
438 | break; | ||
439 | default: | ||
440 | dev_err(codec->dev, "unsupported format\n"); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | snd_soc_update_bits(codec, MAX98090_0x06_DAI_IF, | ||
444 | MAX98090_DAI_IF_MASK, val); | ||
445 | |||
446 | return 0; | ||
447 | } | ||
448 | |||
449 | #define MAX98090_RATES SNDRV_PCM_RATE_8000_96000 | ||
450 | #define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE) | ||
451 | |||
452 | static struct snd_soc_dai_ops max98090_dai_ops = { | ||
453 | .set_sysclk = max98090_dai_set_sysclk, | ||
454 | .set_fmt = max98090_dai_set_fmt, | ||
455 | .hw_params = max98090_dai_hw_params, | ||
456 | }; | ||
457 | |||
458 | static struct snd_soc_dai_driver max98090_dai = { | ||
459 | .name = "max98090-Hifi", | ||
460 | .playback = { | ||
461 | .stream_name = "Playback", | ||
462 | .channels_min = 1, | ||
463 | .channels_max = 2, | ||
464 | .rates = MAX98090_RATES, | ||
465 | .formats = MAX98090_FORMATS, | ||
466 | }, | ||
467 | .ops = &max98090_dai_ops, | ||
468 | }; | ||
469 | |||
470 | static int max98090_probe(struct snd_soc_codec *codec) | ||
471 | { | ||
472 | struct max98090_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
473 | struct device *dev = codec->dev; | ||
474 | int ret; | ||
475 | |||
476 | codec->control_data = priv->regmap; | ||
477 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP); | ||
478 | if (ret < 0) { | ||
479 | dev_err(dev, "Failed to set cache I/O: %d\n", ret); | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | /* Device active */ | ||
484 | snd_soc_update_bits(codec, MAX98090_0x45_DEV_SHUTDOWN, | ||
485 | MAX98090_SHDNRUN, MAX98090_SHDNRUN); | ||
486 | |||
487 | return 0; | ||
488 | } | ||
489 | |||
490 | static int max98090_remove(struct snd_soc_codec *codec) | ||
491 | { | ||
492 | return 0; | ||
493 | } | ||
494 | |||
495 | static struct snd_soc_codec_driver soc_codec_dev_max98090 = { | ||
496 | .probe = max98090_probe, | ||
497 | .remove = max98090_remove, | ||
498 | .controls = max98090_snd_controls, | ||
499 | .num_controls = ARRAY_SIZE(max98090_snd_controls), | ||
500 | .dapm_widgets = max98090_dapm_widgets, | ||
501 | .num_dapm_widgets = ARRAY_SIZE(max98090_dapm_widgets), | ||
502 | .dapm_routes = max98090_audio_map, | ||
503 | .num_dapm_routes = ARRAY_SIZE(max98090_audio_map), | ||
504 | }; | ||
505 | |||
506 | static const struct regmap_config max98090_regmap = { | ||
507 | .reg_bits = 8, | ||
508 | .val_bits = 8, | ||
509 | .max_register = MAX98090_REG_END, | ||
510 | .volatile_reg = max98090_volatile, | ||
511 | .cache_type = REGCACHE_RBTREE, | ||
512 | .reg_defaults = max98090_reg_defaults, | ||
513 | .num_reg_defaults = ARRAY_SIZE(max98090_reg_defaults), | ||
514 | }; | ||
515 | |||
516 | static int max98090_i2c_probe(struct i2c_client *i2c, | ||
517 | const struct i2c_device_id *id) | ||
518 | { | ||
519 | struct max98090_priv *priv; | ||
520 | struct device *dev = &i2c->dev; | ||
521 | unsigned int val; | ||
522 | int ret; | ||
523 | |||
524 | priv = devm_kzalloc(dev, sizeof(struct max98090_priv), | ||
525 | GFP_KERNEL); | ||
526 | if (!priv) | ||
527 | return -ENOMEM; | ||
528 | |||
529 | priv->regmap = devm_regmap_init_i2c(i2c, &max98090_regmap); | ||
530 | if (IS_ERR(priv->regmap)) { | ||
531 | ret = PTR_ERR(priv->regmap); | ||
532 | dev_err(dev, "Failed to init regmap: %d\n", ret); | ||
533 | return ret; | ||
534 | } | ||
535 | |||
536 | i2c_set_clientdata(i2c, priv); | ||
537 | |||
538 | ret = regmap_read(priv->regmap, MAX98090_0xFF_REV_ID, &val); | ||
539 | if (ret < 0) { | ||
540 | dev_err(dev, "Failed to read device revision: %d\n", ret); | ||
541 | return ret; | ||
542 | } | ||
543 | dev_info(dev, "revision 0x%02x\n", val); | ||
544 | |||
545 | ret = snd_soc_register_codec(dev, | ||
546 | &soc_codec_dev_max98090, | ||
547 | &max98090_dai, 1); | ||
548 | |||
549 | return ret; | ||
550 | } | ||
551 | |||
552 | static int max98090_i2c_remove(struct i2c_client *client) | ||
553 | { | ||
554 | snd_soc_unregister_codec(&client->dev); | ||
555 | return 0; | ||
556 | } | ||
557 | |||
558 | static const struct i2c_device_id max98090_i2c_id[] = { | ||
559 | { "max98090", 0 }, | ||
560 | { } | ||
561 | }; | ||
562 | MODULE_DEVICE_TABLE(i2c, max98090_i2c_id); | ||
563 | |||
564 | static struct i2c_driver max98090_i2c_driver = { | ||
565 | .driver = { | ||
566 | .name = "max98090", | ||
567 | .owner = THIS_MODULE, | ||
568 | }, | ||
569 | .probe = max98090_i2c_probe, | ||
570 | .remove = max98090_i2c_remove, | ||
571 | .id_table = max98090_i2c_id, | ||
572 | }; | ||
573 | module_i2c_driver(max98090_i2c_driver); | ||
574 | |||
575 | MODULE_DESCRIPTION("ALSA SoC MAX98090 driver"); | ||
576 | MODULE_AUTHOR("Peter Hsiang, Kuninori Morimoto"); | ||
577 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 960d0e93cce9..d6ca615489ee 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c | |||
@@ -1382,7 +1382,7 @@ static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream, | |||
1382 | timesofbclk); | 1382 | timesofbclk); |
1383 | if (coeff < 0) { | 1383 | if (coeff < 0) { |
1384 | dev_err(codec->dev, "Fail to get coeff\n"); | 1384 | dev_err(codec->dev, "Fail to get coeff\n"); |
1385 | return -EINVAL; | 1385 | return coeff; |
1386 | } | 1386 | } |
1387 | 1387 | ||
1388 | switch (params_format(params)) { | 1388 | switch (params_format(params)) { |
diff --git a/sound/soc/codecs/si476x.c b/sound/soc/codecs/si476x.c new file mode 100644 index 000000000000..38145ba74db8 --- /dev/null +++ b/sound/soc/codecs/si476x.c | |||
@@ -0,0 +1,255 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/slab.h> | ||
3 | #include <sound/pcm.h> | ||
4 | #include <sound/pcm_params.h> | ||
5 | #include <sound/soc.h> | ||
6 | #include <sound/initval.h> | ||
7 | |||
8 | #include <linux/i2c.h> | ||
9 | |||
10 | #include <linux/mfd/si476x-core.h> | ||
11 | |||
12 | enum si476x_audio_registers { | ||
13 | SI476X_DIGITAL_IO_OUTPUT_FORMAT = 0x0203, | ||
14 | SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE = 0x0202, | ||
15 | }; | ||
16 | |||
17 | enum si476x_digital_io_output_format { | ||
18 | SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT = 11, | ||
19 | SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT = 8, | ||
20 | }; | ||
21 | |||
22 | #define SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK ((0b111 << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | \ | ||
23 | (0b111 << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)) | ||
24 | #define SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK (0b1111110) | ||
25 | |||
26 | enum si476x_daudio_formats { | ||
27 | SI476X_DAUDIO_MODE_I2S = (0x0 << 1), | ||
28 | SI476X_DAUDIO_MODE_DSP_A = (0x6 << 1), | ||
29 | SI476X_DAUDIO_MODE_DSP_B = (0x7 << 1), | ||
30 | SI476X_DAUDIO_MODE_LEFT_J = (0x8 << 1), | ||
31 | SI476X_DAUDIO_MODE_RIGHT_J = (0x9 << 1), | ||
32 | |||
33 | SI476X_DAUDIO_MODE_IB = (1 << 5), | ||
34 | SI476X_DAUDIO_MODE_IF = (1 << 6), | ||
35 | }; | ||
36 | |||
37 | enum si476x_pcm_format { | ||
38 | SI476X_PCM_FORMAT_S8 = 2, | ||
39 | SI476X_PCM_FORMAT_S16_LE = 4, | ||
40 | SI476X_PCM_FORMAT_S20_3LE = 5, | ||
41 | SI476X_PCM_FORMAT_S24_LE = 6, | ||
42 | }; | ||
43 | |||
44 | static unsigned int si476x_codec_read(struct snd_soc_codec *codec, | ||
45 | unsigned int reg) | ||
46 | { | ||
47 | int err; | ||
48 | struct si476x_core *core = codec->control_data; | ||
49 | |||
50 | si476x_core_lock(core); | ||
51 | err = si476x_core_cmd_get_property(core, reg); | ||
52 | si476x_core_unlock(core); | ||
53 | |||
54 | return err; | ||
55 | } | ||
56 | |||
57 | static int si476x_codec_write(struct snd_soc_codec *codec, | ||
58 | unsigned int reg, unsigned int val) | ||
59 | { | ||
60 | int err; | ||
61 | struct si476x_core *core = codec->control_data; | ||
62 | |||
63 | si476x_core_lock(core); | ||
64 | err = si476x_core_cmd_set_property(core, reg, val); | ||
65 | si476x_core_unlock(core); | ||
66 | |||
67 | return err; | ||
68 | } | ||
69 | |||
70 | static int si476x_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, | ||
71 | unsigned int fmt) | ||
72 | { | ||
73 | int err; | ||
74 | u16 format = 0; | ||
75 | |||
76 | if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) | ||
77 | return -EINVAL; | ||
78 | |||
79 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
80 | case SND_SOC_DAIFMT_DSP_A: | ||
81 | format |= SI476X_DAUDIO_MODE_DSP_A; | ||
82 | break; | ||
83 | case SND_SOC_DAIFMT_DSP_B: | ||
84 | format |= SI476X_DAUDIO_MODE_DSP_B; | ||
85 | break; | ||
86 | case SND_SOC_DAIFMT_I2S: | ||
87 | format |= SI476X_DAUDIO_MODE_I2S; | ||
88 | break; | ||
89 | case SND_SOC_DAIFMT_RIGHT_J: | ||
90 | format |= SI476X_DAUDIO_MODE_RIGHT_J; | ||
91 | break; | ||
92 | case SND_SOC_DAIFMT_LEFT_J: | ||
93 | format |= SI476X_DAUDIO_MODE_LEFT_J; | ||
94 | break; | ||
95 | default: | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | |||
99 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
100 | case SND_SOC_DAIFMT_DSP_A: | ||
101 | case SND_SOC_DAIFMT_DSP_B: | ||
102 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
103 | case SND_SOC_DAIFMT_NB_NF: | ||
104 | break; | ||
105 | case SND_SOC_DAIFMT_IB_NF: | ||
106 | format |= SI476X_DAUDIO_MODE_IB; | ||
107 | break; | ||
108 | default: | ||
109 | return -EINVAL; | ||
110 | } | ||
111 | break; | ||
112 | case SND_SOC_DAIFMT_I2S: | ||
113 | case SND_SOC_DAIFMT_RIGHT_J: | ||
114 | case SND_SOC_DAIFMT_LEFT_J: | ||
115 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
116 | case SND_SOC_DAIFMT_NB_NF: | ||
117 | break; | ||
118 | case SND_SOC_DAIFMT_IB_IF: | ||
119 | format |= SI476X_DAUDIO_MODE_IB | | ||
120 | SI476X_DAUDIO_MODE_IF; | ||
121 | break; | ||
122 | case SND_SOC_DAIFMT_IB_NF: | ||
123 | format |= SI476X_DAUDIO_MODE_IB; | ||
124 | break; | ||
125 | case SND_SOC_DAIFMT_NB_IF: | ||
126 | format |= SI476X_DAUDIO_MODE_IF; | ||
127 | break; | ||
128 | default: | ||
129 | return -EINVAL; | ||
130 | } | ||
131 | break; | ||
132 | default: | ||
133 | return -EINVAL; | ||
134 | } | ||
135 | |||
136 | err = snd_soc_update_bits(codec_dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, | ||
137 | SI476X_DIGITAL_IO_OUTPUT_FORMAT_MASK, | ||
138 | format); | ||
139 | if (err < 0) { | ||
140 | dev_err(codec_dai->codec->dev, "Failed to set output format\n"); | ||
141 | return err; | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static int si476x_codec_hw_params(struct snd_pcm_substream *substream, | ||
148 | struct snd_pcm_hw_params *params, | ||
149 | struct snd_soc_dai *dai) | ||
150 | { | ||
151 | int rate, width, err; | ||
152 | |||
153 | rate = params_rate(params); | ||
154 | if (rate < 32000 || rate > 48000) { | ||
155 | dev_err(dai->codec->dev, "Rate: %d is not supported\n", rate); | ||
156 | return -EINVAL; | ||
157 | } | ||
158 | |||
159 | switch (params_format(params)) { | ||
160 | case SNDRV_PCM_FORMAT_S8: | ||
161 | width = SI476X_PCM_FORMAT_S8; | ||
162 | case SNDRV_PCM_FORMAT_S16_LE: | ||
163 | width = SI476X_PCM_FORMAT_S16_LE; | ||
164 | break; | ||
165 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
166 | width = SI476X_PCM_FORMAT_S20_3LE; | ||
167 | break; | ||
168 | case SNDRV_PCM_FORMAT_S24_LE: | ||
169 | width = SI476X_PCM_FORMAT_S24_LE; | ||
170 | break; | ||
171 | default: | ||
172 | return -EINVAL; | ||
173 | } | ||
174 | |||
175 | err = snd_soc_write(dai->codec, SI476X_DIGITAL_IO_OUTPUT_SAMPLE_RATE, | ||
176 | rate); | ||
177 | if (err < 0) { | ||
178 | dev_err(dai->codec->dev, "Failed to set sample rate\n"); | ||
179 | return err; | ||
180 | } | ||
181 | |||
182 | err = snd_soc_update_bits(dai->codec, SI476X_DIGITAL_IO_OUTPUT_FORMAT, | ||
183 | SI476X_DIGITAL_IO_OUTPUT_WIDTH_MASK, | ||
184 | (width << SI476X_DIGITAL_IO_SLOT_SIZE_SHIFT) | | ||
185 | (width << SI476X_DIGITAL_IO_SAMPLE_SIZE_SHIFT)); | ||
186 | if (err < 0) { | ||
187 | dev_err(dai->codec->dev, "Failed to set output width\n"); | ||
188 | return err; | ||
189 | } | ||
190 | |||
191 | return 0; | ||
192 | } | ||
193 | |||
194 | static int si476x_codec_probe(struct snd_soc_codec *codec) | ||
195 | { | ||
196 | codec->control_data = i2c_mfd_cell_to_core(codec->dev); | ||
197 | return 0; | ||
198 | } | ||
199 | |||
200 | static struct snd_soc_dai_ops si476x_dai_ops = { | ||
201 | .hw_params = si476x_codec_hw_params, | ||
202 | .set_fmt = si476x_codec_set_dai_fmt, | ||
203 | }; | ||
204 | |||
205 | static struct snd_soc_dai_driver si476x_dai = { | ||
206 | .name = "si476x-codec", | ||
207 | .capture = { | ||
208 | .stream_name = "Capture", | ||
209 | .channels_min = 2, | ||
210 | .channels_max = 2, | ||
211 | |||
212 | .rates = SNDRV_PCM_RATE_32000 | | ||
213 | SNDRV_PCM_RATE_44100 | | ||
214 | SNDRV_PCM_RATE_48000, | ||
215 | .formats = SNDRV_PCM_FMTBIT_S8 | | ||
216 | SNDRV_PCM_FMTBIT_S16_LE | | ||
217 | SNDRV_PCM_FMTBIT_S20_3LE | | ||
218 | SNDRV_PCM_FMTBIT_S24_LE | ||
219 | }, | ||
220 | .ops = &si476x_dai_ops, | ||
221 | }; | ||
222 | |||
223 | static struct snd_soc_codec_driver soc_codec_dev_si476x = { | ||
224 | .probe = si476x_codec_probe, | ||
225 | .read = si476x_codec_read, | ||
226 | .write = si476x_codec_write, | ||
227 | }; | ||
228 | |||
229 | static int __devinit si476x_platform_probe(struct platform_device *pdev) | ||
230 | { | ||
231 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_si476x, | ||
232 | &si476x_dai, 1); | ||
233 | } | ||
234 | |||
235 | static int __devexit si476x_platform_remove(struct platform_device *pdev) | ||
236 | { | ||
237 | snd_soc_unregister_codec(&pdev->dev); | ||
238 | return 0; | ||
239 | } | ||
240 | |||
241 | MODULE_ALIAS("platform:si476x-codec"); | ||
242 | |||
243 | static struct platform_driver si476x_platform_driver = { | ||
244 | .driver = { | ||
245 | .name = "si476x-codec", | ||
246 | .owner = THIS_MODULE, | ||
247 | }, | ||
248 | .probe = si476x_platform_probe, | ||
249 | .remove = __devexit_p(si476x_platform_remove), | ||
250 | }; | ||
251 | module_platform_driver(si476x_platform_driver); | ||
252 | |||
253 | MODULE_AUTHOR("Andrey Smirnov <andrey.smirnov@convergeddevices.net>"); | ||
254 | MODULE_DESCRIPTION("ASoC Si4761/64 codec driver"); | ||
255 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index f230292ba96b..e39e08d5d8e4 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 30 | #include <linux/pm.h> |
31 | #include <linux/gpio.h> | ||
31 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
32 | #include <linux/cdev.h> | 33 | #include <linux/cdev.h> |
33 | #include <linux/slab.h> | 34 | #include <linux/slab.h> |
@@ -65,6 +66,7 @@ struct aic32x4_priv { | |||
65 | u32 power_cfg; | 66 | u32 power_cfg; |
66 | u32 micpga_routing; | 67 | u32 micpga_routing; |
67 | bool swapdacs; | 68 | bool swapdacs; |
69 | int rstn_gpio; | ||
68 | }; | 70 | }; |
69 | 71 | ||
70 | /* 0dB min, 1dB steps */ | 72 | /* 0dB min, 1dB steps */ |
@@ -627,10 +629,20 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
627 | { | 629 | { |
628 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); | 630 | struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec); |
629 | u32 tmp_reg; | 631 | u32 tmp_reg; |
632 | int ret; | ||
630 | 633 | ||
631 | codec->hw_write = (hw_write_t) i2c_master_send; | 634 | codec->hw_write = (hw_write_t) i2c_master_send; |
632 | codec->control_data = aic32x4->control_data; | 635 | codec->control_data = aic32x4->control_data; |
633 | 636 | ||
637 | if (aic32x4->rstn_gpio >= 0) { | ||
638 | ret = devm_gpio_request_one(codec->dev, aic32x4->rstn_gpio, | ||
639 | GPIOF_OUT_INIT_LOW, "tlv320aic32x4 rstn"); | ||
640 | if (ret != 0) | ||
641 | return ret; | ||
642 | ndelay(10); | ||
643 | gpio_set_value(aic32x4->rstn_gpio, 1); | ||
644 | } | ||
645 | |||
634 | snd_soc_write(codec, AIC32X4_RESET, 0x01); | 646 | snd_soc_write(codec, AIC32X4_RESET, 0x01); |
635 | 647 | ||
636 | /* Power platform configuration */ | 648 | /* Power platform configuration */ |
@@ -675,6 +687,16 @@ static int aic32x4_probe(struct snd_soc_codec *codec) | |||
675 | ARRAY_SIZE(aic32x4_snd_controls)); | 687 | ARRAY_SIZE(aic32x4_snd_controls)); |
676 | aic32x4_add_widgets(codec); | 688 | aic32x4_add_widgets(codec); |
677 | 689 | ||
690 | /* | ||
691 | * Workaround: for an unknown reason, the ADC needs to be powered up | ||
692 | * and down for the first capture to work properly. It seems related to | ||
693 | * a HW BUG or some kind of behavior not documented in the datasheet. | ||
694 | */ | ||
695 | tmp_reg = snd_soc_read(codec, AIC32X4_ADCSETUP); | ||
696 | snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg | | ||
697 | AIC32X4_LADC_EN | AIC32X4_RADC_EN); | ||
698 | snd_soc_write(codec, AIC32X4_ADCSETUP, tmp_reg); | ||
699 | |||
678 | return 0; | 700 | return 0; |
679 | } | 701 | } |
680 | 702 | ||
@@ -713,10 +735,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c, | |||
713 | aic32x4->power_cfg = pdata->power_cfg; | 735 | aic32x4->power_cfg = pdata->power_cfg; |
714 | aic32x4->swapdacs = pdata->swapdacs; | 736 | aic32x4->swapdacs = pdata->swapdacs; |
715 | aic32x4->micpga_routing = pdata->micpga_routing; | 737 | aic32x4->micpga_routing = pdata->micpga_routing; |
738 | aic32x4->rstn_gpio = pdata->rstn_gpio; | ||
716 | } else { | 739 | } else { |
717 | aic32x4->power_cfg = 0; | 740 | aic32x4->power_cfg = 0; |
718 | aic32x4->swapdacs = false; | 741 | aic32x4->swapdacs = false; |
719 | aic32x4->micpga_routing = 0; | 742 | aic32x4->micpga_routing = 0; |
743 | aic32x4->rstn_gpio = -1; | ||
720 | } | 744 | } |
721 | 745 | ||
722 | ret = snd_soc_register_codec(&i2c->dev, | 746 | ret = snd_soc_register_codec(&i2c->dev, |
diff --git a/sound/soc/codecs/tlv320aic32x4.h b/sound/soc/codecs/tlv320aic32x4.h index aae2b2440398..35774223fd91 100644 --- a/sound/soc/codecs/tlv320aic32x4.h +++ b/sound/soc/codecs/tlv320aic32x4.h | |||
@@ -94,6 +94,9 @@ | |||
94 | #define AIC32X4_WORD_LEN_24BITS 0x02 | 94 | #define AIC32X4_WORD_LEN_24BITS 0x02 |
95 | #define AIC32X4_WORD_LEN_32BITS 0x03 | 95 | #define AIC32X4_WORD_LEN_32BITS 0x03 |
96 | 96 | ||
97 | #define AIC32X4_LADC_EN (1 << 7) | ||
98 | #define AIC32X4_RADC_EN (1 << 6) | ||
99 | |||
97 | #define AIC32X4_I2S_MODE 0x00 | 100 | #define AIC32X4_I2S_MODE 0x00 |
98 | #define AIC32X4_DSP_MODE 0x01 | 101 | #define AIC32X4_DSP_MODE 0x01 |
99 | #define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02 | 102 | #define AIC32X4_RIGHT_JUSTIFIED_MODE 0x02 |
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c index 99afc003a084..40256b526259 100644 --- a/sound/soc/codecs/wm0010.c +++ b/sound/soc/codecs/wm0010.c | |||
@@ -31,6 +31,9 @@ | |||
31 | 31 | ||
32 | #define DEVICE_ID_WM0010 10 | 32 | #define DEVICE_ID_WM0010 10 |
33 | 33 | ||
34 | /* We only support v1 of the .dfw INFO record */ | ||
35 | #define INFO_VERSION 1 | ||
36 | |||
34 | enum dfw_cmd { | 37 | enum dfw_cmd { |
35 | DFW_CMD_FUSE = 0x01, | 38 | DFW_CMD_FUSE = 0x01, |
36 | DFW_CMD_CODE_HDR, | 39 | DFW_CMD_CODE_HDR, |
@@ -46,6 +49,13 @@ struct dfw_binrec { | |||
46 | uint8_t data[0]; | 49 | uint8_t data[0]; |
47 | } __packed; | 50 | } __packed; |
48 | 51 | ||
52 | struct dfw_inforec { | ||
53 | u8 info_version; | ||
54 | u8 tool_major_version; | ||
55 | u8 tool_minor_version; | ||
56 | u8 dsp_target; | ||
57 | }; | ||
58 | |||
49 | struct dfw_pllrec { | 59 | struct dfw_pllrec { |
50 | u8 command; | 60 | u8 command; |
51 | u32 length:24; | 61 | u32 length:24; |
@@ -97,7 +107,6 @@ struct wm0010_priv { | |||
97 | 107 | ||
98 | enum wm0010_state state; | 108 | enum wm0010_state state; |
99 | bool boot_failed; | 109 | bool boot_failed; |
100 | int boot_done; | ||
101 | bool ready; | 110 | bool ready; |
102 | bool pll_running; | 111 | bool pll_running; |
103 | int max_spi_freq; | 112 | int max_spi_freq; |
@@ -234,7 +243,7 @@ static void wm0010_boot_xfer_complete(void *data) | |||
234 | break; | 243 | break; |
235 | 244 | ||
236 | case 0x55555555: | 245 | case 0x55555555: |
237 | if (wm0010->boot_done == 0) | 246 | if (wm0010->state < WM0010_STAGE2) |
238 | break; | 247 | break; |
239 | dev_err(codec->dev, | 248 | dev_err(codec->dev, |
240 | "%d: ROM bootloader running in stage 2\n", i); | 249 | "%d: ROM bootloader running in stage 2\n", i); |
@@ -321,7 +330,6 @@ static void wm0010_boot_xfer_complete(void *data) | |||
321 | break; | 330 | break; |
322 | } | 331 | } |
323 | 332 | ||
324 | wm0010->boot_done++; | ||
325 | if (xfer->done) | 333 | if (xfer->done) |
326 | complete(xfer->done); | 334 | complete(xfer->done); |
327 | } | 335 | } |
@@ -334,94 +342,198 @@ static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) | |||
334 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); | 342 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); |
335 | } | 343 | } |
336 | 344 | ||
337 | static int wm0010_boot(struct snd_soc_codec *codec) | 345 | static int wm0010_firmware_load(char *name, struct snd_soc_codec *codec) |
338 | { | 346 | { |
339 | struct spi_device *spi = to_spi_device(codec->dev); | 347 | struct spi_device *spi = to_spi_device(codec->dev); |
340 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | 348 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); |
341 | unsigned long flags; | ||
342 | struct list_head xfer_list; | 349 | struct list_head xfer_list; |
343 | struct wm0010_boot_xfer *xfer; | 350 | struct wm0010_boot_xfer *xfer; |
344 | int ret; | 351 | int ret; |
345 | struct completion done; | 352 | struct completion done; |
346 | const struct firmware *fw; | 353 | const struct firmware *fw; |
347 | const struct dfw_binrec *rec; | 354 | const struct dfw_binrec *rec; |
348 | struct spi_message m; | 355 | const struct dfw_inforec *inforec; |
349 | struct spi_transfer t; | 356 | u64 *img; |
350 | struct dfw_pllrec pll_rec; | 357 | u8 *out, dsp; |
351 | u32 *img, *p; | ||
352 | u64 *img_swap; | ||
353 | u8 *out; | ||
354 | u32 len, offset; | 358 | u32 len, offset; |
355 | int i; | ||
356 | 359 | ||
357 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 360 | INIT_LIST_HEAD(&xfer_list); |
358 | if (wm0010->state != WM0010_POWER_OFF) | ||
359 | dev_warn(wm0010->dev, "DSP already powered up!\n"); | ||
360 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
361 | 361 | ||
362 | if (wm0010->sysclk > 26000000) { | 362 | ret = request_firmware(&fw, name, codec->dev); |
363 | dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); | 363 | if (ret != 0) { |
364 | ret = -ECANCELED; | 364 | dev_err(codec->dev, "Failed to request application: %d\n", |
365 | goto err; | 365 | ret); |
366 | return ret; | ||
366 | } | 367 | } |
367 | 368 | ||
368 | INIT_LIST_HEAD(&xfer_list); | 369 | rec = (const struct dfw_binrec *)fw->data; |
370 | inforec = (const struct dfw_inforec *)rec->data; | ||
371 | offset = 0; | ||
372 | dsp = inforec->dsp_target; | ||
373 | wm0010->boot_failed = false; | ||
374 | BUG_ON(!list_empty(&xfer_list)); | ||
375 | init_completion(&done); | ||
369 | 376 | ||
370 | mutex_lock(&wm0010->lock); | 377 | /* First record should be INFO */ |
371 | wm0010->pll_running = false; | 378 | if (rec->command != DFW_CMD_INFO) { |
379 | dev_err(codec->dev, "First record not INFO\r\n"); | ||
380 | ret = -EINVAL; | ||
381 | goto abort; | ||
382 | } | ||
372 | 383 | ||
373 | dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); | 384 | if (inforec->info_version != INFO_VERSION) { |
385 | dev_err(codec->dev, | ||
386 | "Unsupported version (%02d) of INFO record\r\n", | ||
387 | inforec->info_version); | ||
388 | ret = -EINVAL; | ||
389 | goto abort; | ||
390 | } | ||
374 | 391 | ||
375 | ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), | 392 | dev_dbg(codec->dev, "Version v%02d INFO record found\r\n", |
376 | wm0010->core_supplies); | 393 | inforec->info_version); |
377 | if (ret != 0) { | 394 | |
378 | dev_err(&spi->dev, "Failed to enable core supplies: %d\n", | 395 | /* Check it's a DSP file */ |
379 | ret); | 396 | if (dsp != DEVICE_ID_WM0010) { |
380 | mutex_unlock(&wm0010->lock); | 397 | dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); |
381 | goto err; | 398 | ret = -EINVAL; |
399 | goto abort; | ||
382 | } | 400 | } |
383 | 401 | ||
384 | ret = regulator_enable(wm0010->dbvdd); | 402 | /* Skip the info record as we don't need to send it */ |
385 | if (ret != 0) { | 403 | offset += ((rec->length) + 8); |
386 | dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); | 404 | rec = (void *)&rec->data[rec->length]; |
387 | goto err_core; | 405 | |
406 | while (offset < fw->size) { | ||
407 | dev_dbg(codec->dev, | ||
408 | "Packet: command %d, data length = 0x%x\r\n", | ||
409 | rec->command, rec->length); | ||
410 | len = rec->length + 8; | ||
411 | |||
412 | out = kzalloc(len, GFP_KERNEL); | ||
413 | if (!out) { | ||
414 | dev_err(codec->dev, | ||
415 | "Failed to allocate RX buffer\n"); | ||
416 | ret = -ENOMEM; | ||
417 | goto abort1; | ||
418 | } | ||
419 | |||
420 | img = kzalloc(len, GFP_KERNEL); | ||
421 | if (!img) { | ||
422 | dev_err(codec->dev, | ||
423 | "Failed to allocate image buffer\n"); | ||
424 | ret = -ENOMEM; | ||
425 | goto abort1; | ||
426 | } | ||
427 | |||
428 | byte_swap_64((u64 *)&rec->command, img, len); | ||
429 | |||
430 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | ||
431 | if (!xfer) { | ||
432 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
433 | ret = -ENOMEM; | ||
434 | goto abort1; | ||
435 | } | ||
436 | |||
437 | xfer->codec = codec; | ||
438 | list_add_tail(&xfer->list, &xfer_list); | ||
439 | |||
440 | spi_message_init(&xfer->m); | ||
441 | xfer->m.complete = wm0010_boot_xfer_complete; | ||
442 | xfer->m.context = xfer; | ||
443 | xfer->t.tx_buf = img; | ||
444 | xfer->t.rx_buf = out; | ||
445 | xfer->t.len = len; | ||
446 | xfer->t.bits_per_word = 8; | ||
447 | |||
448 | if (!wm0010->pll_running) { | ||
449 | xfer->t.speed_hz = wm0010->sysclk / 6; | ||
450 | } else { | ||
451 | xfer->t.speed_hz = wm0010->max_spi_freq; | ||
452 | |||
453 | if (wm0010->board_max_spi_speed && | ||
454 | (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) | ||
455 | xfer->t.speed_hz = wm0010->board_max_spi_speed; | ||
456 | } | ||
457 | |||
458 | /* Store max usable spi frequency for later use */ | ||
459 | wm0010->max_spi_freq = xfer->t.speed_hz; | ||
460 | |||
461 | spi_message_add_tail(&xfer->t, &xfer->m); | ||
462 | |||
463 | offset += ((rec->length) + 8); | ||
464 | rec = (void *)&rec->data[rec->length]; | ||
465 | |||
466 | if (offset >= fw->size) { | ||
467 | dev_dbg(codec->dev, "All transfers scheduled\n"); | ||
468 | xfer->done = &done; | ||
469 | } | ||
470 | |||
471 | ret = spi_async(spi, &xfer->m); | ||
472 | if (ret != 0) { | ||
473 | dev_err(codec->dev, "Write failed: %d\n", ret); | ||
474 | goto abort1; | ||
475 | } | ||
476 | |||
477 | if (wm0010->boot_failed) { | ||
478 | dev_dbg(codec->dev, "Boot fail!\n"); | ||
479 | ret = -EINVAL; | ||
480 | goto abort1; | ||
481 | } | ||
388 | } | 482 | } |
389 | 483 | ||
390 | /* Release reset */ | 484 | wait_for_completion(&done); |
391 | gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); | 485 | |
392 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 486 | ret = 0; |
393 | wm0010->state = WM0010_OUT_OF_RESET; | 487 | |
394 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | 488 | abort1: |
489 | while (!list_empty(&xfer_list)) { | ||
490 | xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, | ||
491 | list); | ||
492 | kfree(xfer->t.rx_buf); | ||
493 | kfree(xfer->t.tx_buf); | ||
494 | list_del(&xfer->list); | ||
495 | kfree(xfer); | ||
496 | } | ||
497 | |||
498 | abort: | ||
499 | release_firmware(fw); | ||
500 | return ret; | ||
501 | } | ||
502 | |||
503 | static int wm0010_stage2_load(struct snd_soc_codec *codec) | ||
504 | { | ||
505 | struct spi_device *spi = to_spi_device(codec->dev); | ||
506 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
507 | const struct firmware *fw; | ||
508 | struct spi_message m; | ||
509 | struct spi_transfer t; | ||
510 | u32 *img; | ||
511 | u8 *out; | ||
512 | int i; | ||
513 | int ret = 0; | ||
395 | 514 | ||
396 | /* First the bootloader */ | ||
397 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | 515 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); |
398 | if (ret != 0) { | 516 | if (ret != 0) { |
399 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | 517 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", |
400 | ret); | 518 | ret); |
401 | goto abort; | 519 | return ret; |
402 | } | 520 | } |
403 | 521 | ||
404 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
405 | msecs_to_jiffies(10))) | ||
406 | dev_err(codec->dev, "Failed to get interrupt from DSP\n"); | ||
407 | |||
408 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
409 | wm0010->state = WM0010_BOOTROM; | ||
410 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
411 | |||
412 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); | 522 | dev_dbg(codec->dev, "Downloading %zu byte stage 2 loader\n", fw->size); |
413 | 523 | ||
414 | /* Copy to local buffer first as vmalloc causes problems for dma */ | 524 | /* Copy to local buffer first as vmalloc causes problems for dma */ |
415 | img = kzalloc(fw->size, GFP_KERNEL); | 525 | img = kzalloc(fw->size, GFP_KERNEL); |
416 | if (!img) { | 526 | if (!img) { |
417 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | 527 | dev_err(codec->dev, "Failed to allocate image buffer\n"); |
418 | goto abort; | 528 | ret = -ENOMEM; |
529 | goto abort2; | ||
419 | } | 530 | } |
420 | 531 | ||
421 | out = kzalloc(fw->size, GFP_KERNEL); | 532 | out = kzalloc(fw->size, GFP_KERNEL); |
422 | if (!out) { | 533 | if (!out) { |
423 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | 534 | dev_err(codec->dev, "Failed to allocate output buffer\n"); |
424 | goto abort; | 535 | ret = -ENOMEM; |
536 | goto abort1; | ||
425 | } | 537 | } |
426 | 538 | ||
427 | memcpy(img, &fw->data[0], fw->size); | 539 | memcpy(img, &fw->data[0], fw->size); |
@@ -447,20 +559,97 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
447 | /* Look for errors from the boot ROM */ | 559 | /* Look for errors from the boot ROM */ |
448 | for (i = 0; i < fw->size; i++) { | 560 | for (i = 0; i < fw->size; i++) { |
449 | if (out[i] != 0x55) { | 561 | if (out[i] != 0x55) { |
450 | ret = -EBUSY; | ||
451 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | 562 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", |
452 | out[i], i); | 563 | out[i], i); |
453 | wm0010_mark_boot_failure(wm0010); | 564 | wm0010_mark_boot_failure(wm0010); |
565 | ret = -EBUSY; | ||
454 | goto abort; | 566 | goto abort; |
455 | } | 567 | } |
456 | } | 568 | } |
457 | 569 | abort: | |
458 | release_firmware(fw); | ||
459 | kfree(img); | ||
460 | kfree(out); | 570 | kfree(out); |
571 | abort1: | ||
572 | kfree(img); | ||
573 | abort2: | ||
574 | release_firmware(fw); | ||
575 | |||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int wm0010_boot(struct snd_soc_codec *codec) | ||
580 | { | ||
581 | struct spi_device *spi = to_spi_device(codec->dev); | ||
582 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
583 | unsigned long flags; | ||
584 | int ret; | ||
585 | const struct firmware *fw; | ||
586 | struct spi_message m; | ||
587 | struct spi_transfer t; | ||
588 | struct dfw_pllrec pll_rec; | ||
589 | u32 *p, len; | ||
590 | u64 *img_swap; | ||
591 | u8 *out; | ||
592 | int i; | ||
593 | |||
594 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
595 | if (wm0010->state != WM0010_POWER_OFF) | ||
596 | dev_warn(wm0010->dev, "DSP already powered up!\n"); | ||
597 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
598 | |||
599 | if (wm0010->sysclk > 26000000) { | ||
600 | dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); | ||
601 | ret = -ECANCELED; | ||
602 | goto err; | ||
603 | } | ||
604 | |||
605 | mutex_lock(&wm0010->lock); | ||
606 | wm0010->pll_running = false; | ||
607 | |||
608 | dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); | ||
609 | |||
610 | ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), | ||
611 | wm0010->core_supplies); | ||
612 | if (ret != 0) { | ||
613 | dev_err(&spi->dev, "Failed to enable core supplies: %d\n", | ||
614 | ret); | ||
615 | mutex_unlock(&wm0010->lock); | ||
616 | goto err; | ||
617 | } | ||
618 | |||
619 | ret = regulator_enable(wm0010->dbvdd); | ||
620 | if (ret != 0) { | ||
621 | dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); | ||
622 | goto err_core; | ||
623 | } | ||
624 | |||
625 | /* Release reset */ | ||
626 | gpio_set_value_cansleep(wm0010->gpio_reset, !wm0010->gpio_reset_value); | ||
627 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
628 | wm0010->state = WM0010_OUT_OF_RESET; | ||
629 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
630 | |||
631 | /* First the bootloader */ | ||
632 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | ||
633 | if (ret != 0) { | ||
634 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | ||
635 | ret); | ||
636 | goto abort; | ||
637 | } | ||
638 | |||
639 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
640 | msecs_to_jiffies(20))) | ||
641 | dev_err(codec->dev, "Failed to get interrupt from DSP\n"); | ||
642 | |||
643 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
644 | wm0010->state = WM0010_BOOTROM; | ||
645 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
646 | |||
647 | ret = wm0010_stage2_load(codec); | ||
648 | if (ret) | ||
649 | goto abort; | ||
461 | 650 | ||
462 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | 651 | if (!wait_for_completion_timeout(&wm0010->boot_completion, |
463 | msecs_to_jiffies(10))) | 652 | msecs_to_jiffies(20))) |
464 | dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); | 653 | dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); |
465 | 654 | ||
466 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 655 | spin_lock_irqsave(&wm0010->irq_lock, flags); |
@@ -535,110 +724,10 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
535 | } else | 724 | } else |
536 | dev_dbg(codec->dev, "Not enabling DSP PLL."); | 725 | dev_dbg(codec->dev, "Not enabling DSP PLL."); |
537 | 726 | ||
538 | ret = request_firmware(&fw, "wm0010.dfw", codec->dev); | 727 | ret = wm0010_firmware_load("wm0010.dfw", codec); |
539 | if (ret != 0) { | ||
540 | dev_err(codec->dev, "Failed to request application: %d\n", | ||
541 | ret); | ||
542 | goto abort; | ||
543 | } | ||
544 | |||
545 | rec = (const struct dfw_binrec *)fw->data; | ||
546 | offset = 0; | ||
547 | wm0010->boot_done = 0; | ||
548 | wm0010->boot_failed = false; | ||
549 | BUG_ON(!list_empty(&xfer_list)); | ||
550 | init_completion(&done); | ||
551 | 728 | ||
552 | /* First record should be INFO */ | 729 | if (ret != 0) |
553 | if (rec->command != DFW_CMD_INFO) { | ||
554 | dev_err(codec->dev, "First record not INFO\r\n"); | ||
555 | goto abort; | ||
556 | } | ||
557 | |||
558 | /* Check it's a 0010 file */ | ||
559 | if (rec->data[0] != DEVICE_ID_WM0010) { | ||
560 | dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); | ||
561 | goto abort; | 730 | goto abort; |
562 | } | ||
563 | |||
564 | /* Skip the info record as we don't need to send it */ | ||
565 | offset += ((rec->length) + 8); | ||
566 | rec = (void *)&rec->data[rec->length]; | ||
567 | |||
568 | while (offset < fw->size) { | ||
569 | dev_dbg(codec->dev, | ||
570 | "Packet: command %d, data length = 0x%x\r\n", | ||
571 | rec->command, rec->length); | ||
572 | len = rec->length + 8; | ||
573 | |||
574 | out = kzalloc(len, GFP_KERNEL); | ||
575 | if (!out) { | ||
576 | dev_err(codec->dev, | ||
577 | "Failed to allocate RX buffer\n"); | ||
578 | goto abort; | ||
579 | } | ||
580 | |||
581 | img_swap = kzalloc(len, GFP_KERNEL); | ||
582 | if (!img_swap) { | ||
583 | dev_err(codec->dev, | ||
584 | "Failed to allocate image buffer\n"); | ||
585 | goto abort; | ||
586 | } | ||
587 | |||
588 | /* We need to re-order for 0010 */ | ||
589 | byte_swap_64((u64 *)&rec->command, img_swap, len); | ||
590 | |||
591 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | ||
592 | if (!xfer) { | ||
593 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
594 | goto abort; | ||
595 | } | ||
596 | |||
597 | xfer->codec = codec; | ||
598 | list_add_tail(&xfer->list, &xfer_list); | ||
599 | |||
600 | spi_message_init(&xfer->m); | ||
601 | xfer->m.complete = wm0010_boot_xfer_complete; | ||
602 | xfer->m.context = xfer; | ||
603 | xfer->t.tx_buf = img_swap; | ||
604 | xfer->t.rx_buf = out; | ||
605 | xfer->t.len = len; | ||
606 | xfer->t.bits_per_word = 8; | ||
607 | |||
608 | if (!wm0010->pll_running) { | ||
609 | xfer->t.speed_hz = wm0010->sysclk / 6; | ||
610 | } else { | ||
611 | xfer->t.speed_hz = wm0010->max_spi_freq; | ||
612 | |||
613 | if (wm0010->board_max_spi_speed && | ||
614 | (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) | ||
615 | xfer->t.speed_hz = wm0010->board_max_spi_speed; | ||
616 | } | ||
617 | |||
618 | /* Store max usable spi frequency for later use */ | ||
619 | wm0010->max_spi_freq = xfer->t.speed_hz; | ||
620 | |||
621 | spi_message_add_tail(&xfer->t, &xfer->m); | ||
622 | |||
623 | offset += ((rec->length) + 8); | ||
624 | rec = (void *)&rec->data[rec->length]; | ||
625 | |||
626 | if (offset >= fw->size) { | ||
627 | dev_dbg(codec->dev, "All transfers scheduled\n"); | ||
628 | xfer->done = &done; | ||
629 | } | ||
630 | |||
631 | ret = spi_async(spi, &xfer->m); | ||
632 | if (ret != 0) { | ||
633 | dev_err(codec->dev, "Write failed: %d\n", ret); | ||
634 | goto abort; | ||
635 | } | ||
636 | |||
637 | if (wm0010->boot_failed) | ||
638 | goto abort; | ||
639 | } | ||
640 | |||
641 | wait_for_completion(&done); | ||
642 | 731 | ||
643 | spin_lock_irqsave(&wm0010->irq_lock, flags); | 732 | spin_lock_irqsave(&wm0010->irq_lock, flags); |
644 | wm0010->state = WM0010_FIRMWARE; | 733 | wm0010->state = WM0010_FIRMWARE; |
@@ -646,17 +735,6 @@ static int wm0010_boot(struct snd_soc_codec *codec) | |||
646 | 735 | ||
647 | mutex_unlock(&wm0010->lock); | 736 | mutex_unlock(&wm0010->lock); |
648 | 737 | ||
649 | release_firmware(fw); | ||
650 | |||
651 | while (!list_empty(&xfer_list)) { | ||
652 | xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, | ||
653 | list); | ||
654 | kfree(xfer->t.rx_buf); | ||
655 | kfree(xfer->t.tx_buf); | ||
656 | list_del(&xfer->list); | ||
657 | kfree(xfer); | ||
658 | } | ||
659 | |||
660 | return 0; | 738 | return 0; |
661 | 739 | ||
662 | abort: | 740 | abort: |
@@ -784,7 +862,6 @@ static irqreturn_t wm0010_irq(int irq, void *data) | |||
784 | struct wm0010_priv *wm0010 = data; | 862 | struct wm0010_priv *wm0010 = data; |
785 | 863 | ||
786 | switch (wm0010->state) { | 864 | switch (wm0010->state) { |
787 | case WM0010_POWER_OFF: | ||
788 | case WM0010_OUT_OF_RESET: | 865 | case WM0010_OUT_OF_RESET: |
789 | case WM0010_BOOTROM: | 866 | case WM0010_BOOTROM: |
790 | case WM0010_STAGE2: | 867 | case WM0010_STAGE2: |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 683dc43b1d87..02750ab020de 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -646,7 +646,7 @@ static const struct snd_kcontrol_new wm2000_controls[] = { | |||
646 | static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, | 646 | static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w, |
647 | struct snd_kcontrol *kcontrol, int event) | 647 | struct snd_kcontrol *kcontrol, int event) |
648 | { | 648 | { |
649 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 649 | struct snd_soc_codec *codec = w->codec; |
650 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 650 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
651 | 651 | ||
652 | if (SND_SOC_DAPM_EVENT_ON(event)) | 652 | if (SND_SOC_DAPM_EVENT_ON(event)) |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index eab64a193989..ff45b02a9dff 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/firmware.h> | ||
18 | #include <linux/gcd.h> | 19 | #include <linux/gcd.h> |
19 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
20 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
@@ -32,6 +33,40 @@ | |||
32 | #include <sound/wm2200.h> | 33 | #include <sound/wm2200.h> |
33 | 34 | ||
34 | #include "wm2200.h" | 35 | #include "wm2200.h" |
36 | #include "wmfw.h" | ||
37 | #include "wm_adsp.h" | ||
38 | |||
39 | #define WM2200_DSP_CONTROL_1 0x00 | ||
40 | #define WM2200_DSP_CONTROL_2 0x02 | ||
41 | #define WM2200_DSP_CONTROL_3 0x03 | ||
42 | #define WM2200_DSP_CONTROL_4 0x04 | ||
43 | #define WM2200_DSP_CONTROL_5 0x06 | ||
44 | #define WM2200_DSP_CONTROL_6 0x07 | ||
45 | #define WM2200_DSP_CONTROL_7 0x08 | ||
46 | #define WM2200_DSP_CONTROL_8 0x09 | ||
47 | #define WM2200_DSP_CONTROL_9 0x0A | ||
48 | #define WM2200_DSP_CONTROL_10 0x0B | ||
49 | #define WM2200_DSP_CONTROL_11 0x0C | ||
50 | #define WM2200_DSP_CONTROL_12 0x0D | ||
51 | #define WM2200_DSP_CONTROL_13 0x0F | ||
52 | #define WM2200_DSP_CONTROL_14 0x10 | ||
53 | #define WM2200_DSP_CONTROL_15 0x11 | ||
54 | #define WM2200_DSP_CONTROL_16 0x12 | ||
55 | #define WM2200_DSP_CONTROL_17 0x13 | ||
56 | #define WM2200_DSP_CONTROL_18 0x14 | ||
57 | #define WM2200_DSP_CONTROL_19 0x16 | ||
58 | #define WM2200_DSP_CONTROL_20 0x17 | ||
59 | #define WM2200_DSP_CONTROL_21 0x18 | ||
60 | #define WM2200_DSP_CONTROL_22 0x1A | ||
61 | #define WM2200_DSP_CONTROL_23 0x1B | ||
62 | #define WM2200_DSP_CONTROL_24 0x1C | ||
63 | #define WM2200_DSP_CONTROL_25 0x1E | ||
64 | #define WM2200_DSP_CONTROL_26 0x20 | ||
65 | #define WM2200_DSP_CONTROL_27 0x21 | ||
66 | #define WM2200_DSP_CONTROL_28 0x22 | ||
67 | #define WM2200_DSP_CONTROL_29 0x23 | ||
68 | #define WM2200_DSP_CONTROL_30 0x24 | ||
69 | #define WM2200_DSP_CONTROL_31 0x26 | ||
35 | 70 | ||
36 | /* The code assumes DCVDD is generated internally */ | 71 | /* The code assumes DCVDD is generated internally */ |
37 | #define WM2200_NUM_CORE_SUPPLIES 2 | 72 | #define WM2200_NUM_CORE_SUPPLIES 2 |
@@ -49,6 +84,7 @@ struct wm2200_fll { | |||
49 | 84 | ||
50 | /* codec private data */ | 85 | /* codec private data */ |
51 | struct wm2200_priv { | 86 | struct wm2200_priv { |
87 | struct wm_adsp dsp[2]; | ||
52 | struct regmap *regmap; | 88 | struct regmap *regmap; |
53 | struct device *dev; | 89 | struct device *dev; |
54 | struct snd_soc_codec *codec; | 90 | struct snd_soc_codec *codec; |
@@ -64,6 +100,72 @@ struct wm2200_priv { | |||
64 | int sysclk; | 100 | int sysclk; |
65 | }; | 101 | }; |
66 | 102 | ||
103 | #define WM2200_DSP_RANGE_BASE (WM2200_MAX_REGISTER + 1) | ||
104 | #define WM2200_DSP_SPACING 12288 | ||
105 | |||
106 | #define WM2200_DSP1_DM_BASE (WM2200_DSP_RANGE_BASE + (0 * WM2200_DSP_SPACING)) | ||
107 | #define WM2200_DSP1_PM_BASE (WM2200_DSP_RANGE_BASE + (1 * WM2200_DSP_SPACING)) | ||
108 | #define WM2200_DSP1_ZM_BASE (WM2200_DSP_RANGE_BASE + (2 * WM2200_DSP_SPACING)) | ||
109 | #define WM2200_DSP2_DM_BASE (WM2200_DSP_RANGE_BASE + (3 * WM2200_DSP_SPACING)) | ||
110 | #define WM2200_DSP2_PM_BASE (WM2200_DSP_RANGE_BASE + (4 * WM2200_DSP_SPACING)) | ||
111 | #define WM2200_DSP2_ZM_BASE (WM2200_DSP_RANGE_BASE + (5 * WM2200_DSP_SPACING)) | ||
112 | |||
113 | static const struct regmap_range_cfg wm2200_ranges[] = { | ||
114 | { .name = "DSP1DM", .range_min = WM2200_DSP1_DM_BASE, | ||
115 | .range_max = WM2200_DSP1_DM_BASE + 12287, | ||
116 | .selector_reg = WM2200_DSP1_CONTROL_3, | ||
117 | .selector_mask = WM2200_DSP1_PAGE_BASE_DM_0_MASK, | ||
118 | .selector_shift = WM2200_DSP1_PAGE_BASE_DM_0_SHIFT, | ||
119 | .window_start = WM2200_DSP1_DM_0, .window_len = 2048, }, | ||
120 | |||
121 | { .name = "DSP1PM", .range_min = WM2200_DSP1_PM_BASE, | ||
122 | .range_max = WM2200_DSP1_PM_BASE + 12287, | ||
123 | .selector_reg = WM2200_DSP1_CONTROL_2, | ||
124 | .selector_mask = WM2200_DSP1_PAGE_BASE_PM_0_MASK, | ||
125 | .selector_shift = WM2200_DSP1_PAGE_BASE_PM_0_SHIFT, | ||
126 | .window_start = WM2200_DSP1_PM_0, .window_len = 768, }, | ||
127 | |||
128 | { .name = "DSP1ZM", .range_min = WM2200_DSP1_ZM_BASE, | ||
129 | .range_max = WM2200_DSP1_ZM_BASE + 2047, | ||
130 | .selector_reg = WM2200_DSP1_CONTROL_4, | ||
131 | .selector_mask = WM2200_DSP1_PAGE_BASE_ZM_0_MASK, | ||
132 | .selector_shift = WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT, | ||
133 | .window_start = WM2200_DSP1_ZM_0, .window_len = 1024, }, | ||
134 | |||
135 | { .name = "DSP2DM", .range_min = WM2200_DSP2_DM_BASE, | ||
136 | .range_max = WM2200_DSP2_DM_BASE + 4095, | ||
137 | .selector_reg = WM2200_DSP2_CONTROL_3, | ||
138 | .selector_mask = WM2200_DSP2_PAGE_BASE_DM_0_MASK, | ||
139 | .selector_shift = WM2200_DSP2_PAGE_BASE_DM_0_SHIFT, | ||
140 | .window_start = WM2200_DSP2_DM_0, .window_len = 2048, }, | ||
141 | |||
142 | { .name = "DSP2PM", .range_min = WM2200_DSP2_PM_BASE, | ||
143 | .range_max = WM2200_DSP2_PM_BASE + 11287, | ||
144 | .selector_reg = WM2200_DSP2_CONTROL_2, | ||
145 | .selector_mask = WM2200_DSP2_PAGE_BASE_PM_0_MASK, | ||
146 | .selector_shift = WM2200_DSP2_PAGE_BASE_PM_0_SHIFT, | ||
147 | .window_start = WM2200_DSP2_PM_0, .window_len = 768, }, | ||
148 | |||
149 | { .name = "DSP2ZM", .range_min = WM2200_DSP2_ZM_BASE, | ||
150 | .range_max = WM2200_DSP2_ZM_BASE + 2047, | ||
151 | .selector_reg = WM2200_DSP2_CONTROL_4, | ||
152 | .selector_mask = WM2200_DSP2_PAGE_BASE_ZM_0_MASK, | ||
153 | .selector_shift = WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT, | ||
154 | .window_start = WM2200_DSP2_ZM_0, .window_len = 1024, }, | ||
155 | }; | ||
156 | |||
157 | static const struct wm_adsp_region wm2200_dsp1_regions[] = { | ||
158 | { .type = WMFW_ADSP1_PM, .base = WM2200_DSP1_PM_BASE }, | ||
159 | { .type = WMFW_ADSP1_DM, .base = WM2200_DSP1_DM_BASE }, | ||
160 | { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP1_ZM_BASE }, | ||
161 | }; | ||
162 | |||
163 | static const struct wm_adsp_region wm2200_dsp2_regions[] = { | ||
164 | { .type = WMFW_ADSP1_PM, .base = WM2200_DSP2_PM_BASE }, | ||
165 | { .type = WMFW_ADSP1_DM, .base = WM2200_DSP2_DM_BASE }, | ||
166 | { .type = WMFW_ADSP1_ZM, .base = WM2200_DSP2_ZM_BASE }, | ||
167 | }; | ||
168 | |||
67 | static struct reg_default wm2200_reg_defaults[] = { | 169 | static struct reg_default wm2200_reg_defaults[] = { |
68 | { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ | 170 | { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */ |
69 | { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ | 171 | { 0x0102, 0x0000 }, /* R258 - Clocking 3 */ |
@@ -407,6 +509,16 @@ static struct reg_default wm2200_reg_defaults[] = { | |||
407 | 509 | ||
408 | static bool wm2200_volatile_register(struct device *dev, unsigned int reg) | 510 | static bool wm2200_volatile_register(struct device *dev, unsigned int reg) |
409 | { | 511 | { |
512 | int i; | ||
513 | |||
514 | for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++) | ||
515 | if ((reg >= wm2200_ranges[i].window_start && | ||
516 | reg <= wm2200_ranges[i].window_start + | ||
517 | wm2200_ranges[i].window_len) || | ||
518 | (reg >= wm2200_ranges[i].range_min && | ||
519 | reg <= wm2200_ranges[i].range_max)) | ||
520 | return true; | ||
521 | |||
410 | switch (reg) { | 522 | switch (reg) { |
411 | case WM2200_SOFTWARE_RESET: | 523 | case WM2200_SOFTWARE_RESET: |
412 | case WM2200_DEVICE_REVISION: | 524 | case WM2200_DEVICE_REVISION: |
@@ -423,6 +535,16 @@ static bool wm2200_volatile_register(struct device *dev, unsigned int reg) | |||
423 | 535 | ||
424 | static bool wm2200_readable_register(struct device *dev, unsigned int reg) | 536 | static bool wm2200_readable_register(struct device *dev, unsigned int reg) |
425 | { | 537 | { |
538 | int i; | ||
539 | |||
540 | for (i = 0; i < ARRAY_SIZE(wm2200_ranges); i++) | ||
541 | if ((reg >= wm2200_ranges[i].window_start && | ||
542 | reg <= wm2200_ranges[i].window_start + | ||
543 | wm2200_ranges[i].window_len) || | ||
544 | (reg >= wm2200_ranges[i].range_min && | ||
545 | reg <= wm2200_ranges[i].range_max)) | ||
546 | return true; | ||
547 | |||
426 | switch (reg) { | 548 | switch (reg) { |
427 | case WM2200_SOFTWARE_RESET: | 549 | case WM2200_SOFTWARE_RESET: |
428 | case WM2200_DEVICE_REVISION: | 550 | case WM2200_DEVICE_REVISION: |
@@ -880,7 +1002,7 @@ static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0); | |||
880 | static const char *wm2200_mixer_texts[] = { | 1002 | static const char *wm2200_mixer_texts[] = { |
881 | "None", | 1003 | "None", |
882 | "Tone Generator", | 1004 | "Tone Generator", |
883 | "AEC loopback", | 1005 | "AEC Loopback", |
884 | "IN1L", | 1006 | "IN1L", |
885 | "IN1R", | 1007 | "IN1R", |
886 | "IN2L", | 1008 | "IN2L", |
@@ -976,6 +1098,20 @@ static int wm2200_mixer_values[] = { | |||
976 | static WM2200_MUX_CTL_DECL(name##_in3); \ | 1098 | static WM2200_MUX_CTL_DECL(name##_in3); \ |
977 | static WM2200_MUX_CTL_DECL(name##_in4) | 1099 | static WM2200_MUX_CTL_DECL(name##_in4) |
978 | 1100 | ||
1101 | #define WM2200_DSP_ENUMS(name, base_reg) \ | ||
1102 | static WM2200_MUX_ENUM_DECL(name##_aux1_enum, base_reg); \ | ||
1103 | static WM2200_MUX_ENUM_DECL(name##_aux2_enum, base_reg + 1); \ | ||
1104 | static WM2200_MUX_ENUM_DECL(name##_aux3_enum, base_reg + 2); \ | ||
1105 | static WM2200_MUX_ENUM_DECL(name##_aux4_enum, base_reg + 3); \ | ||
1106 | static WM2200_MUX_ENUM_DECL(name##_aux5_enum, base_reg + 4); \ | ||
1107 | static WM2200_MUX_ENUM_DECL(name##_aux6_enum, base_reg + 5); \ | ||
1108 | static WM2200_MUX_CTL_DECL(name##_aux1); \ | ||
1109 | static WM2200_MUX_CTL_DECL(name##_aux2); \ | ||
1110 | static WM2200_MUX_CTL_DECL(name##_aux3); \ | ||
1111 | static WM2200_MUX_CTL_DECL(name##_aux4); \ | ||
1112 | static WM2200_MUX_CTL_DECL(name##_aux5); \ | ||
1113 | static WM2200_MUX_CTL_DECL(name##_aux6); | ||
1114 | |||
979 | static const struct snd_kcontrol_new wm2200_snd_controls[] = { | 1115 | static const struct snd_kcontrol_new wm2200_snd_controls[] = { |
980 | SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, | 1116 | SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL, |
981 | WM2200_IN1_OSR_SHIFT, 1, 0), | 1117 | WM2200_IN1_OSR_SHIFT, 1, 0), |
@@ -1051,6 +1187,9 @@ WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE); | |||
1051 | WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE); | 1187 | WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE); |
1052 | WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE); | 1188 | WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE); |
1053 | 1189 | ||
1190 | WM2200_DSP_ENUMS(DSP1, WM2200_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
1191 | WM2200_DSP_ENUMS(DSP2, WM2200_DSP2AUX1MIX_INPUT_1_SOURCE); | ||
1192 | |||
1054 | WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE); | 1193 | WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE); |
1055 | WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); | 1194 | WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); |
1056 | 1195 | ||
@@ -1064,8 +1203,19 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); | |||
1064 | WM2200_MUX(name_str " Input 4", &name##_in4_mux), \ | 1203 | WM2200_MUX(name_str " Input 4", &name##_in4_mux), \ |
1065 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) | 1204 | SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0) |
1066 | 1205 | ||
1206 | #define WM2200_DSP_WIDGETS(name, name_str) \ | ||
1207 | WM2200_MIXER_WIDGETS(name##L, name_str "L"), \ | ||
1208 | WM2200_MIXER_WIDGETS(name##R, name_str "R"), \ | ||
1209 | WM2200_MUX(name_str " Aux 1", &name##_aux1_mux), \ | ||
1210 | WM2200_MUX(name_str " Aux 2", &name##_aux2_mux), \ | ||
1211 | WM2200_MUX(name_str " Aux 3", &name##_aux3_mux), \ | ||
1212 | WM2200_MUX(name_str " Aux 4", &name##_aux4_mux), \ | ||
1213 | WM2200_MUX(name_str " Aux 5", &name##_aux5_mux), \ | ||
1214 | WM2200_MUX(name_str " Aux 6", &name##_aux6_mux) | ||
1215 | |||
1067 | #define WM2200_MIXER_INPUT_ROUTES(name) \ | 1216 | #define WM2200_MIXER_INPUT_ROUTES(name) \ |
1068 | { name, "Tone Generator", "Tone Generator" }, \ | 1217 | { name, "Tone Generator", "Tone Generator" }, \ |
1218 | { name, "AEC Loopback", "AEC Loopback" }, \ | ||
1069 | { name, "IN1L", "IN1L PGA" }, \ | 1219 | { name, "IN1L", "IN1L PGA" }, \ |
1070 | { name, "IN1R", "IN1R PGA" }, \ | 1220 | { name, "IN1R", "IN1R PGA" }, \ |
1071 | { name, "IN2L", "IN2L PGA" }, \ | 1221 | { name, "IN2L", "IN2L PGA" }, \ |
@@ -1106,6 +1256,33 @@ WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE); | |||
1106 | WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \ | 1256 | WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \ |
1107 | WM2200_MIXER_INPUT_ROUTES(name " Input 4") | 1257 | WM2200_MIXER_INPUT_ROUTES(name " Input 4") |
1108 | 1258 | ||
1259 | #define WM2200_DSP_AUX_ROUTES(name) \ | ||
1260 | { name, NULL, name " Aux 1" }, \ | ||
1261 | { name, NULL, name " Aux 2" }, \ | ||
1262 | { name, NULL, name " Aux 3" }, \ | ||
1263 | { name, NULL, name " Aux 4" }, \ | ||
1264 | { name, NULL, name " Aux 5" }, \ | ||
1265 | { name, NULL, name " Aux 6" }, \ | ||
1266 | WM2200_MIXER_INPUT_ROUTES(name " Aux 1"), \ | ||
1267 | WM2200_MIXER_INPUT_ROUTES(name " Aux 2"), \ | ||
1268 | WM2200_MIXER_INPUT_ROUTES(name " Aux 3"), \ | ||
1269 | WM2200_MIXER_INPUT_ROUTES(name " Aux 4"), \ | ||
1270 | WM2200_MIXER_INPUT_ROUTES(name " Aux 5"), \ | ||
1271 | WM2200_MIXER_INPUT_ROUTES(name " Aux 6") | ||
1272 | |||
1273 | static const char *wm2200_aec_loopback_texts[] = { | ||
1274 | "OUT1L", "OUT1R", "OUT2L", "OUT2R", | ||
1275 | }; | ||
1276 | |||
1277 | static const struct soc_enum wm2200_aec_loopback = | ||
1278 | SOC_ENUM_SINGLE(WM2200_DAC_AEC_CONTROL_1, | ||
1279 | WM2200_AEC_LOOPBACK_SRC_SHIFT, | ||
1280 | ARRAY_SIZE(wm2200_aec_loopback_texts), | ||
1281 | wm2200_aec_loopback_texts); | ||
1282 | |||
1283 | static const struct snd_kcontrol_new wm2200_aec_loopback_mux = | ||
1284 | SOC_DAPM_ENUM("AEC Loopback", wm2200_aec_loopback); | ||
1285 | |||
1109 | static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = { | 1286 | static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = { |
1110 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0, | 1287 | SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0, |
1111 | NULL, 0), | 1288 | NULL, 0), |
@@ -1165,8 +1342,8 @@ SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0, | |||
1165 | SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0, | 1342 | SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0, |
1166 | NULL, 0), | 1343 | NULL, 0), |
1167 | 1344 | ||
1168 | SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0), | 1345 | WM_ADSP1("DSP1", 0), |
1169 | SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0), | 1346 | WM_ADSP1("DSP2", 1), |
1170 | 1347 | ||
1171 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, | 1348 | SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0, |
1172 | WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0), | 1349 | WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0), |
@@ -1181,6 +1358,9 @@ SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4, | |||
1181 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5, | 1358 | SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5, |
1182 | WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0), | 1359 | WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0), |
1183 | 1360 | ||
1361 | SND_SOC_DAPM_MUX("AEC Loopback", WM2200_DAC_AEC_CONTROL_1, | ||
1362 | WM2200_AEC_LOOPBACK_ENA_SHIFT, 0, &wm2200_aec_loopback_mux), | ||
1363 | |||
1184 | SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES, | 1364 | SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES, |
1185 | WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0), | 1365 | WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0), |
1186 | SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES, | 1366 | SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES, |
@@ -1231,10 +1411,8 @@ WM2200_MIXER_WIDGETS(EQR, "EQR"), | |||
1231 | WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"), | 1411 | WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"), |
1232 | WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"), | 1412 | WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"), |
1233 | 1413 | ||
1234 | WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"), | 1414 | WM2200_DSP_WIDGETS(DSP1, "DSP1"), |
1235 | WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"), | 1415 | WM2200_DSP_WIDGETS(DSP2, "DSP2"), |
1236 | WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"), | ||
1237 | WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"), | ||
1238 | 1416 | ||
1239 | WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), | 1417 | WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"), |
1240 | WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), | 1418 | WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"), |
@@ -1326,11 +1504,19 @@ static const struct snd_soc_dapm_route wm2200_dapm_routes[] = { | |||
1326 | { "SPK", NULL, "OUT2L" }, | 1504 | { "SPK", NULL, "OUT2L" }, |
1327 | { "SPK", NULL, "OUT2R" }, | 1505 | { "SPK", NULL, "OUT2R" }, |
1328 | 1506 | ||
1507 | { "AEC Loopback", "OUT1L", "OUT1L" }, | ||
1508 | { "AEC Loopback", "OUT1R", "OUT1R" }, | ||
1509 | { "AEC Loopback", "OUT2L", "OUT2L" }, | ||
1510 | { "AEC Loopback", "OUT2R", "OUT2R" }, | ||
1511 | |||
1329 | WM2200_MIXER_ROUTES("DSP1", "DSP1L"), | 1512 | WM2200_MIXER_ROUTES("DSP1", "DSP1L"), |
1330 | WM2200_MIXER_ROUTES("DSP1", "DSP1R"), | 1513 | WM2200_MIXER_ROUTES("DSP1", "DSP1R"), |
1331 | WM2200_MIXER_ROUTES("DSP2", "DSP2L"), | 1514 | WM2200_MIXER_ROUTES("DSP2", "DSP2L"), |
1332 | WM2200_MIXER_ROUTES("DSP2", "DSP2R"), | 1515 | WM2200_MIXER_ROUTES("DSP2", "DSP2R"), |
1333 | 1516 | ||
1517 | WM2200_DSP_AUX_ROUTES("DSP1"), | ||
1518 | WM2200_DSP_AUX_ROUTES("DSP2"), | ||
1519 | |||
1334 | WM2200_MIXER_ROUTES("OUT1L", "OUT1L"), | 1520 | WM2200_MIXER_ROUTES("OUT1L", "OUT1L"), |
1335 | WM2200_MIXER_ROUTES("OUT1R", "OUT1R"), | 1521 | WM2200_MIXER_ROUTES("OUT1R", "OUT1R"), |
1336 | WM2200_MIXER_ROUTES("OUT2L", "OUT2L"), | 1522 | WM2200_MIXER_ROUTES("OUT2L", "OUT2L"), |
@@ -1968,12 +2154,15 @@ static const struct regmap_config wm2200_regmap = { | |||
1968 | .reg_bits = 16, | 2154 | .reg_bits = 16, |
1969 | .val_bits = 16, | 2155 | .val_bits = 16, |
1970 | 2156 | ||
1971 | .max_register = WM2200_MAX_REGISTER, | 2157 | .max_register = WM2200_MAX_REGISTER + (ARRAY_SIZE(wm2200_ranges) * |
2158 | WM2200_DSP_SPACING), | ||
1972 | .reg_defaults = wm2200_reg_defaults, | 2159 | .reg_defaults = wm2200_reg_defaults, |
1973 | .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults), | 2160 | .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults), |
1974 | .volatile_reg = wm2200_volatile_register, | 2161 | .volatile_reg = wm2200_volatile_register, |
1975 | .readable_reg = wm2200_readable_register, | 2162 | .readable_reg = wm2200_readable_register, |
1976 | .cache_type = REGCACHE_RBTREE, | 2163 | .cache_type = REGCACHE_RBTREE, |
2164 | .ranges = wm2200_ranges, | ||
2165 | .num_ranges = ARRAY_SIZE(wm2200_ranges), | ||
1977 | }; | 2166 | }; |
1978 | 2167 | ||
1979 | static const unsigned int wm2200_dig_vu[] = { | 2168 | static const unsigned int wm2200_dig_vu[] = { |
@@ -2011,14 +2200,30 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2011 | wm2200->dev = &i2c->dev; | 2200 | wm2200->dev = &i2c->dev; |
2012 | init_completion(&wm2200->fll_lock); | 2201 | init_completion(&wm2200->fll_lock); |
2013 | 2202 | ||
2014 | wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap); | 2203 | wm2200->regmap = devm_regmap_init_i2c(i2c, &wm2200_regmap); |
2015 | if (IS_ERR(wm2200->regmap)) { | 2204 | if (IS_ERR(wm2200->regmap)) { |
2016 | ret = PTR_ERR(wm2200->regmap); | 2205 | ret = PTR_ERR(wm2200->regmap); |
2017 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 2206 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
2018 | ret); | 2207 | ret); |
2019 | goto err; | 2208 | return ret; |
2209 | } | ||
2210 | |||
2211 | for (i = 0; i < 2; i++) { | ||
2212 | wm2200->dsp[i].type = WMFW_ADSP1; | ||
2213 | wm2200->dsp[i].part = "wm2200"; | ||
2214 | wm2200->dsp[i].num = i + 1; | ||
2215 | wm2200->dsp[i].dev = &i2c->dev; | ||
2216 | wm2200->dsp[i].regmap = wm2200->regmap; | ||
2020 | } | 2217 | } |
2021 | 2218 | ||
2219 | wm2200->dsp[0].base = WM2200_DSP1_CONTROL_1; | ||
2220 | wm2200->dsp[0].mem = wm2200_dsp1_regions; | ||
2221 | wm2200->dsp[0].num_mems = ARRAY_SIZE(wm2200_dsp1_regions); | ||
2222 | |||
2223 | wm2200->dsp[1].base = WM2200_DSP2_CONTROL_1; | ||
2224 | wm2200->dsp[1].mem = wm2200_dsp2_regions; | ||
2225 | wm2200->dsp[1].num_mems = ARRAY_SIZE(wm2200_dsp2_regions); | ||
2226 | |||
2022 | if (pdata) | 2227 | if (pdata) |
2023 | wm2200->pdata = *pdata; | 2228 | wm2200->pdata = *pdata; |
2024 | 2229 | ||
@@ -2027,12 +2232,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2027 | for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++) | 2232 | for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++) |
2028 | wm2200->core_supplies[i].supply = wm2200_core_supply_names[i]; | 2233 | wm2200->core_supplies[i].supply = wm2200_core_supply_names[i]; |
2029 | 2234 | ||
2030 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies), | 2235 | ret = devm_regulator_bulk_get(&i2c->dev, |
2031 | wm2200->core_supplies); | 2236 | ARRAY_SIZE(wm2200->core_supplies), |
2237 | wm2200->core_supplies); | ||
2032 | if (ret != 0) { | 2238 | if (ret != 0) { |
2033 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n", | 2239 | dev_err(&i2c->dev, "Failed to request core supplies: %d\n", |
2034 | ret); | 2240 | ret); |
2035 | goto err_regmap; | 2241 | return ret; |
2036 | } | 2242 | } |
2037 | 2243 | ||
2038 | ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), | 2244 | ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies), |
@@ -2040,12 +2246,13 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2040 | if (ret != 0) { | 2246 | if (ret != 0) { |
2041 | dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", | 2247 | dev_err(&i2c->dev, "Failed to enable core supplies: %d\n", |
2042 | ret); | 2248 | ret); |
2043 | goto err_core; | 2249 | return ret; |
2044 | } | 2250 | } |
2045 | 2251 | ||
2046 | if (wm2200->pdata.ldo_ena) { | 2252 | if (wm2200->pdata.ldo_ena) { |
2047 | ret = gpio_request_one(wm2200->pdata.ldo_ena, | 2253 | ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.ldo_ena, |
2048 | GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA"); | 2254 | GPIOF_OUT_INIT_HIGH, |
2255 | "WM2200 LDOENA"); | ||
2049 | if (ret < 0) { | 2256 | if (ret < 0) { |
2050 | dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", | 2257 | dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n", |
2051 | wm2200->pdata.ldo_ena, ret); | 2258 | wm2200->pdata.ldo_ena, ret); |
@@ -2055,8 +2262,9 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2055 | } | 2262 | } |
2056 | 2263 | ||
2057 | if (wm2200->pdata.reset) { | 2264 | if (wm2200->pdata.reset) { |
2058 | ret = gpio_request_one(wm2200->pdata.reset, | 2265 | ret = devm_gpio_request_one(&i2c->dev, wm2200->pdata.reset, |
2059 | GPIOF_OUT_INIT_HIGH, "WM2200 /RESET"); | 2266 | GPIOF_OUT_INIT_HIGH, |
2267 | "WM2200 /RESET"); | ||
2060 | if (ret < 0) { | 2268 | if (ret < 0) { |
2061 | dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", | 2269 | dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n", |
2062 | wm2200->pdata.reset, ret); | 2270 | wm2200->pdata.reset, ret); |
@@ -2166,24 +2374,14 @@ static __devinit int wm2200_i2c_probe(struct i2c_client *i2c, | |||
2166 | err_pm_runtime: | 2374 | err_pm_runtime: |
2167 | pm_runtime_disable(&i2c->dev); | 2375 | pm_runtime_disable(&i2c->dev); |
2168 | err_reset: | 2376 | err_reset: |
2169 | if (wm2200->pdata.reset) { | 2377 | if (wm2200->pdata.reset) |
2170 | gpio_set_value_cansleep(wm2200->pdata.reset, 0); | 2378 | gpio_set_value_cansleep(wm2200->pdata.reset, 0); |
2171 | gpio_free(wm2200->pdata.reset); | ||
2172 | } | ||
2173 | err_ldo: | 2379 | err_ldo: |
2174 | if (wm2200->pdata.ldo_ena) { | 2380 | if (wm2200->pdata.ldo_ena) |
2175 | gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); | 2381 | gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); |
2176 | gpio_free(wm2200->pdata.ldo_ena); | ||
2177 | } | ||
2178 | err_enable: | 2382 | err_enable: |
2179 | regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), | 2383 | regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies), |
2180 | wm2200->core_supplies); | 2384 | wm2200->core_supplies); |
2181 | err_core: | ||
2182 | regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies), | ||
2183 | wm2200->core_supplies); | ||
2184 | err_regmap: | ||
2185 | regmap_exit(wm2200->regmap); | ||
2186 | err: | ||
2187 | return ret; | 2385 | return ret; |
2188 | } | 2386 | } |
2189 | 2387 | ||
@@ -2194,17 +2392,10 @@ static __devexit int wm2200_i2c_remove(struct i2c_client *i2c) | |||
2194 | snd_soc_unregister_codec(&i2c->dev); | 2392 | snd_soc_unregister_codec(&i2c->dev); |
2195 | if (i2c->irq) | 2393 | if (i2c->irq) |
2196 | free_irq(i2c->irq, wm2200); | 2394 | free_irq(i2c->irq, wm2200); |
2197 | if (wm2200->pdata.reset) { | 2395 | if (wm2200->pdata.reset) |
2198 | gpio_set_value_cansleep(wm2200->pdata.reset, 0); | 2396 | gpio_set_value_cansleep(wm2200->pdata.reset, 0); |
2199 | gpio_free(wm2200->pdata.reset); | 2397 | if (wm2200->pdata.ldo_ena) |
2200 | } | ||
2201 | if (wm2200->pdata.ldo_ena) { | ||
2202 | gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); | 2398 | gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0); |
2203 | gpio_free(wm2200->pdata.ldo_ena); | ||
2204 | } | ||
2205 | regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies), | ||
2206 | wm2200->core_supplies); | ||
2207 | regmap_exit(wm2200->regmap); | ||
2208 | 2399 | ||
2209 | return 0; | 2400 | return 0; |
2210 | } | 2401 | } |
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c index 7f567585832e..9f57996ff272 100644 --- a/sound/soc/codecs/wm5100.c +++ b/sound/soc/codecs/wm5100.c | |||
@@ -1233,7 +1233,7 @@ static const struct snd_soc_dapm_route wm5100_dapm_routes[] = { | |||
1233 | { "PWM2", NULL, "PWM2 Driver" }, | 1233 | { "PWM2", NULL, "PWM2 Driver" }, |
1234 | }; | 1234 | }; |
1235 | 1235 | ||
1236 | static const __devinitconst struct reg_default wm5100_reva_patches[] = { | 1236 | static const struct reg_default wm5100_reva_patches[] = { |
1237 | { WM5100_AUDIO_IF_1_10, 0 }, | 1237 | { WM5100_AUDIO_IF_1_10, 0 }, |
1238 | { WM5100_AUDIO_IF_1_11, 1 }, | 1238 | { WM5100_AUDIO_IF_1_11, 1 }, |
1239 | { WM5100_AUDIO_IF_1_12, 2 }, | 1239 | { WM5100_AUDIO_IF_1_12, 2 }, |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index 7394e73fa43c..27f7e38e7eca 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -31,6 +31,7 @@ | |||
31 | 31 | ||
32 | #include "arizona.h" | 32 | #include "arizona.h" |
33 | #include "wm5102.h" | 33 | #include "wm5102.h" |
34 | #include "wm_adsp.h" | ||
34 | 35 | ||
35 | struct wm5102_priv { | 36 | struct wm5102_priv { |
36 | struct arizona_priv core; | 37 | struct arizona_priv core; |
@@ -42,6 +43,13 @@ static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | |||
42 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); | 43 | static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0); |
43 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); | 44 | static DECLARE_TLV_DB_SCALE(noise_tlv, 0, 600, 0); |
44 | 45 | ||
46 | static const struct wm_adsp_region wm5102_dsp1_regions[] = { | ||
47 | { .type = WMFW_ADSP2_PM, .base = 0x100000 }, | ||
48 | { .type = WMFW_ADSP2_ZM, .base = 0x180000 }, | ||
49 | { .type = WMFW_ADSP2_XM, .base = 0x190000 }, | ||
50 | { .type = WMFW_ADSP2_YM, .base = 0x1a8000 }, | ||
51 | }; | ||
52 | |||
45 | static const struct reg_default wm5102_sysclk_reva_patch[] = { | 53 | static const struct reg_default wm5102_sysclk_reva_patch[] = { |
46 | { 0x3000, 0x2225 }, | 54 | { 0x3000, 0x2225 }, |
47 | { 0x3001, 0x3a03 }, | 55 | { 0x3001, 0x3a03 }, |
@@ -627,11 +635,23 @@ SOC_DOUBLE_R_TLV("IN3 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_3L, | |||
627 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, | 635 | ARIZONA_ADC_DIGITAL_VOLUME_3R, ARIZONA_IN3L_DIG_VOL_SHIFT, |
628 | 0xbf, 0, digital_tlv), | 636 | 0xbf, 0, digital_tlv), |
629 | 637 | ||
638 | SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp), | ||
639 | SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp), | ||
640 | |||
630 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | 641 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), |
631 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | 642 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), |
632 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 643 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
633 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 644 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
634 | 645 | ||
646 | SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21, | ||
647 | ARIZONA_EQ1_ENA_MASK), | ||
648 | SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21, | ||
649 | ARIZONA_EQ2_ENA_MASK), | ||
650 | SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21, | ||
651 | ARIZONA_EQ3_ENA_MASK), | ||
652 | SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21, | ||
653 | ARIZONA_EQ4_ENA_MASK), | ||
654 | |||
635 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 655 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
636 | 24, 0, eq_tlv), | 656 | 24, 0, eq_tlv), |
637 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 657 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -687,6 +707,14 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |||
687 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | 707 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), |
688 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | 708 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), |
689 | 709 | ||
710 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | ||
711 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | ||
712 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | ||
713 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | ||
714 | |||
715 | ARIZONA_MIXER_CONTROLS("DSP1L", ARIZONA_DSP1LMIX_INPUT_1_SOURCE), | ||
716 | ARIZONA_MIXER_CONTROLS("DSP1R", ARIZONA_DSP1RMIX_INPUT_1_SOURCE), | ||
717 | |||
690 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | 718 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), |
691 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | 719 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), |
692 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 720 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
@@ -708,14 +736,6 @@ ARIZONA_MIXER_CONTROLS("SPKOUTR", ARIZONA_OUT4RMIX_INPUT_1_SOURCE), | |||
708 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), | 736 | ARIZONA_MIXER_CONTROLS("SPKDAT1L", ARIZONA_OUT5LMIX_INPUT_1_SOURCE), |
709 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), | 737 | ARIZONA_MIXER_CONTROLS("SPKDAT1R", ARIZONA_OUT5RMIX_INPUT_1_SOURCE), |
710 | 738 | ||
711 | SOC_SINGLE("HPOUT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_1L, | ||
712 | ARIZONA_OUT1_OSR_SHIFT, 1, 0), | ||
713 | SOC_SINGLE("OUT2 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
714 | ARIZONA_OUT2_OSR_SHIFT, 1, 0), | ||
715 | SOC_SINGLE("EPOUT High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
716 | ARIZONA_OUT3_OSR_SHIFT, 1, 0), | ||
717 | SOC_SINGLE("Speaker High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_4L, | ||
718 | ARIZONA_OUT4_OSR_SHIFT, 1, 0), | ||
719 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, | 739 | SOC_SINGLE("SPKDAT1 High Performance Switch", ARIZONA_OUTPUT_PATH_CONFIG_5L, |
720 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), | 740 | ARIZONA_OUT5_OSR_SHIFT, 1, 0), |
721 | 741 | ||
@@ -745,16 +765,8 @@ SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", ARIZONA_DAC_DIGITAL_VOLUME_5L, | |||
745 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, | 765 | ARIZONA_DAC_DIGITAL_VOLUME_5R, ARIZONA_OUT5L_VOL_SHIFT, |
746 | 0xbf, 0, digital_tlv), | 766 | 0xbf, 0, digital_tlv), |
747 | 767 | ||
748 | SOC_DOUBLE_R_RANGE_TLV("HPOUT1 Volume", ARIZONA_OUTPUT_PATH_CONFIG_1L, | 768 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), |
749 | ARIZONA_OUTPUT_PATH_CONFIG_1R, | 769 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), |
750 | ARIZONA_OUT1L_PGA_VOL_SHIFT, | ||
751 | 0x34, 0x40, 0, ana_tlv), | ||
752 | SOC_DOUBLE_R_RANGE_TLV("OUT2 Volume", ARIZONA_OUTPUT_PATH_CONFIG_2L, | ||
753 | ARIZONA_OUTPUT_PATH_CONFIG_2R, | ||
754 | ARIZONA_OUT2L_PGA_VOL_SHIFT, | ||
755 | 0x34, 0x40, 0, ana_tlv), | ||
756 | SOC_SINGLE_RANGE_TLV("EPOUT Volume", ARIZONA_OUTPUT_PATH_CONFIG_3L, | ||
757 | ARIZONA_OUT3L_PGA_VOL_SHIFT, 0x34, 0x40, 0, ana_tlv), | ||
758 | 770 | ||
759 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | 771 | SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, |
760 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), | 772 | ARIZONA_SPK1R_MUTE_SHIFT, 1, 1), |
@@ -819,11 +831,15 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
819 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 831 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
820 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 832 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
821 | 833 | ||
822 | ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 834 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
823 | ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 835 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
824 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 836 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
825 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 837 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
838 | |||
839 | ARIZONA_MIXER_ENUMS(DSP1L, ARIZONA_DSP1LMIX_INPUT_1_SOURCE); | ||
840 | ARIZONA_MIXER_ENUMS(DSP1R, ARIZONA_DSP1RMIX_INPUT_1_SOURCE); | ||
826 | 841 | ||
842 | ARIZONA_DSP_AUX_ENUMS(DSP1, ARIZONA_DSP1AUX1MIX_INPUT_1_SOURCE); | ||
827 | 843 | ||
828 | static const char *wm5102_aec_loopback_texts[] = { | 844 | static const char *wm5102_aec_loopback_texts[] = { |
829 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", | 845 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", |
@@ -864,6 +880,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | |||
864 | 880 | ||
865 | SND_SOC_DAPM_SIGGEN("TONE"), | 881 | SND_SOC_DAPM_SIGGEN("TONE"), |
866 | SND_SOC_DAPM_SIGGEN("NOISE"), | 882 | SND_SOC_DAPM_SIGGEN("NOISE"), |
883 | SND_SOC_DAPM_SIGGEN("HAPTICS"), | ||
867 | 884 | ||
868 | SND_SOC_DAPM_INPUT("IN1L"), | 885 | SND_SOC_DAPM_INPUT("IN1L"), |
869 | SND_SOC_DAPM_INPUT("IN1R"), | 886 | SND_SOC_DAPM_INPUT("IN1R"), |
@@ -894,9 +911,9 @@ SND_SOC_DAPM_PGA_E("IN3R PGA", ARIZONA_INPUT_ENABLES, ARIZONA_IN3R_ENA_SHIFT, | |||
894 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, | 911 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ARIZONA_MIC_BIAS_CTRL_1, |
895 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | 912 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), |
896 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, | 913 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ARIZONA_MIC_BIAS_CTRL_2, |
897 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | 914 | ARIZONA_MICB2_ENA_SHIFT, 0, NULL, 0), |
898 | SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, | 915 | SND_SOC_DAPM_SUPPLY("MICBIAS3", ARIZONA_MIC_BIAS_CTRL_3, |
899 | ARIZONA_MICB1_ENA_SHIFT, 0, NULL, 0), | 916 | ARIZONA_MICB3_ENA_SHIFT, 0, NULL, 0), |
900 | 917 | ||
901 | SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, | 918 | SND_SOC_DAPM_PGA("Noise Generator", ARIZONA_COMFORT_NOISE_GENERATOR, |
902 | ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), | 919 | ARIZONA_NOISE_GEN_ENA_SHIFT, 0, NULL, 0), |
@@ -996,6 +1013,8 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
996 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 1013 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, |
997 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 1014 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
998 | 1015 | ||
1016 | ARIZONA_DSP_WIDGETS(DSP1, "DSP1"), | ||
1017 | |||
999 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | 1018 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, |
1000 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), | 1019 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), |
1001 | 1020 | ||
@@ -1071,10 +1090,12 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
1071 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 1090 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
1072 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 1091 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
1073 | 1092 | ||
1074 | ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | 1093 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
1075 | ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | 1094 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
1076 | ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | 1095 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
1077 | ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | 1096 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), |
1097 | |||
1098 | WM_ADSP2("DSP1", 0), | ||
1078 | 1099 | ||
1079 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | 1100 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), |
1080 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 1101 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
@@ -1094,6 +1115,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |||
1094 | { name, "Noise Generator", "Noise Generator" }, \ | 1115 | { name, "Noise Generator", "Noise Generator" }, \ |
1095 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 1116 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
1096 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 1117 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
1118 | { name, "Haptics", "HAPTICS" }, \ | ||
1097 | { name, "AEC", "AEC Loopback" }, \ | 1119 | { name, "AEC", "AEC Loopback" }, \ |
1098 | { name, "IN1L", "IN1L PGA" }, \ | 1120 | { name, "IN1L", "IN1L PGA" }, \ |
1099 | { name, "IN1R", "IN1R PGA" }, \ | 1121 | { name, "IN1R", "IN1R PGA" }, \ |
@@ -1127,7 +1149,13 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |||
1127 | { name, "ASRC1L", "ASRC1L" }, \ | 1149 | { name, "ASRC1L", "ASRC1L" }, \ |
1128 | { name, "ASRC1R", "ASRC1R" }, \ | 1150 | { name, "ASRC1R", "ASRC1R" }, \ |
1129 | { name, "ASRC2L", "ASRC2L" }, \ | 1151 | { name, "ASRC2L", "ASRC2L" }, \ |
1130 | { name, "ASRC2R", "ASRC2R" } | 1152 | { name, "ASRC2R", "ASRC2R" }, \ |
1153 | { name, "DSP1.1", "DSP1" }, \ | ||
1154 | { name, "DSP1.2", "DSP1" }, \ | ||
1155 | { name, "DSP1.3", "DSP1" }, \ | ||
1156 | { name, "DSP1.4", "DSP1" }, \ | ||
1157 | { name, "DSP1.5", "DSP1" }, \ | ||
1158 | { name, "DSP1.6", "DSP1" } | ||
1131 | 1159 | ||
1132 | static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | 1160 | static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { |
1133 | { "AIF2 Capture", NULL, "DBVDD2" }, | 1161 | { "AIF2 Capture", NULL, "DBVDD2" }, |
@@ -1213,6 +1241,11 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
1213 | { "IN3L PGA", NULL, "IN3L" }, | 1241 | { "IN3L PGA", NULL, "IN3L" }, |
1214 | { "IN3R PGA", NULL, "IN3R" }, | 1242 | { "IN3R PGA", NULL, "IN3R" }, |
1215 | 1243 | ||
1244 | { "ASRC1L", NULL, "ASRC1L Input" }, | ||
1245 | { "ASRC1R", NULL, "ASRC1R Input" }, | ||
1246 | { "ASRC2L", NULL, "ASRC2L Input" }, | ||
1247 | { "ASRC2R", NULL, "ASRC2R Input" }, | ||
1248 | |||
1216 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), | 1249 | ARIZONA_MIXER_ROUTES("OUT1L", "HPOUT1L"), |
1217 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), | 1250 | ARIZONA_MIXER_ROUTES("OUT1R", "HPOUT1R"), |
1218 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), | 1251 | ARIZONA_MIXER_ROUTES("OUT2L", "HPOUT2L"), |
@@ -1255,10 +1288,12 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
1255 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | 1288 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), |
1256 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | 1289 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), |
1257 | 1290 | ||
1258 | ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | 1291 | ARIZONA_MUX_ROUTES("ASRC1L"), |
1259 | ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | 1292 | ARIZONA_MUX_ROUTES("ASRC1R"), |
1260 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | 1293 | ARIZONA_MUX_ROUTES("ASRC2L"), |
1261 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | 1294 | ARIZONA_MUX_ROUTES("ASRC2R"), |
1295 | |||
1296 | ARIZONA_DSP_ROUTES("DSP1"), | ||
1262 | 1297 | ||
1263 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | 1298 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, |
1264 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | 1299 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, |
@@ -1377,9 +1412,28 @@ static struct snd_soc_dai_driver wm5102_dai[] = { | |||
1377 | static int wm5102_codec_probe(struct snd_soc_codec *codec) | 1412 | static int wm5102_codec_probe(struct snd_soc_codec *codec) |
1378 | { | 1413 | { |
1379 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | 1414 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); |
1415 | int ret; | ||
1380 | 1416 | ||
1381 | codec->control_data = priv->core.arizona->regmap; | 1417 | codec->control_data = priv->core.arizona->regmap; |
1382 | return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | 1418 | |
1419 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
1420 | if (ret != 0) | ||
1421 | return ret; | ||
1422 | |||
1423 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | ||
1424 | |||
1425 | priv->core.arizona->dapm = &codec->dapm; | ||
1426 | |||
1427 | return 0; | ||
1428 | } | ||
1429 | |||
1430 | static int wm5102_codec_remove(struct snd_soc_codec *codec) | ||
1431 | { | ||
1432 | struct wm5102_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
1433 | |||
1434 | priv->core.arizona->dapm = NULL; | ||
1435 | |||
1436 | return 0; | ||
1383 | } | 1437 | } |
1384 | 1438 | ||
1385 | #define WM5102_DIG_VU 0x0200 | 1439 | #define WM5102_DIG_VU 0x0200 |
@@ -1406,6 +1460,7 @@ static unsigned int wm5102_digital_vu[] = { | |||
1406 | 1460 | ||
1407 | static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { | 1461 | static struct snd_soc_codec_driver soc_codec_dev_wm5102 = { |
1408 | .probe = wm5102_codec_probe, | 1462 | .probe = wm5102_codec_probe, |
1463 | .remove = wm5102_codec_remove, | ||
1409 | 1464 | ||
1410 | .idle_bias_off = true, | 1465 | .idle_bias_off = true, |
1411 | 1466 | ||
@@ -1424,7 +1479,7 @@ static int __devinit wm5102_probe(struct platform_device *pdev) | |||
1424 | { | 1479 | { |
1425 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); | 1480 | struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); |
1426 | struct wm5102_priv *wm5102; | 1481 | struct wm5102_priv *wm5102; |
1427 | int i; | 1482 | int i, ret; |
1428 | 1483 | ||
1429 | wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv), | 1484 | wm5102 = devm_kzalloc(&pdev->dev, sizeof(struct wm5102_priv), |
1430 | GFP_KERNEL); | 1485 | GFP_KERNEL); |
@@ -1434,6 +1489,19 @@ static int __devinit wm5102_probe(struct platform_device *pdev) | |||
1434 | 1489 | ||
1435 | wm5102->core.arizona = arizona; | 1490 | wm5102->core.arizona = arizona; |
1436 | 1491 | ||
1492 | wm5102->core.adsp[0].part = "wm5102"; | ||
1493 | wm5102->core.adsp[0].num = 1; | ||
1494 | wm5102->core.adsp[0].type = WMFW_ADSP2; | ||
1495 | wm5102->core.adsp[0].base = ARIZONA_DSP1_CONTROL_1; | ||
1496 | wm5102->core.adsp[0].dev = arizona->dev; | ||
1497 | wm5102->core.adsp[0].regmap = arizona->regmap; | ||
1498 | wm5102->core.adsp[0].mem = wm5102_dsp1_regions; | ||
1499 | wm5102->core.adsp[0].num_mems = ARRAY_SIZE(wm5102_dsp1_regions); | ||
1500 | |||
1501 | ret = wm_adsp2_init(&wm5102->core.adsp[0], true); | ||
1502 | if (ret != 0) | ||
1503 | return ret; | ||
1504 | |||
1437 | for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) | 1505 | for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) |
1438 | wm5102->fll[i].vco_mult = 1; | 1506 | wm5102->fll[i].vco_mult = 1; |
1439 | 1507 | ||
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 9211e4192f71..c57dc7468300 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -84,11 +84,23 @@ SOC_DOUBLE_R_TLV("IN4 Digital Volume", ARIZONA_ADC_DIGITAL_VOLUME_4L, | |||
84 | ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT, | 84 | ARIZONA_ADC_DIGITAL_VOLUME_4R, ARIZONA_IN4L_DIG_VOL_SHIFT, |
85 | 0xbf, 0, digital_tlv), | 85 | 0xbf, 0, digital_tlv), |
86 | 86 | ||
87 | SOC_ENUM("Input Ramp Up", arizona_in_vi_ramp), | ||
88 | SOC_ENUM("Input Ramp Down", arizona_in_vd_ramp), | ||
89 | |||
87 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), | 90 | ARIZONA_MIXER_CONTROLS("EQ1", ARIZONA_EQ1MIX_INPUT_1_SOURCE), |
88 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), | 91 | ARIZONA_MIXER_CONTROLS("EQ2", ARIZONA_EQ2MIX_INPUT_1_SOURCE), |
89 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), | 92 | ARIZONA_MIXER_CONTROLS("EQ3", ARIZONA_EQ3MIX_INPUT_1_SOURCE), |
90 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), | 93 | ARIZONA_MIXER_CONTROLS("EQ4", ARIZONA_EQ4MIX_INPUT_1_SOURCE), |
91 | 94 | ||
95 | SND_SOC_BYTES_MASK("EQ1 Coefficeints", ARIZONA_EQ1_1, 21, | ||
96 | ARIZONA_EQ1_ENA_MASK), | ||
97 | SND_SOC_BYTES_MASK("EQ2 Coefficeints", ARIZONA_EQ2_1, 21, | ||
98 | ARIZONA_EQ2_ENA_MASK), | ||
99 | SND_SOC_BYTES_MASK("EQ3 Coefficeints", ARIZONA_EQ3_1, 21, | ||
100 | ARIZONA_EQ3_ENA_MASK), | ||
101 | SND_SOC_BYTES_MASK("EQ4 Coefficeints", ARIZONA_EQ4_1, 21, | ||
102 | ARIZONA_EQ4_ENA_MASK), | ||
103 | |||
92 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, | 104 | SOC_SINGLE_TLV("EQ1 B1 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B1_GAIN_SHIFT, |
93 | 24, 0, eq_tlv), | 105 | 24, 0, eq_tlv), |
94 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, | 106 | SOC_SINGLE_TLV("EQ1 B2 Volume", ARIZONA_EQ1_1, ARIZONA_EQ1_B2_GAIN_SHIFT, |
@@ -148,6 +160,11 @@ ARIZONA_MIXER_CONTROLS("LHPF2", ARIZONA_HPLP2MIX_INPUT_1_SOURCE), | |||
148 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), | 160 | ARIZONA_MIXER_CONTROLS("LHPF3", ARIZONA_HPLP3MIX_INPUT_1_SOURCE), |
149 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), | 161 | ARIZONA_MIXER_CONTROLS("LHPF4", ARIZONA_HPLP4MIX_INPUT_1_SOURCE), |
150 | 162 | ||
163 | SND_SOC_BYTES("LHPF1 Coefficients", ARIZONA_HPLPF1_2, 1), | ||
164 | SND_SOC_BYTES("LHPF2 Coefficients", ARIZONA_HPLPF2_2, 1), | ||
165 | SND_SOC_BYTES("LHPF3 Coefficients", ARIZONA_HPLPF3_2, 1), | ||
166 | SND_SOC_BYTES("LHPF4 Coefficients", ARIZONA_HPLPF4_2, 1), | ||
167 | |||
151 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), | 168 | SOC_ENUM("LHPF1 Mode", arizona_lhpf1_mode), |
152 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), | 169 | SOC_ENUM("LHPF2 Mode", arizona_lhpf2_mode), |
153 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), | 170 | SOC_ENUM("LHPF3 Mode", arizona_lhpf3_mode), |
@@ -243,6 +260,9 @@ SOC_DOUBLE("SPKDAT1 Switch", ARIZONA_PDM_SPK1_CTRL_1, ARIZONA_SPK1L_MUTE_SHIFT, | |||
243 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, | 260 | SOC_DOUBLE("SPKDAT2 Switch", ARIZONA_PDM_SPK2_CTRL_1, ARIZONA_SPK2L_MUTE_SHIFT, |
244 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), | 261 | ARIZONA_SPK2R_MUTE_SHIFT, 1, 1), |
245 | 262 | ||
263 | SOC_ENUM("Output Ramp Up", arizona_out_vi_ramp), | ||
264 | SOC_ENUM("Output Ramp Down", arizona_out_vd_ramp), | ||
265 | |||
246 | ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), | 266 | ARIZONA_MIXER_CONTROLS("AIF1TX1", ARIZONA_AIF1TX1MIX_INPUT_1_SOURCE), |
247 | ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), | 267 | ARIZONA_MIXER_CONTROLS("AIF1TX2", ARIZONA_AIF1TX2MIX_INPUT_1_SOURCE), |
248 | ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), | 268 | ARIZONA_MIXER_CONTROLS("AIF1TX3", ARIZONA_AIF1TX3MIX_INPUT_1_SOURCE), |
@@ -308,10 +328,10 @@ ARIZONA_MIXER_ENUMS(AIF2TX2, ARIZONA_AIF2TX2MIX_INPUT_1_SOURCE); | |||
308 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); | 328 | ARIZONA_MIXER_ENUMS(AIF3TX1, ARIZONA_AIF3TX1MIX_INPUT_1_SOURCE); |
309 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); | 329 | ARIZONA_MIXER_ENUMS(AIF3TX2, ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE); |
310 | 330 | ||
311 | ARIZONA_MIXER_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); | 331 | ARIZONA_MUX_ENUMS(ASRC1L, ARIZONA_ASRC1LMIX_INPUT_1_SOURCE); |
312 | ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | 332 | ARIZONA_MUX_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); |
313 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 333 | ARIZONA_MUX_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
314 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 334 | ARIZONA_MUX_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
315 | 335 | ||
316 | static const char *wm5110_aec_loopback_texts[] = { | 336 | static const char *wm5110_aec_loopback_texts[] = { |
317 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", | 337 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "HPOUT3L", "HPOUT3R", |
@@ -352,6 +372,7 @@ SND_SOC_DAPM_REGULATOR_SUPPLY("SPKVDDR", 0, 0), | |||
352 | 372 | ||
353 | SND_SOC_DAPM_SIGGEN("TONE"), | 373 | SND_SOC_DAPM_SIGGEN("TONE"), |
354 | SND_SOC_DAPM_SIGGEN("NOISE"), | 374 | SND_SOC_DAPM_SIGGEN("NOISE"), |
375 | SND_SOC_DAPM_SIGGEN("HAPTICS"), | ||
355 | 376 | ||
356 | SND_SOC_DAPM_INPUT("IN1L"), | 377 | SND_SOC_DAPM_INPUT("IN1L"), |
357 | SND_SOC_DAPM_INPUT("IN1R"), | 378 | SND_SOC_DAPM_INPUT("IN1R"), |
@@ -585,10 +606,10 @@ ARIZONA_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"), | |||
585 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), | 606 | ARIZONA_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"), |
586 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), | 607 | ARIZONA_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"), |
587 | 608 | ||
588 | ARIZONA_MIXER_WIDGETS(ASRC1L, "ASRC1L"), | 609 | ARIZONA_MUX_WIDGETS(ASRC1L, "ASRC1L"), |
589 | ARIZONA_MIXER_WIDGETS(ASRC1R, "ASRC1R"), | 610 | ARIZONA_MUX_WIDGETS(ASRC1R, "ASRC1R"), |
590 | ARIZONA_MIXER_WIDGETS(ASRC2L, "ASRC2L"), | 611 | ARIZONA_MUX_WIDGETS(ASRC2L, "ASRC2L"), |
591 | ARIZONA_MIXER_WIDGETS(ASRC2R, "ASRC2R"), | 612 | ARIZONA_MUX_WIDGETS(ASRC2R, "ASRC2R"), |
592 | 613 | ||
593 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), | 614 | SND_SOC_DAPM_OUTPUT("HPOUT1L"), |
594 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), | 615 | SND_SOC_DAPM_OUTPUT("HPOUT1R"), |
@@ -610,6 +631,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT2R"), | |||
610 | { name, "Noise Generator", "Noise Generator" }, \ | 631 | { name, "Noise Generator", "Noise Generator" }, \ |
611 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 632 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
612 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 633 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
634 | { name, "Haptics", "HAPTICS" }, \ | ||
613 | { name, "AEC", "AEC Loopback" }, \ | 635 | { name, "AEC", "AEC Loopback" }, \ |
614 | { name, "IN1L", "IN1L PGA" }, \ | 636 | { name, "IN1L", "IN1L PGA" }, \ |
615 | { name, "IN1R", "IN1R PGA" }, \ | 637 | { name, "IN1R", "IN1R PGA" }, \ |
@@ -786,10 +808,10 @@ static const struct snd_soc_dapm_route wm5110_dapm_routes[] = { | |||
786 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), | 808 | ARIZONA_MIXER_ROUTES("LHPF3", "LHPF3"), |
787 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), | 809 | ARIZONA_MIXER_ROUTES("LHPF4", "LHPF4"), |
788 | 810 | ||
789 | ARIZONA_MIXER_ROUTES("ASRC1L", "ASRC1L"), | 811 | ARIZONA_MUX_ROUTES("ASRC1L"), |
790 | ARIZONA_MIXER_ROUTES("ASRC1R", "ASRC1R"), | 812 | ARIZONA_MUX_ROUTES("ASRC1R"), |
791 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | 813 | ARIZONA_MUX_ROUTES("ASRC2L"), |
792 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | 814 | ARIZONA_MUX_ROUTES("ASRC2R"), |
793 | 815 | ||
794 | { "HPOUT1L", NULL, "OUT1L" }, | 816 | { "HPOUT1L", NULL, "OUT1L" }, |
795 | { "HPOUT1R", NULL, "OUT1R" }, | 817 | { "HPOUT1R", NULL, "OUT1R" }, |
@@ -902,9 +924,29 @@ static struct snd_soc_dai_driver wm5110_dai[] = { | |||
902 | static int wm5110_codec_probe(struct snd_soc_codec *codec) | 924 | static int wm5110_codec_probe(struct snd_soc_codec *codec) |
903 | { | 925 | { |
904 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | 926 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); |
927 | int ret; | ||
905 | 928 | ||
906 | codec->control_data = priv->core.arizona->regmap; | 929 | codec->control_data = priv->core.arizona->regmap; |
907 | return snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | 930 | priv->core.arizona->dapm = &codec->dapm; |
931 | |||
932 | ret = snd_soc_codec_set_cache_io(codec, 32, 16, SND_SOC_REGMAP); | ||
933 | if (ret != 0) | ||
934 | return ret; | ||
935 | |||
936 | snd_soc_dapm_disable_pin(&codec->dapm, "HAPTICS"); | ||
937 | |||
938 | priv->core.arizona->dapm = &codec->dapm; | ||
939 | |||
940 | return 0; | ||
941 | } | ||
942 | |||
943 | static int wm5110_codec_remove(struct snd_soc_codec *codec) | ||
944 | { | ||
945 | struct wm5110_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
946 | |||
947 | priv->core.arizona->dapm = NULL; | ||
948 | |||
949 | return 0; | ||
908 | } | 950 | } |
909 | 951 | ||
910 | #define WM5110_DIG_VU 0x0200 | 952 | #define WM5110_DIG_VU 0x0200 |
@@ -935,6 +977,7 @@ static unsigned int wm5110_digital_vu[] = { | |||
935 | 977 | ||
936 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { | 978 | static struct snd_soc_codec_driver soc_codec_dev_wm5110 = { |
937 | .probe = wm5110_codec_probe, | 979 | .probe = wm5110_codec_probe, |
980 | .remove = wm5110_codec_remove, | ||
938 | 981 | ||
939 | .idle_bias_off = true, | 982 | .idle_bias_off = true, |
940 | 983 | ||
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c index a4cae060bf26..32b8f0852f6e 100644 --- a/sound/soc/codecs/wm8350.c +++ b/sound/soc/codecs/wm8350.c | |||
@@ -1500,7 +1500,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec) | |||
1500 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) | 1500 | for (i = 0; i < ARRAY_SIZE(supply_names); i++) |
1501 | priv->supplies[i].supply = supply_names[i]; | 1501 | priv->supplies[i].supply = supply_names[i]; |
1502 | 1502 | ||
1503 | ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), | 1503 | ret = devm_regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies), |
1504 | priv->supplies); | 1504 | priv->supplies); |
1505 | if (ret != 0) | 1505 | if (ret != 0) |
1506 | return ret; | 1506 | return ret; |
@@ -1607,8 +1607,6 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec) | |||
1607 | 1607 | ||
1608 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); | 1608 | wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); |
1609 | 1609 | ||
1610 | regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies); | ||
1611 | |||
1612 | return 0; | 1610 | return 0; |
1613 | } | 1611 | } |
1614 | 1612 | ||
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index 5d277a915f81..262c44082eb0 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -1373,7 +1373,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1373 | codec->control_data = priv->wm8400 = wm8400; | 1373 | codec->control_data = priv->wm8400 = wm8400; |
1374 | priv->codec = codec; | 1374 | priv->codec = codec; |
1375 | 1375 | ||
1376 | ret = regulator_bulk_get(wm8400->dev, | 1376 | ret = devm_regulator_bulk_get(wm8400->dev, |
1377 | ARRAY_SIZE(power), &power[0]); | 1377 | ARRAY_SIZE(power), &power[0]); |
1378 | if (ret != 0) { | 1378 | if (ret != 0) { |
1379 | dev_err(codec->dev, "Failed to get regulators: %d\n", ret); | 1379 | dev_err(codec->dev, "Failed to get regulators: %d\n", ret); |
@@ -1398,15 +1398,9 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec) | |||
1398 | snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1398 | snd_soc_write(codec, WM8400_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1399 | snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); | 1399 | snd_soc_write(codec, WM8400_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8)); |
1400 | 1400 | ||
1401 | if (!schedule_work(&priv->work)) { | 1401 | if (!schedule_work(&priv->work)) |
1402 | ret = -EINVAL; | 1402 | return -EINVAL; |
1403 | goto err_regulator; | ||
1404 | } | ||
1405 | return 0; | 1403 | return 0; |
1406 | |||
1407 | err_regulator: | ||
1408 | regulator_bulk_free(ARRAY_SIZE(power), power); | ||
1409 | return ret; | ||
1410 | } | 1404 | } |
1411 | 1405 | ||
1412 | static int wm8400_codec_remove(struct snd_soc_codec *codec) | 1406 | static int wm8400_codec_remove(struct snd_soc_codec *codec) |
@@ -1417,8 +1411,6 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec) | |||
1417 | snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, | 1411 | snd_soc_write(codec, WM8400_POWER_MANAGEMENT_1, |
1418 | reg & (~WM8400_CODEC_ENA)); | 1412 | reg & (~WM8400_CODEC_ENA)); |
1419 | 1413 | ||
1420 | regulator_bulk_free(ARRAY_SIZE(power), power); | ||
1421 | |||
1422 | return 0; | 1414 | return 0; |
1423 | } | 1415 | } |
1424 | 1416 | ||
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index c12a54e72e89..923e7e1f6704 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -608,10 +608,7 @@ static int wm8510_probe(struct snd_soc_codec *codec) | |||
608 | /* power down chip */ | 608 | /* power down chip */ |
609 | static int wm8510_remove(struct snd_soc_codec *codec) | 609 | static int wm8510_remove(struct snd_soc_codec *codec) |
610 | { | 610 | { |
611 | struct wm8510_priv *wm8510 = snd_soc_codec_get_drvdata(codec); | ||
612 | |||
613 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); | 611 | wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF); |
614 | kfree(wm8510); | ||
615 | return 0; | 612 | return 0; |
616 | } | 613 | } |
617 | 614 | ||
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 4281a0802138..99b8ebe93424 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -522,7 +522,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c, | |||
522 | return ret; | 522 | return ret; |
523 | } | 523 | } |
524 | 524 | ||
525 | wm8741->regmap = regmap_init_i2c(i2c, &wm8741_regmap); | 525 | wm8741->regmap = devm_regmap_init_i2c(i2c, &wm8741_regmap); |
526 | if (IS_ERR(wm8741->regmap)) { | 526 | if (IS_ERR(wm8741->regmap)) { |
527 | ret = PTR_ERR(wm8741->regmap); | 527 | ret = PTR_ERR(wm8741->regmap); |
528 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | 528 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); |
@@ -582,7 +582,7 @@ static int __devinit wm8741_spi_probe(struct spi_device *spi) | |||
582 | return ret; | 582 | return ret; |
583 | } | 583 | } |
584 | 584 | ||
585 | wm8741->regmap = regmap_init_spi(spi, &wm8741_regmap); | 585 | wm8741->regmap = devm_regmap_init_spi(spi, &wm8741_regmap); |
586 | if (IS_ERR(wm8741->regmap)) { | 586 | if (IS_ERR(wm8741->regmap)) { |
587 | ret = PTR_ERR(wm8741->regmap); | 587 | ret = PTR_ERR(wm8741->regmap); |
588 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | 588 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index 89151ca5e776..7665d68c4558 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/regmap.h> | ||
21 | #include <linux/spi/spi.h> | 22 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | 24 | #include <linux/of_device.h> |
@@ -34,24 +35,55 @@ | |||
34 | * We can't read the WM8750 register space when we | 35 | * We can't read the WM8750 register space when we |
35 | * are using 2 wire for device control, so we cache them instead. | 36 | * are using 2 wire for device control, so we cache them instead. |
36 | */ | 37 | */ |
37 | static const u16 wm8750_reg[] = { | 38 | static const struct reg_default wm8750_reg_defaults[] = { |
38 | 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ | 39 | { 0, 0x0097 }, |
39 | 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ | 40 | { 1, 0x0097 }, |
40 | 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ | 41 | { 2, 0x0079 }, |
41 | 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ | 42 | { 3, 0x0079 }, |
42 | 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ | 43 | { 4, 0x0000 }, |
43 | 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ | 44 | { 5, 0x0008 }, |
44 | 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ | 45 | { 6, 0x0000 }, |
45 | 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ | 46 | { 7, 0x000a }, |
46 | 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ | 47 | { 8, 0x0000 }, |
47 | 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ | 48 | { 9, 0x0000 }, |
48 | 0x0079, 0x0079, 0x0079, /* 40 */ | 49 | { 10, 0x00ff }, |
50 | { 11, 0x00ff }, | ||
51 | { 12, 0x000f }, | ||
52 | { 13, 0x000f }, | ||
53 | { 14, 0x0000 }, | ||
54 | { 15, 0x0000 }, | ||
55 | { 16, 0x0000 }, | ||
56 | { 17, 0x007b }, | ||
57 | { 18, 0x0000 }, | ||
58 | { 19, 0x0032 }, | ||
59 | { 20, 0x0000 }, | ||
60 | { 21, 0x00c3 }, | ||
61 | { 22, 0x00c3 }, | ||
62 | { 23, 0x00c0 }, | ||
63 | { 24, 0x0000 }, | ||
64 | { 25, 0x0000 }, | ||
65 | { 26, 0x0000 }, | ||
66 | { 27, 0x0000 }, | ||
67 | { 28, 0x0000 }, | ||
68 | { 29, 0x0000 }, | ||
69 | { 30, 0x0000 }, | ||
70 | { 31, 0x0000 }, | ||
71 | { 32, 0x0000 }, | ||
72 | { 33, 0x0000 }, | ||
73 | { 34, 0x0050 }, | ||
74 | { 35, 0x0050 }, | ||
75 | { 36, 0x0050 }, | ||
76 | { 37, 0x0050 }, | ||
77 | { 38, 0x0050 }, | ||
78 | { 39, 0x0050 }, | ||
79 | { 40, 0x0079 }, | ||
80 | { 41, 0x0079 }, | ||
81 | { 42, 0x0079 }, | ||
49 | }; | 82 | }; |
50 | 83 | ||
51 | /* codec private data */ | 84 | /* codec private data */ |
52 | struct wm8750_priv { | 85 | struct wm8750_priv { |
53 | unsigned int sysclk; | 86 | unsigned int sysclk; |
54 | enum snd_soc_control_type control_type; | ||
55 | }; | 87 | }; |
56 | 88 | ||
57 | #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) | 89 | #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) |
@@ -668,10 +700,9 @@ static int wm8750_resume(struct snd_soc_codec *codec) | |||
668 | 700 | ||
669 | static int wm8750_probe(struct snd_soc_codec *codec) | 701 | static int wm8750_probe(struct snd_soc_codec *codec) |
670 | { | 702 | { |
671 | struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); | ||
672 | int ret; | 703 | int ret; |
673 | 704 | ||
674 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type); | 705 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
675 | if (ret < 0) { | 706 | if (ret < 0) { |
676 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); | 707 | printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); |
677 | return ret; | 708 | return ret; |
@@ -711,9 +742,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { | |||
711 | .suspend = wm8750_suspend, | 742 | .suspend = wm8750_suspend, |
712 | .resume = wm8750_resume, | 743 | .resume = wm8750_resume, |
713 | .set_bias_level = wm8750_set_bias_level, | 744 | .set_bias_level = wm8750_set_bias_level, |
714 | .reg_cache_size = ARRAY_SIZE(wm8750_reg), | ||
715 | .reg_word_size = sizeof(u16), | ||
716 | .reg_cache_default = wm8750_reg, | ||
717 | 745 | ||
718 | .controls = wm8750_snd_controls, | 746 | .controls = wm8750_snd_controls, |
719 | .num_controls = ARRAY_SIZE(wm8750_snd_controls), | 747 | .num_controls = ARRAY_SIZE(wm8750_snd_controls), |
@@ -730,10 +758,21 @@ static const struct of_device_id wm8750_of_match[] = { | |||
730 | }; | 758 | }; |
731 | MODULE_DEVICE_TABLE(of, wm8750_of_match); | 759 | MODULE_DEVICE_TABLE(of, wm8750_of_match); |
732 | 760 | ||
761 | static const struct regmap_config wm8750_regmap = { | ||
762 | .reg_bits = 7, | ||
763 | .val_bits = 9, | ||
764 | .max_register = WM8750_MOUTV, | ||
765 | |||
766 | .reg_defaults = wm8750_reg_defaults, | ||
767 | .num_reg_defaults = ARRAY_SIZE(wm8750_reg_defaults), | ||
768 | .cache_type = REGCACHE_RBTREE, | ||
769 | }; | ||
770 | |||
733 | #if defined(CONFIG_SPI_MASTER) | 771 | #if defined(CONFIG_SPI_MASTER) |
734 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 772 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
735 | { | 773 | { |
736 | struct wm8750_priv *wm8750; | 774 | struct wm8750_priv *wm8750; |
775 | struct regmap *regmap; | ||
737 | int ret; | 776 | int ret; |
738 | 777 | ||
739 | wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv), | 778 | wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv), |
@@ -741,7 +780,10 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi) | |||
741 | if (wm8750 == NULL) | 780 | if (wm8750 == NULL) |
742 | return -ENOMEM; | 781 | return -ENOMEM; |
743 | 782 | ||
744 | wm8750->control_type = SND_SOC_SPI; | 783 | regmap = devm_regmap_init_spi(spi, &wm8750_regmap); |
784 | if (IS_ERR(regmap)) | ||
785 | return PTR_ERR(regmap); | ||
786 | |||
745 | spi_set_drvdata(spi, wm8750); | 787 | spi_set_drvdata(spi, wm8750); |
746 | 788 | ||
747 | ret = snd_soc_register_codec(&spi->dev, | 789 | ret = snd_soc_register_codec(&spi->dev, |
@@ -779,6 +821,7 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, | |||
779 | const struct i2c_device_id *id) | 821 | const struct i2c_device_id *id) |
780 | { | 822 | { |
781 | struct wm8750_priv *wm8750; | 823 | struct wm8750_priv *wm8750; |
824 | struct regmap *regmap; | ||
782 | int ret; | 825 | int ret; |
783 | 826 | ||
784 | wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv), | 827 | wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv), |
@@ -787,7 +830,10 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c, | |||
787 | return -ENOMEM; | 830 | return -ENOMEM; |
788 | 831 | ||
789 | i2c_set_clientdata(i2c, wm8750); | 832 | i2c_set_clientdata(i2c, wm8750); |
790 | wm8750->control_type = SND_SOC_I2C; | 833 | |
834 | regmap = devm_regmap_init_i2c(i2c, &wm8750_regmap); | ||
835 | if (IS_ERR(regmap)) | ||
836 | return PTR_ERR(regmap); | ||
791 | 837 | ||
792 | ret = snd_soc_register_codec(&i2c->dev, | 838 | ret = snd_soc_register_codec(&i2c->dev, |
793 | &soc_codec_dev_wm8750, &wm8750_dai, 1); | 839 | &soc_codec_dev_wm8750, &wm8750_dai, 1); |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index 2e4a775ae560..50a5dc7974e1 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -1562,36 +1562,25 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi) | |||
1562 | 1562 | ||
1563 | spi_set_drvdata(spi, wm8753); | 1563 | spi_set_drvdata(spi, wm8753); |
1564 | 1564 | ||
1565 | wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap); | 1565 | wm8753->regmap = devm_regmap_init_spi(spi, &wm8753_regmap); |
1566 | if (IS_ERR(wm8753->regmap)) { | 1566 | if (IS_ERR(wm8753->regmap)) { |
1567 | ret = PTR_ERR(wm8753->regmap); | 1567 | ret = PTR_ERR(wm8753->regmap); |
1568 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", | 1568 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", |
1569 | ret); | 1569 | ret); |
1570 | goto err; | 1570 | return ret; |
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753, | 1573 | ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753, |
1574 | wm8753_dai, ARRAY_SIZE(wm8753_dai)); | 1574 | wm8753_dai, ARRAY_SIZE(wm8753_dai)); |
1575 | if (ret != 0) { | 1575 | if (ret != 0) |
1576 | dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); | 1576 | dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret); |
1577 | goto err_regmap; | ||
1578 | } | ||
1579 | 1577 | ||
1580 | return 0; | ||
1581 | |||
1582 | err_regmap: | ||
1583 | regmap_exit(wm8753->regmap); | ||
1584 | err: | ||
1585 | return ret; | 1578 | return ret; |
1586 | } | 1579 | } |
1587 | 1580 | ||
1588 | static int __devexit wm8753_spi_remove(struct spi_device *spi) | 1581 | static int __devexit wm8753_spi_remove(struct spi_device *spi) |
1589 | { | 1582 | { |
1590 | struct wm8753_priv *wm8753 = spi_get_drvdata(spi); | ||
1591 | |||
1592 | snd_soc_unregister_codec(&spi->dev); | 1583 | snd_soc_unregister_codec(&spi->dev); |
1593 | regmap_exit(wm8753->regmap); | ||
1594 | kfree(wm8753); | ||
1595 | return 0; | 1584 | return 0; |
1596 | } | 1585 | } |
1597 | 1586 | ||
@@ -1620,35 +1609,25 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c, | |||
1620 | 1609 | ||
1621 | i2c_set_clientdata(i2c, wm8753); | 1610 | i2c_set_clientdata(i2c, wm8753); |
1622 | 1611 | ||
1623 | wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap); | 1612 | wm8753->regmap = devm_regmap_init_i2c(i2c, &wm8753_regmap); |
1624 | if (IS_ERR(wm8753->regmap)) { | 1613 | if (IS_ERR(wm8753->regmap)) { |
1625 | ret = PTR_ERR(wm8753->regmap); | 1614 | ret = PTR_ERR(wm8753->regmap); |
1626 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 1615 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
1627 | ret); | 1616 | ret); |
1628 | goto err; | 1617 | return ret; |
1629 | } | 1618 | } |
1630 | 1619 | ||
1631 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753, | 1620 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753, |
1632 | wm8753_dai, ARRAY_SIZE(wm8753_dai)); | 1621 | wm8753_dai, ARRAY_SIZE(wm8753_dai)); |
1633 | if (ret != 0) { | 1622 | if (ret != 0) |
1634 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | 1623 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); |
1635 | goto err_regmap; | ||
1636 | } | ||
1637 | 1624 | ||
1638 | return 0; | ||
1639 | |||
1640 | err_regmap: | ||
1641 | regmap_exit(wm8753->regmap); | ||
1642 | err: | ||
1643 | return ret; | 1625 | return ret; |
1644 | } | 1626 | } |
1645 | 1627 | ||
1646 | static __devexit int wm8753_i2c_remove(struct i2c_client *client) | 1628 | static __devexit int wm8753_i2c_remove(struct i2c_client *client) |
1647 | { | 1629 | { |
1648 | struct wm8753_priv *wm8753 = i2c_get_clientdata(client); | ||
1649 | |||
1650 | snd_soc_unregister_codec(&client->dev); | 1630 | snd_soc_unregister_codec(&client->dev); |
1651 | regmap_exit(wm8753->regmap); | ||
1652 | return 0; | 1631 | return 0; |
1653 | } | 1632 | } |
1654 | 1633 | ||
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index c7c0034d3966..0b690ba875f8 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/of_device.h> | 17 | #include <linux/of_device.h> |
18 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | #include <linux/regmap.h> | ||
20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
@@ -35,19 +36,52 @@ static const char *wm8770_supply_names[WM8770_NUM_SUPPLIES] = { | |||
35 | "DVDD" | 36 | "DVDD" |
36 | }; | 37 | }; |
37 | 38 | ||
38 | static const u16 wm8770_reg_defs[WM8770_CACHEREGNUM] = { | 39 | static const struct reg_default wm8770_reg_defaults[] = { |
39 | 0x7f, 0x7f, 0x7f, 0x7f, | 40 | { 0, 0x7f }, |
40 | 0x7f, 0x7f, 0x7f, 0x7f, | 41 | { 1, 0x7f }, |
41 | 0x7f, 0xff, 0xff, 0xff, | 42 | { 2, 0x7f }, |
42 | 0xff, 0xff, 0xff, 0xff, | 43 | { 3, 0x7f }, |
43 | 0xff, 0xff, 0, 0x90, 0, | 44 | { 4, 0x7f }, |
44 | 0, 0x22, 0x22, 0x3e, | 45 | { 5, 0x7f }, |
45 | 0xc, 0xc, 0x100, 0x189, | 46 | { 6, 0x7f }, |
46 | 0x189, 0x8770 | 47 | { 7, 0x7f }, |
48 | { 8, 0x7f }, | ||
49 | { 9, 0xff }, | ||
50 | { 10, 0xff }, | ||
51 | { 11, 0xff }, | ||
52 | { 12, 0xff }, | ||
53 | { 13, 0xff }, | ||
54 | { 14, 0xff }, | ||
55 | { 15, 0xff }, | ||
56 | { 16, 0xff }, | ||
57 | { 17, 0xff }, | ||
58 | { 18, 0 }, | ||
59 | { 19, 0x90 }, | ||
60 | { 20, 0 }, | ||
61 | { 21, 0 }, | ||
62 | { 22, 0x22 }, | ||
63 | { 23, 0x22 }, | ||
64 | { 24, 0x3e }, | ||
65 | { 25, 0xc }, | ||
66 | { 26, 0xc }, | ||
67 | { 27, 0x100 }, | ||
68 | { 28, 0x189 }, | ||
69 | { 29, 0x189 }, | ||
70 | { 30, 0x8770 }, | ||
47 | }; | 71 | }; |
48 | 72 | ||
73 | static bool wm8770_volatile_reg(struct device *dev, unsigned int reg) | ||
74 | { | ||
75 | switch (reg) { | ||
76 | case WM8770_RESET: | ||
77 | return true; | ||
78 | default: | ||
79 | return false; | ||
80 | } | ||
81 | } | ||
82 | |||
49 | struct wm8770_priv { | 83 | struct wm8770_priv { |
50 | enum snd_soc_control_type control_type; | 84 | struct regmap *regmap; |
51 | struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES]; | 85 | struct regulator_bulk_data supplies[WM8770_NUM_SUPPLIES]; |
52 | struct notifier_block disable_nb[WM8770_NUM_SUPPLIES]; | 86 | struct notifier_block disable_nb[WM8770_NUM_SUPPLIES]; |
53 | struct snd_soc_codec *codec; | 87 | struct snd_soc_codec *codec; |
@@ -71,7 +105,7 @@ static int wm8770_regulator_event_##n(struct notifier_block *nb, \ | |||
71 | struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \ | 105 | struct wm8770_priv *wm8770 = container_of(nb, struct wm8770_priv, \ |
72 | disable_nb[n]); \ | 106 | disable_nb[n]); \ |
73 | if (event & REGULATOR_EVENT_DISABLE) { \ | 107 | if (event & REGULATOR_EVENT_DISABLE) { \ |
74 | wm8770->codec->cache_sync = 1; \ | 108 | regcache_mark_dirty(wm8770->regmap); \ |
75 | } \ | 109 | } \ |
76 | return 0; \ | 110 | return 0; \ |
77 | } | 111 | } |
@@ -466,24 +500,6 @@ static int wm8770_set_sysclk(struct snd_soc_dai *dai, | |||
466 | return 0; | 500 | return 0; |
467 | } | 501 | } |
468 | 502 | ||
469 | static void wm8770_sync_cache(struct snd_soc_codec *codec) | ||
470 | { | ||
471 | int i; | ||
472 | u16 *cache; | ||
473 | |||
474 | if (!codec->cache_sync) | ||
475 | return; | ||
476 | |||
477 | codec->cache_only = 0; | ||
478 | cache = codec->reg_cache; | ||
479 | for (i = 0; i < codec->driver->reg_cache_size; i++) { | ||
480 | if (i == WM8770_RESET || cache[i] == wm8770_reg_defs[i]) | ||
481 | continue; | ||
482 | snd_soc_write(codec, i, cache[i]); | ||
483 | } | ||
484 | codec->cache_sync = 0; | ||
485 | } | ||
486 | |||
487 | static int wm8770_set_bias_level(struct snd_soc_codec *codec, | 503 | static int wm8770_set_bias_level(struct snd_soc_codec *codec, |
488 | enum snd_soc_bias_level level) | 504 | enum snd_soc_bias_level level) |
489 | { | 505 | { |
@@ -507,7 +523,9 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec, | |||
507 | ret); | 523 | ret); |
508 | return ret; | 524 | return ret; |
509 | } | 525 | } |
510 | wm8770_sync_cache(codec); | 526 | |
527 | regcache_sync(wm8770->regmap); | ||
528 | |||
511 | /* global powerup */ | 529 | /* global powerup */ |
512 | snd_soc_write(codec, WM8770_PWDNCTRL, 0); | 530 | snd_soc_write(codec, WM8770_PWDNCTRL, 0); |
513 | } | 531 | } |
@@ -554,68 +572,25 @@ static struct snd_soc_dai_driver wm8770_dai = { | |||
554 | .symmetric_rates = 1 | 572 | .symmetric_rates = 1 |
555 | }; | 573 | }; |
556 | 574 | ||
557 | #ifdef CONFIG_PM | ||
558 | static int wm8770_suspend(struct snd_soc_codec *codec) | ||
559 | { | ||
560 | wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
561 | return 0; | ||
562 | } | ||
563 | |||
564 | static int wm8770_resume(struct snd_soc_codec *codec) | ||
565 | { | ||
566 | wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
567 | return 0; | ||
568 | } | ||
569 | #else | ||
570 | #define wm8770_suspend NULL | ||
571 | #define wm8770_resume NULL | ||
572 | #endif | ||
573 | |||
574 | static int wm8770_probe(struct snd_soc_codec *codec) | 575 | static int wm8770_probe(struct snd_soc_codec *codec) |
575 | { | 576 | { |
576 | struct wm8770_priv *wm8770; | 577 | struct wm8770_priv *wm8770; |
577 | int ret; | 578 | int ret; |
578 | int i; | ||
579 | 579 | ||
580 | wm8770 = snd_soc_codec_get_drvdata(codec); | 580 | wm8770 = snd_soc_codec_get_drvdata(codec); |
581 | wm8770->codec = codec; | 581 | wm8770->codec = codec; |
582 | 582 | ||
583 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type); | 583 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
584 | if (ret < 0) { | 584 | if (ret < 0) { |
585 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 585 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
586 | return ret; | 586 | return ret; |
587 | } | 587 | } |
588 | 588 | ||
589 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) | ||
590 | wm8770->supplies[i].supply = wm8770_supply_names[i]; | ||
591 | |||
592 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8770->supplies), | ||
593 | wm8770->supplies); | ||
594 | if (ret) { | ||
595 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
596 | return ret; | ||
597 | } | ||
598 | |||
599 | wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0; | ||
600 | wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1; | ||
601 | wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2; | ||
602 | |||
603 | /* This should really be moved into the regulator core */ | ||
604 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) { | ||
605 | ret = regulator_register_notifier(wm8770->supplies[i].consumer, | ||
606 | &wm8770->disable_nb[i]); | ||
607 | if (ret) { | ||
608 | dev_err(codec->dev, | ||
609 | "Failed to register regulator notifier: %d\n", | ||
610 | ret); | ||
611 | } | ||
612 | } | ||
613 | |||
614 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), | 589 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8770->supplies), |
615 | wm8770->supplies); | 590 | wm8770->supplies); |
616 | if (ret) { | 591 | if (ret) { |
617 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 592 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
618 | goto err_reg_get; | 593 | return ret; |
619 | } | 594 | } |
620 | 595 | ||
621 | ret = wm8770_reset(codec); | 596 | ret = wm8770_reset(codec); |
@@ -624,8 +599,6 @@ static int wm8770_probe(struct snd_soc_codec *codec) | |||
624 | goto err_reg_enable; | 599 | goto err_reg_enable; |
625 | } | 600 | } |
626 | 601 | ||
627 | wm8770_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
628 | |||
629 | /* latch the volume update bits */ | 602 | /* latch the volume update bits */ |
630 | snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100); | 603 | snd_soc_update_bits(codec, WM8770_MSDIGVOL, 0x100, 0x100); |
631 | snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100); | 604 | snd_soc_update_bits(codec, WM8770_MSALGVOL, 0x100, 0x100); |
@@ -641,46 +614,22 @@ static int wm8770_probe(struct snd_soc_codec *codec) | |||
641 | /* mute all DACs */ | 614 | /* mute all DACs */ |
642 | snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10); | 615 | snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10); |
643 | 616 | ||
644 | snd_soc_add_codec_controls(codec, wm8770_snd_controls, | ||
645 | ARRAY_SIZE(wm8770_snd_controls)); | ||
646 | snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets, | ||
647 | ARRAY_SIZE(wm8770_dapm_widgets)); | ||
648 | snd_soc_dapm_add_routes(&codec->dapm, wm8770_intercon, | ||
649 | ARRAY_SIZE(wm8770_intercon)); | ||
650 | return 0; | ||
651 | |||
652 | err_reg_enable: | 617 | err_reg_enable: |
653 | regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); | 618 | regulator_bulk_disable(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); |
654 | err_reg_get: | ||
655 | regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); | ||
656 | return ret; | 619 | return ret; |
657 | } | 620 | } |
658 | 621 | ||
659 | static int wm8770_remove(struct snd_soc_codec *codec) | ||
660 | { | ||
661 | struct wm8770_priv *wm8770; | ||
662 | int i; | ||
663 | |||
664 | wm8770 = snd_soc_codec_get_drvdata(codec); | ||
665 | wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
666 | |||
667 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i) | ||
668 | regulator_unregister_notifier(wm8770->supplies[i].consumer, | ||
669 | &wm8770->disable_nb[i]); | ||
670 | regulator_bulk_free(ARRAY_SIZE(wm8770->supplies), wm8770->supplies); | ||
671 | return 0; | ||
672 | } | ||
673 | |||
674 | static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { | 622 | static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { |
675 | .probe = wm8770_probe, | 623 | .probe = wm8770_probe, |
676 | .remove = wm8770_remove, | ||
677 | .suspend = wm8770_suspend, | ||
678 | .resume = wm8770_resume, | ||
679 | .set_bias_level = wm8770_set_bias_level, | 624 | .set_bias_level = wm8770_set_bias_level, |
680 | .idle_bias_off = true, | 625 | .idle_bias_off = true, |
681 | .reg_cache_size = ARRAY_SIZE(wm8770_reg_defs), | 626 | |
682 | .reg_word_size = sizeof (u16), | 627 | .controls = wm8770_snd_controls, |
683 | .reg_cache_default = wm8770_reg_defs | 628 | .num_controls = ARRAY_SIZE(wm8770_snd_controls), |
629 | .dapm_widgets = wm8770_dapm_widgets, | ||
630 | .num_dapm_widgets = ARRAY_SIZE(wm8770_dapm_widgets), | ||
631 | .dapm_routes = wm8770_intercon, | ||
632 | .num_dapm_routes = ARRAY_SIZE(wm8770_intercon), | ||
684 | }; | 633 | }; |
685 | 634 | ||
686 | static const struct of_device_id wm8770_of_match[] = { | 635 | static const struct of_device_id wm8770_of_match[] = { |
@@ -689,17 +638,57 @@ static const struct of_device_id wm8770_of_match[] = { | |||
689 | }; | 638 | }; |
690 | MODULE_DEVICE_TABLE(of, wm8770_of_match); | 639 | MODULE_DEVICE_TABLE(of, wm8770_of_match); |
691 | 640 | ||
641 | static const struct regmap_config wm8770_regmap = { | ||
642 | .reg_bits = 7, | ||
643 | .val_bits = 9, | ||
644 | .max_register = WM8770_RESET, | ||
645 | |||
646 | .reg_defaults = wm8770_reg_defaults, | ||
647 | .num_reg_defaults = ARRAY_SIZE(wm8770_reg_defaults), | ||
648 | .cache_type = REGCACHE_RBTREE, | ||
649 | |||
650 | .volatile_reg = wm8770_volatile_reg, | ||
651 | }; | ||
652 | |||
692 | static int __devinit wm8770_spi_probe(struct spi_device *spi) | 653 | static int __devinit wm8770_spi_probe(struct spi_device *spi) |
693 | { | 654 | { |
694 | struct wm8770_priv *wm8770; | 655 | struct wm8770_priv *wm8770; |
695 | int ret; | 656 | int ret, i; |
696 | 657 | ||
697 | wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv), | 658 | wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv), |
698 | GFP_KERNEL); | 659 | GFP_KERNEL); |
699 | if (!wm8770) | 660 | if (!wm8770) |
700 | return -ENOMEM; | 661 | return -ENOMEM; |
701 | 662 | ||
702 | wm8770->control_type = SND_SOC_SPI; | 663 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) |
664 | wm8770->supplies[i].supply = wm8770_supply_names[i]; | ||
665 | |||
666 | ret = devm_regulator_bulk_get(&spi->dev, ARRAY_SIZE(wm8770->supplies), | ||
667 | wm8770->supplies); | ||
668 | if (ret) { | ||
669 | dev_err(&spi->dev, "Failed to request supplies: %d\n", ret); | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | wm8770->disable_nb[0].notifier_call = wm8770_regulator_event_0; | ||
674 | wm8770->disable_nb[1].notifier_call = wm8770_regulator_event_1; | ||
675 | wm8770->disable_nb[2].notifier_call = wm8770_regulator_event_2; | ||
676 | |||
677 | /* This should really be moved into the regulator core */ | ||
678 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); i++) { | ||
679 | ret = regulator_register_notifier(wm8770->supplies[i].consumer, | ||
680 | &wm8770->disable_nb[i]); | ||
681 | if (ret) { | ||
682 | dev_err(&spi->dev, | ||
683 | "Failed to register regulator notifier: %d\n", | ||
684 | ret); | ||
685 | } | ||
686 | } | ||
687 | |||
688 | wm8770->regmap = devm_regmap_init_spi(spi, &wm8770_regmap); | ||
689 | if (IS_ERR(wm8770->regmap)) | ||
690 | return PTR_ERR(wm8770->regmap); | ||
691 | |||
703 | spi_set_drvdata(spi, wm8770); | 692 | spi_set_drvdata(spi, wm8770); |
704 | 693 | ||
705 | ret = snd_soc_register_codec(&spi->dev, | 694 | ret = snd_soc_register_codec(&spi->dev, |
@@ -710,7 +699,15 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi) | |||
710 | 699 | ||
711 | static int __devexit wm8770_spi_remove(struct spi_device *spi) | 700 | static int __devexit wm8770_spi_remove(struct spi_device *spi) |
712 | { | 701 | { |
702 | struct wm8770_priv *wm8770 = spi_get_drvdata(spi); | ||
703 | int i; | ||
704 | |||
705 | for (i = 0; i < ARRAY_SIZE(wm8770->supplies); ++i) | ||
706 | regulator_unregister_notifier(wm8770->supplies[i].consumer, | ||
707 | &wm8770->disable_nb[i]); | ||
708 | |||
713 | snd_soc_unregister_codec(&spi->dev); | 709 | snd_soc_unregister_codec(&spi->dev); |
710 | |||
714 | return 0; | 711 | return 0; |
715 | } | 712 | } |
716 | 713 | ||
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index c088020172ab..837bfb51cebf 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -711,7 +711,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi) | |||
711 | if (!wm8804) | 711 | if (!wm8804) |
712 | return -ENOMEM; | 712 | return -ENOMEM; |
713 | 713 | ||
714 | wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config); | 714 | wm8804->regmap = devm_regmap_init_spi(spi, &wm8804_regmap_config); |
715 | if (IS_ERR(wm8804->regmap)) { | 715 | if (IS_ERR(wm8804->regmap)) { |
716 | ret = PTR_ERR(wm8804->regmap); | 716 | ret = PTR_ERR(wm8804->regmap); |
717 | return ret; | 717 | return ret; |
@@ -727,9 +727,7 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi) | |||
727 | 727 | ||
728 | static int __devexit wm8804_spi_remove(struct spi_device *spi) | 728 | static int __devexit wm8804_spi_remove(struct spi_device *spi) |
729 | { | 729 | { |
730 | struct wm8804_priv *wm8804 = spi_get_drvdata(spi); | ||
731 | snd_soc_unregister_codec(&spi->dev); | 730 | snd_soc_unregister_codec(&spi->dev); |
732 | regmap_exit(wm8804->regmap); | ||
733 | return 0; | 731 | return 0; |
734 | } | 732 | } |
735 | 733 | ||
@@ -755,7 +753,7 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c, | |||
755 | if (!wm8804) | 753 | if (!wm8804) |
756 | return -ENOMEM; | 754 | return -ENOMEM; |
757 | 755 | ||
758 | wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config); | 756 | wm8804->regmap = devm_regmap_init_i2c(i2c, &wm8804_regmap_config); |
759 | if (IS_ERR(wm8804->regmap)) { | 757 | if (IS_ERR(wm8804->regmap)) { |
760 | ret = PTR_ERR(wm8804->regmap); | 758 | ret = PTR_ERR(wm8804->regmap); |
761 | return ret; | 759 | return ret; |
@@ -765,23 +763,12 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c, | |||
765 | 763 | ||
766 | ret = snd_soc_register_codec(&i2c->dev, | 764 | ret = snd_soc_register_codec(&i2c->dev, |
767 | &soc_codec_dev_wm8804, &wm8804_dai, 1); | 765 | &soc_codec_dev_wm8804, &wm8804_dai, 1); |
768 | if (ret != 0) | ||
769 | goto err; | ||
770 | |||
771 | return 0; | ||
772 | |||
773 | err: | ||
774 | regmap_exit(wm8804->regmap); | ||
775 | return ret; | 766 | return ret; |
776 | } | 767 | } |
777 | 768 | ||
778 | static __devexit int wm8804_i2c_remove(struct i2c_client *i2c) | 769 | static __devexit int wm8804_i2c_remove(struct i2c_client *i2c) |
779 | { | 770 | { |
780 | struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c); | ||
781 | |||
782 | snd_soc_unregister_codec(&i2c->dev); | 771 | snd_soc_unregister_codec(&i2c->dev); |
783 | regmap_exit(wm8804->regmap); | ||
784 | |||
785 | return 0; | 772 | return 0; |
786 | } | 773 | } |
787 | 774 | ||
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 2f1c075755b1..7a82b7d28dcd 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -1023,7 +1023,7 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, | |||
1023 | if (wm8955 == NULL) | 1023 | if (wm8955 == NULL) |
1024 | return -ENOMEM; | 1024 | return -ENOMEM; |
1025 | 1025 | ||
1026 | wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap); | 1026 | wm8955->regmap = devm_regmap_init_i2c(i2c, &wm8955_regmap); |
1027 | if (IS_ERR(wm8955->regmap)) { | 1027 | if (IS_ERR(wm8955->regmap)) { |
1028 | ret = PTR_ERR(wm8955->regmap); | 1028 | ret = PTR_ERR(wm8955->regmap); |
1029 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 1029 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
@@ -1035,22 +1035,13 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, | |||
1035 | 1035 | ||
1036 | ret = snd_soc_register_codec(&i2c->dev, | 1036 | ret = snd_soc_register_codec(&i2c->dev, |
1037 | &soc_codec_dev_wm8955, &wm8955_dai, 1); | 1037 | &soc_codec_dev_wm8955, &wm8955_dai, 1); |
1038 | if (ret != 0) | ||
1039 | goto err; | ||
1040 | 1038 | ||
1041 | return ret; | 1039 | return ret; |
1042 | |||
1043 | err: | ||
1044 | regmap_exit(wm8955->regmap); | ||
1045 | return ret; | ||
1046 | } | 1040 | } |
1047 | 1041 | ||
1048 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) | 1042 | static __devexit int wm8955_i2c_remove(struct i2c_client *client) |
1049 | { | 1043 | { |
1050 | struct wm8955_priv *wm8955 = i2c_get_clientdata(client); | ||
1051 | |||
1052 | snd_soc_unregister_codec(&client->dev); | 1044 | snd_soc_unregister_codec(&client->dev); |
1053 | regmap_exit(wm8955->regmap); | ||
1054 | 1045 | ||
1055 | return 0; | 1046 | return 0; |
1056 | } | 1047 | } |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 00121ba36597..b0710d817a65 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -195,7 +195,7 @@ ok: | |||
195 | static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) | 195 | static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) |
196 | { | 196 | { |
197 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 197 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
198 | struct wm8994_pdata *pdata = wm8994->pdata; | 198 | struct wm8994 *control = wm8994->wm8994; |
199 | int i; | 199 | int i; |
200 | 200 | ||
201 | /* If the DSP is already running then noop */ | 201 | /* If the DSP is already running then noop */ |
@@ -210,9 +210,9 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) | |||
210 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | 210 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); |
211 | 211 | ||
212 | /* If we've got user supplied MBC settings use them */ | 212 | /* If we've got user supplied MBC settings use them */ |
213 | if (pdata && pdata->num_mbc_cfgs) { | 213 | if (control->pdata.num_mbc_cfgs) { |
214 | struct wm8958_mbc_cfg *cfg | 214 | struct wm8958_mbc_cfg *cfg |
215 | = &pdata->mbc_cfgs[wm8994->mbc_cfg]; | 215 | = &control->pdata.mbc_cfgs[wm8994->mbc_cfg]; |
216 | 216 | ||
217 | for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) | 217 | for (i = 0; i < ARRAY_SIZE(cfg->coeff_regs); i++) |
218 | snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1, | 218 | snd_soc_write(codec, i + WM8958_MBC_BAND_1_K_1, |
@@ -239,7 +239,7 @@ static void wm8958_dsp_start_mbc(struct snd_soc_codec *codec, int path) | |||
239 | static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) | 239 | static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) |
240 | { | 240 | { |
241 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 241 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
242 | struct wm8994_pdata *pdata = wm8994->pdata; | 242 | struct wm8994 *control = wm8994->wm8994; |
243 | int i, ena; | 243 | int i, ena; |
244 | 244 | ||
245 | if (wm8994->mbc_vss) | 245 | if (wm8994->mbc_vss) |
@@ -249,26 +249,26 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) | |||
249 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | 249 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); |
250 | 250 | ||
251 | /* If we've got user supplied settings use them */ | 251 | /* If we've got user supplied settings use them */ |
252 | if (pdata && pdata->num_mbc_cfgs) { | 252 | if (control->pdata.num_mbc_cfgs) { |
253 | struct wm8958_mbc_cfg *cfg | 253 | struct wm8958_mbc_cfg *cfg |
254 | = &pdata->mbc_cfgs[wm8994->mbc_cfg]; | 254 | = &control->pdata.mbc_cfgs[wm8994->mbc_cfg]; |
255 | 255 | ||
256 | for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++) | 256 | for (i = 0; i < ARRAY_SIZE(cfg->combined_regs); i++) |
257 | snd_soc_write(codec, i + 0x2800, | 257 | snd_soc_write(codec, i + 0x2800, |
258 | cfg->combined_regs[i]); | 258 | cfg->combined_regs[i]); |
259 | } | 259 | } |
260 | 260 | ||
261 | if (pdata && pdata->num_vss_cfgs) { | 261 | if (control->pdata.num_vss_cfgs) { |
262 | struct wm8958_vss_cfg *cfg | 262 | struct wm8958_vss_cfg *cfg |
263 | = &pdata->vss_cfgs[wm8994->vss_cfg]; | 263 | = &control->pdata.vss_cfgs[wm8994->vss_cfg]; |
264 | 264 | ||
265 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | 265 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) |
266 | snd_soc_write(codec, i + 0x2600, cfg->regs[i]); | 266 | snd_soc_write(codec, i + 0x2600, cfg->regs[i]); |
267 | } | 267 | } |
268 | 268 | ||
269 | if (pdata && pdata->num_vss_hpf_cfgs) { | 269 | if (control->pdata.num_vss_hpf_cfgs) { |
270 | struct wm8958_vss_hpf_cfg *cfg | 270 | struct wm8958_vss_hpf_cfg *cfg |
271 | = &pdata->vss_hpf_cfgs[wm8994->vss_hpf_cfg]; | 271 | = &control->pdata.vss_hpf_cfgs[wm8994->vss_hpf_cfg]; |
272 | 272 | ||
273 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | 273 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) |
274 | snd_soc_write(codec, i + 0x2400, cfg->regs[i]); | 274 | snd_soc_write(codec, i + 0x2400, cfg->regs[i]); |
@@ -300,7 +300,7 @@ static void wm8958_dsp_start_vss(struct snd_soc_codec *codec, int path) | |||
300 | static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path) | 300 | static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path) |
301 | { | 301 | { |
302 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 302 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
303 | struct wm8994_pdata *pdata = wm8994->pdata; | 303 | struct wm8994 *control = wm8994->wm8994; |
304 | int i; | 304 | int i; |
305 | 305 | ||
306 | wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false); | 306 | wm8958_dsp2_fw(codec, "ENH_EQ", wm8994->enh_eq, false); |
@@ -309,9 +309,9 @@ static void wm8958_dsp_start_enh_eq(struct snd_soc_codec *codec, int path) | |||
309 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); | 309 | WM8958_DSP2_ENA, WM8958_DSP2_ENA); |
310 | 310 | ||
311 | /* If we've got user supplied settings use them */ | 311 | /* If we've got user supplied settings use them */ |
312 | if (pdata && pdata->num_enh_eq_cfgs) { | 312 | if (control->pdata.num_enh_eq_cfgs) { |
313 | struct wm8958_enh_eq_cfg *cfg | 313 | struct wm8958_enh_eq_cfg *cfg |
314 | = &pdata->enh_eq_cfgs[wm8994->enh_eq_cfg]; | 314 | = &control->pdata.enh_eq_cfgs[wm8994->enh_eq_cfg]; |
315 | 315 | ||
316 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) | 316 | for (i = 0; i < ARRAY_SIZE(cfg->regs); i++) |
317 | snd_soc_write(codec, i + 0x2200, | 317 | snd_soc_write(codec, i + 0x2200, |
@@ -458,7 +458,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, | |||
458 | { | 458 | { |
459 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 459 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
460 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 460 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
461 | struct wm8994_pdata *pdata = wm8994->pdata; | 461 | struct wm8994 *control = wm8994->wm8994; |
462 | int value = ucontrol->value.integer.value[0]; | 462 | int value = ucontrol->value.integer.value[0]; |
463 | int reg; | 463 | int reg; |
464 | 464 | ||
@@ -467,7 +467,7 @@ static int wm8958_put_mbc_enum(struct snd_kcontrol *kcontrol, | |||
467 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | 467 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) |
468 | return -EBUSY; | 468 | return -EBUSY; |
469 | 469 | ||
470 | if (value >= pdata->num_mbc_cfgs) | 470 | if (value >= control->pdata.num_mbc_cfgs) |
471 | return -EINVAL; | 471 | return -EINVAL; |
472 | 472 | ||
473 | wm8994->mbc_cfg = value; | 473 | wm8994->mbc_cfg = value; |
@@ -548,7 +548,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, | |||
548 | { | 548 | { |
549 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 549 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
550 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 550 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
551 | struct wm8994_pdata *pdata = wm8994->pdata; | 551 | struct wm8994 *control = wm8994->wm8994; |
552 | int value = ucontrol->value.integer.value[0]; | 552 | int value = ucontrol->value.integer.value[0]; |
553 | int reg; | 553 | int reg; |
554 | 554 | ||
@@ -557,7 +557,7 @@ static int wm8958_put_vss_enum(struct snd_kcontrol *kcontrol, | |||
557 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | 557 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) |
558 | return -EBUSY; | 558 | return -EBUSY; |
559 | 559 | ||
560 | if (value >= pdata->num_vss_cfgs) | 560 | if (value >= control->pdata.num_vss_cfgs) |
561 | return -EINVAL; | 561 | return -EINVAL; |
562 | 562 | ||
563 | wm8994->vss_cfg = value; | 563 | wm8994->vss_cfg = value; |
@@ -581,7 +581,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, | |||
581 | { | 581 | { |
582 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 582 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
583 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 583 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
584 | struct wm8994_pdata *pdata = wm8994->pdata; | 584 | struct wm8994 *control = wm8994->wm8994; |
585 | int value = ucontrol->value.integer.value[0]; | 585 | int value = ucontrol->value.integer.value[0]; |
586 | int reg; | 586 | int reg; |
587 | 587 | ||
@@ -590,7 +590,7 @@ static int wm8958_put_vss_hpf_enum(struct snd_kcontrol *kcontrol, | |||
590 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | 590 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) |
591 | return -EBUSY; | 591 | return -EBUSY; |
592 | 592 | ||
593 | if (value >= pdata->num_vss_hpf_cfgs) | 593 | if (value >= control->pdata.num_vss_hpf_cfgs) |
594 | return -EINVAL; | 594 | return -EINVAL; |
595 | 595 | ||
596 | wm8994->vss_hpf_cfg = value; | 596 | wm8994->vss_hpf_cfg = value; |
@@ -748,7 +748,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, | |||
748 | { | 748 | { |
749 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 749 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
750 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 750 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
751 | struct wm8994_pdata *pdata = wm8994->pdata; | 751 | struct wm8994 *control = wm8994->wm8994; |
752 | int value = ucontrol->value.integer.value[0]; | 752 | int value = ucontrol->value.integer.value[0]; |
753 | int reg; | 753 | int reg; |
754 | 754 | ||
@@ -757,7 +757,7 @@ static int wm8958_put_enh_eq_enum(struct snd_kcontrol *kcontrol, | |||
757 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) | 757 | if (reg < 0 || reg & WM8958_DSP2CLK_ENA) |
758 | return -EBUSY; | 758 | return -EBUSY; |
759 | 759 | ||
760 | if (value >= pdata->num_enh_eq_cfgs) | 760 | if (value >= control->pdata.num_enh_eq_cfgs) |
761 | return -EINVAL; | 761 | return -EINVAL; |
762 | 762 | ||
763 | wm8994->enh_eq_cfg = value; | 763 | wm8994->enh_eq_cfg = value; |
@@ -883,13 +883,6 @@ static void wm8958_mbc_vss_loaded(const struct firmware *fw, void *context) | |||
883 | wm8994->mbc_vss = fw; | 883 | wm8994->mbc_vss = fw; |
884 | mutex_unlock(&codec->mutex); | 884 | mutex_unlock(&codec->mutex); |
885 | } | 885 | } |
886 | |||
887 | /* We can't have more than one request outstanding at once so | ||
888 | * we daisy chain. | ||
889 | */ | ||
890 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
891 | "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL, | ||
892 | codec, wm8958_enh_eq_loaded); | ||
893 | } | 886 | } |
894 | 887 | ||
895 | static void wm8958_mbc_loaded(const struct firmware *fw, void *context) | 888 | static void wm8958_mbc_loaded(const struct firmware *fw, void *context) |
@@ -897,25 +890,18 @@ static void wm8958_mbc_loaded(const struct firmware *fw, void *context) | |||
897 | struct snd_soc_codec *codec = context; | 890 | struct snd_soc_codec *codec = context; |
898 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 891 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
899 | 892 | ||
900 | if (wm8958_dsp2_fw(codec, "MBC", fw, true) != 0) | 893 | if (fw && (wm8958_dsp2_fw(codec, "MBC", fw, true) == 0)) { |
901 | return; | 894 | mutex_lock(&codec->mutex); |
902 | 895 | wm8994->mbc = fw; | |
903 | mutex_lock(&codec->mutex); | 896 | mutex_unlock(&codec->mutex); |
904 | wm8994->mbc = fw; | 897 | } |
905 | mutex_unlock(&codec->mutex); | ||
906 | |||
907 | /* We can't have more than one request outstanding at once so | ||
908 | * we daisy chain. | ||
909 | */ | ||
910 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
911 | "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL, | ||
912 | codec, wm8958_mbc_vss_loaded); | ||
913 | } | 898 | } |
914 | 899 | ||
915 | void wm8958_dsp2_init(struct snd_soc_codec *codec) | 900 | void wm8958_dsp2_init(struct snd_soc_codec *codec) |
916 | { | 901 | { |
917 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 902 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
918 | struct wm8994_pdata *pdata = wm8994->pdata; | 903 | struct wm8994 *control = wm8994->wm8994; |
904 | struct wm8994_pdata *pdata = &control->pdata; | ||
919 | int ret, i; | 905 | int ret, i; |
920 | 906 | ||
921 | wm8994->dsp_active = -1; | 907 | wm8994->dsp_active = -1; |
@@ -932,9 +918,12 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
932 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | 918 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, |
933 | "wm8958_mbc.wfw", codec->dev, GFP_KERNEL, | 919 | "wm8958_mbc.wfw", codec->dev, GFP_KERNEL, |
934 | codec, wm8958_mbc_loaded); | 920 | codec, wm8958_mbc_loaded); |
935 | 921 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | |
936 | if (!pdata) | 922 | "wm8958_mbc_vss.wfw", codec->dev, GFP_KERNEL, |
937 | return; | 923 | codec, wm8958_mbc_vss_loaded); |
924 | request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, | ||
925 | "wm8958_enh_eq.wfw", codec->dev, GFP_KERNEL, | ||
926 | codec, wm8958_enh_eq_loaded); | ||
938 | 927 | ||
939 | if (pdata->num_mbc_cfgs) { | 928 | if (pdata->num_mbc_cfgs) { |
940 | struct snd_kcontrol_new control[] = { | 929 | struct snd_kcontrol_new control[] = { |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index f0f6f6601785..cf09cb625a7b 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -1040,7 +1040,7 @@ static __devinit int wm8960_i2c_probe(struct i2c_client *i2c, | |||
1040 | if (wm8960 == NULL) | 1040 | if (wm8960 == NULL) |
1041 | return -ENOMEM; | 1041 | return -ENOMEM; |
1042 | 1042 | ||
1043 | wm8960->regmap = regmap_init_i2c(i2c, &wm8960_regmap); | 1043 | wm8960->regmap = devm_regmap_init_i2c(i2c, &wm8960_regmap); |
1044 | if (IS_ERR(wm8960->regmap)) | 1044 | if (IS_ERR(wm8960->regmap)) |
1045 | return PTR_ERR(wm8960->regmap); | 1045 | return PTR_ERR(wm8960->regmap); |
1046 | 1046 | ||
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index ce6720073798..8fd38cb4ba48 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -3610,7 +3610,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3610 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) | 3610 | for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) |
3611 | wm8962->supplies[i].supply = wm8962_supply_names[i]; | 3611 | wm8962->supplies[i].supply = wm8962_supply_names[i]; |
3612 | 3612 | ||
3613 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies), | 3613 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies), |
3614 | wm8962->supplies); | 3614 | wm8962->supplies); |
3615 | if (ret != 0) { | 3615 | if (ret != 0) { |
3616 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | 3616 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
@@ -3621,10 +3621,10 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3621 | wm8962->supplies); | 3621 | wm8962->supplies); |
3622 | if (ret != 0) { | 3622 | if (ret != 0) { |
3623 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | 3623 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
3624 | goto err_get; | 3624 | return ret; |
3625 | } | 3625 | } |
3626 | 3626 | ||
3627 | wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap); | 3627 | wm8962->regmap = devm_regmap_init_i2c(i2c, &wm8962_regmap); |
3628 | if (IS_ERR(wm8962->regmap)) { | 3628 | if (IS_ERR(wm8962->regmap)) { |
3629 | ret = PTR_ERR(wm8962->regmap); | 3629 | ret = PTR_ERR(wm8962->regmap); |
3630 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | 3630 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); |
@@ -3641,20 +3641,20 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3641 | ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, ®); | 3641 | ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, ®); |
3642 | if (ret < 0) { | 3642 | if (ret < 0) { |
3643 | dev_err(&i2c->dev, "Failed to read ID register\n"); | 3643 | dev_err(&i2c->dev, "Failed to read ID register\n"); |
3644 | goto err_regmap; | 3644 | goto err_enable; |
3645 | } | 3645 | } |
3646 | if (reg != 0x6243) { | 3646 | if (reg != 0x6243) { |
3647 | dev_err(&i2c->dev, | 3647 | dev_err(&i2c->dev, |
3648 | "Device is not a WM8962, ID %x != 0x6243\n", reg); | 3648 | "Device is not a WM8962, ID %x != 0x6243\n", reg); |
3649 | ret = -EINVAL; | 3649 | ret = -EINVAL; |
3650 | goto err_regmap; | 3650 | goto err_enable; |
3651 | } | 3651 | } |
3652 | 3652 | ||
3653 | ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, ®); | 3653 | ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, ®); |
3654 | if (ret < 0) { | 3654 | if (ret < 0) { |
3655 | dev_err(&i2c->dev, "Failed to read device revision: %d\n", | 3655 | dev_err(&i2c->dev, "Failed to read device revision: %d\n", |
3656 | ret); | 3656 | ret); |
3657 | goto err_regmap; | 3657 | goto err_enable; |
3658 | } | 3658 | } |
3659 | 3659 | ||
3660 | dev_info(&i2c->dev, "customer id %x revision %c\n", | 3660 | dev_info(&i2c->dev, "customer id %x revision %c\n", |
@@ -3667,7 +3667,7 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3667 | ret = wm8962_reset(wm8962); | 3667 | ret = wm8962_reset(wm8962); |
3668 | if (ret < 0) { | 3668 | if (ret < 0) { |
3669 | dev_err(&i2c->dev, "Failed to issue reset\n"); | 3669 | dev_err(&i2c->dev, "Failed to issue reset\n"); |
3670 | goto err_regmap; | 3670 | goto err_enable; |
3671 | } | 3671 | } |
3672 | 3672 | ||
3673 | if (pdata && pdata->in4_dc_measure) { | 3673 | if (pdata && pdata->in4_dc_measure) { |
@@ -3686,30 +3686,22 @@ static __devinit int wm8962_i2c_probe(struct i2c_client *i2c, | |||
3686 | ret = snd_soc_register_codec(&i2c->dev, | 3686 | ret = snd_soc_register_codec(&i2c->dev, |
3687 | &soc_codec_dev_wm8962, &wm8962_dai, 1); | 3687 | &soc_codec_dev_wm8962, &wm8962_dai, 1); |
3688 | if (ret < 0) | 3688 | if (ret < 0) |
3689 | goto err_regmap; | 3689 | goto err_enable; |
3690 | 3690 | ||
3691 | /* The drivers should power up as needed */ | 3691 | /* The drivers should power up as needed */ |
3692 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | 3692 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); |
3693 | 3693 | ||
3694 | return 0; | 3694 | return 0; |
3695 | 3695 | ||
3696 | err_regmap: | ||
3697 | regmap_exit(wm8962->regmap); | ||
3698 | err_enable: | 3696 | err_enable: |
3699 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | 3697 | regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); |
3700 | err_get: | ||
3701 | regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | ||
3702 | err: | 3698 | err: |
3703 | return ret; | 3699 | return ret; |
3704 | } | 3700 | } |
3705 | 3701 | ||
3706 | static __devexit int wm8962_i2c_remove(struct i2c_client *client) | 3702 | static __devexit int wm8962_i2c_remove(struct i2c_client *client) |
3707 | { | 3703 | { |
3708 | struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev); | ||
3709 | |||
3710 | snd_soc_unregister_codec(&client->dev); | 3704 | snd_soc_unregister_codec(&client->dev); |
3711 | regmap_exit(wm8962->regmap); | ||
3712 | regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies); | ||
3713 | return 0; | 3705 | return 0; |
3714 | } | 3706 | } |
3715 | 3707 | ||
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index 5ce647758443..70dd27e94514 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/delay.h> | 19 | #include <linux/delay.h> |
20 | #include <linux/pm.h> | 20 | #include <linux/pm.h> |
21 | #include <linux/i2c.h> | 21 | #include <linux/i2c.h> |
22 | #include <linux/regmap.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
@@ -34,7 +35,6 @@ static struct workqueue_struct *wm8971_workq = NULL; | |||
34 | 35 | ||
35 | /* codec private data */ | 36 | /* codec private data */ |
36 | struct wm8971_priv { | 37 | struct wm8971_priv { |
37 | enum snd_soc_control_type control_type; | ||
38 | unsigned int sysclk; | 38 | unsigned int sysclk; |
39 | }; | 39 | }; |
40 | 40 | ||
@@ -43,18 +43,50 @@ struct wm8971_priv { | |||
43 | * We can't read the WM8971 register space when we | 43 | * We can't read the WM8971 register space when we |
44 | * are using 2 wire for device control, so we cache them instead. | 44 | * are using 2 wire for device control, so we cache them instead. |
45 | */ | 45 | */ |
46 | static const u16 wm8971_reg[] = { | 46 | static const struct reg_default wm8971_reg_defaults[] = { |
47 | 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ | 47 | { 0, 0x0097 }, |
48 | 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ | 48 | { 1, 0x0097 }, |
49 | 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ | 49 | { 2, 0x0079 }, |
50 | 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ | 50 | { 3, 0x0079 }, |
51 | 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ | 51 | { 4, 0x0000 }, |
52 | 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ | 52 | { 5, 0x0008 }, |
53 | 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ | 53 | { 6, 0x0000 }, |
54 | 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ | 54 | { 7, 0x000a }, |
55 | 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ | 55 | { 8, 0x0000 }, |
56 | 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ | 56 | { 9, 0x0000 }, |
57 | 0x0079, 0x0079, 0x0079, /* 40 */ | 57 | { 10, 0x00ff }, |
58 | { 11, 0x00ff }, | ||
59 | { 12, 0x000f }, | ||
60 | { 13, 0x000f }, | ||
61 | { 14, 0x0000 }, | ||
62 | { 15, 0x0000 }, | ||
63 | { 16, 0x0000 }, | ||
64 | { 17, 0x007b }, | ||
65 | { 18, 0x0000 }, | ||
66 | { 19, 0x0032 }, | ||
67 | { 20, 0x0000 }, | ||
68 | { 21, 0x00c3 }, | ||
69 | { 22, 0x00c3 }, | ||
70 | { 23, 0x00c0 }, | ||
71 | { 24, 0x0000 }, | ||
72 | { 25, 0x0000 }, | ||
73 | { 26, 0x0000 }, | ||
74 | { 27, 0x0000 }, | ||
75 | { 28, 0x0000 }, | ||
76 | { 29, 0x0000 }, | ||
77 | { 30, 0x0000 }, | ||
78 | { 31, 0x0000 }, | ||
79 | { 32, 0x0000 }, | ||
80 | { 33, 0x0000 }, | ||
81 | { 34, 0x0050 }, | ||
82 | { 35, 0x0050 }, | ||
83 | { 36, 0x0050 }, | ||
84 | { 37, 0x0050 }, | ||
85 | { 38, 0x0050 }, | ||
86 | { 39, 0x0050 }, | ||
87 | { 40, 0x0079 }, | ||
88 | { 41, 0x0079 }, | ||
89 | { 42, 0x0079 }, | ||
58 | }; | 90 | }; |
59 | 91 | ||
60 | #define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0) | 92 | #define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0) |
@@ -613,11 +645,10 @@ static int wm8971_resume(struct snd_soc_codec *codec) | |||
613 | 645 | ||
614 | static int wm8971_probe(struct snd_soc_codec *codec) | 646 | static int wm8971_probe(struct snd_soc_codec *codec) |
615 | { | 647 | { |
616 | struct wm8971_priv *wm8971 = snd_soc_codec_get_drvdata(codec); | ||
617 | int ret = 0; | 648 | int ret = 0; |
618 | u16 reg; | 649 | u16 reg; |
619 | 650 | ||
620 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8971->control_type); | 651 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP); |
621 | if (ret < 0) { | 652 | if (ret < 0) { |
622 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); | 653 | printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret); |
623 | return ret; | 654 | return ret; |
@@ -667,9 +698,6 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { | |||
667 | .suspend = wm8971_suspend, | 698 | .suspend = wm8971_suspend, |
668 | .resume = wm8971_resume, | 699 | .resume = wm8971_resume, |
669 | .set_bias_level = wm8971_set_bias_level, | 700 | .set_bias_level = wm8971_set_bias_level, |
670 | .reg_cache_size = ARRAY_SIZE(wm8971_reg), | ||
671 | .reg_word_size = sizeof(u16), | ||
672 | .reg_cache_default = wm8971_reg, | ||
673 | 701 | ||
674 | .controls = wm8971_snd_controls, | 702 | .controls = wm8971_snd_controls, |
675 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), | 703 | .num_controls = ARRAY_SIZE(wm8971_snd_controls), |
@@ -679,10 +707,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = { | |||
679 | .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), | 707 | .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes), |
680 | }; | 708 | }; |
681 | 709 | ||
710 | static const struct regmap_config wm8971_regmap = { | ||
711 | .reg_bits = 7, | ||
712 | .val_bits = 9, | ||
713 | .max_register = WM8971_MOUTV, | ||
714 | |||
715 | .reg_defaults = wm8971_reg_defaults, | ||
716 | .num_reg_defaults = ARRAY_SIZE(wm8971_reg_defaults), | ||
717 | .cache_type = REGCACHE_RBTREE, | ||
718 | }; | ||
719 | |||
682 | static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, | 720 | static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, |
683 | const struct i2c_device_id *id) | 721 | const struct i2c_device_id *id) |
684 | { | 722 | { |
685 | struct wm8971_priv *wm8971; | 723 | struct wm8971_priv *wm8971; |
724 | struct regmap *regmap; | ||
686 | int ret; | 725 | int ret; |
687 | 726 | ||
688 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), | 727 | wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv), |
@@ -690,7 +729,10 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c, | |||
690 | if (wm8971 == NULL) | 729 | if (wm8971 == NULL) |
691 | return -ENOMEM; | 730 | return -ENOMEM; |
692 | 731 | ||
693 | wm8971->control_type = SND_SOC_I2C; | 732 | regmap = devm_regmap_init_i2c(i2c, &wm8971_regmap); |
733 | if (IS_ERR(regmap)) | ||
734 | return PTR_ERR(regmap); | ||
735 | |||
694 | i2c_set_clientdata(i2c, wm8971); | 736 | i2c_set_clientdata(i2c, wm8971); |
695 | 737 | ||
696 | ret = snd_soc_register_codec(&i2c->dev, | 738 | ret = snd_soc_register_codec(&i2c->dev, |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 4c0a8e496131..ef467001c3d5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -527,9 +527,6 @@ static int wm8978_configure_pll(struct snd_soc_codec *codec) | |||
527 | return idx; | 527 | return idx; |
528 | 528 | ||
529 | wm8978->mclk_idx = idx; | 529 | wm8978->mclk_idx = idx; |
530 | |||
531 | /* GPIO1 into default mode as input - before configuring PLL */ | ||
532 | snd_soc_update_bits(codec, WM8978_GPIO_CONTROL, 7, 0); | ||
533 | } else { | 530 | } else { |
534 | return -EINVAL; | 531 | return -EINVAL; |
535 | } | 532 | } |
@@ -1049,7 +1046,7 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, | |||
1049 | if (wm8978 == NULL) | 1046 | if (wm8978 == NULL) |
1050 | return -ENOMEM; | 1047 | return -ENOMEM; |
1051 | 1048 | ||
1052 | wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config); | 1049 | wm8978->regmap = devm_regmap_init_i2c(i2c, &wm8978_regmap_config); |
1053 | if (IS_ERR(wm8978->regmap)) { | 1050 | if (IS_ERR(wm8978->regmap)) { |
1054 | ret = PTR_ERR(wm8978->regmap); | 1051 | ret = PTR_ERR(wm8978->regmap); |
1055 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | 1052 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); |
@@ -1062,29 +1059,22 @@ static __devinit int wm8978_i2c_probe(struct i2c_client *i2c, | |||
1062 | ret = regmap_write(wm8978->regmap, WM8978_RESET, 0); | 1059 | ret = regmap_write(wm8978->regmap, WM8978_RESET, 0); |
1063 | if (ret != 0) { | 1060 | if (ret != 0) { |
1064 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); | 1061 | dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret); |
1065 | goto err; | 1062 | return ret; |
1066 | } | 1063 | } |
1067 | 1064 | ||
1068 | ret = snd_soc_register_codec(&i2c->dev, | 1065 | ret = snd_soc_register_codec(&i2c->dev, |
1069 | &soc_codec_dev_wm8978, &wm8978_dai, 1); | 1066 | &soc_codec_dev_wm8978, &wm8978_dai, 1); |
1070 | if (ret != 0) { | 1067 | if (ret != 0) { |
1071 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | 1068 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); |
1072 | goto err; | 1069 | return ret; |
1073 | } | 1070 | } |
1074 | 1071 | ||
1075 | return 0; | 1072 | return 0; |
1076 | |||
1077 | err: | ||
1078 | regmap_exit(wm8978->regmap); | ||
1079 | return ret; | ||
1080 | } | 1073 | } |
1081 | 1074 | ||
1082 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) | 1075 | static __devexit int wm8978_i2c_remove(struct i2c_client *client) |
1083 | { | 1076 | { |
1084 | struct wm8978_priv *wm8978 = i2c_get_clientdata(client); | ||
1085 | |||
1086 | snd_soc_unregister_codec(&client->dev); | 1077 | snd_soc_unregister_codec(&client->dev); |
1087 | regmap_exit(wm8978->regmap); | ||
1088 | 1078 | ||
1089 | return 0; | 1079 | return 0; |
1090 | } | 1080 | } |
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c index 14f666398d0c..7b3f4097609b 100644 --- a/sound/soc/codecs/wm8985.c +++ b/sound/soc/codecs/wm8985.c | |||
@@ -1122,33 +1122,22 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi) | |||
1122 | 1122 | ||
1123 | spi_set_drvdata(spi, wm8985); | 1123 | spi_set_drvdata(spi, wm8985); |
1124 | 1124 | ||
1125 | wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap); | 1125 | wm8985->regmap = devm_regmap_init_spi(spi, &wm8985_regmap); |
1126 | if (IS_ERR(wm8985->regmap)) { | 1126 | if (IS_ERR(wm8985->regmap)) { |
1127 | ret = PTR_ERR(wm8985->regmap); | 1127 | ret = PTR_ERR(wm8985->regmap); |
1128 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", | 1128 | dev_err(&spi->dev, "Failed to allocate register map: %d\n", |
1129 | ret); | 1129 | ret); |
1130 | goto err; | 1130 | return ret; |
1131 | } | 1131 | } |
1132 | 1132 | ||
1133 | ret = snd_soc_register_codec(&spi->dev, | 1133 | ret = snd_soc_register_codec(&spi->dev, |
1134 | &soc_codec_dev_wm8985, &wm8985_dai, 1); | 1134 | &soc_codec_dev_wm8985, &wm8985_dai, 1); |
1135 | if (ret != 0) | ||
1136 | goto err; | ||
1137 | |||
1138 | return 0; | ||
1139 | |||
1140 | err: | ||
1141 | regmap_exit(wm8985->regmap); | ||
1142 | return ret; | 1135 | return ret; |
1143 | } | 1136 | } |
1144 | 1137 | ||
1145 | static int __devexit wm8985_spi_remove(struct spi_device *spi) | 1138 | static int __devexit wm8985_spi_remove(struct spi_device *spi) |
1146 | { | 1139 | { |
1147 | struct wm8985_priv *wm8985 = spi_get_drvdata(spi); | ||
1148 | |||
1149 | snd_soc_unregister_codec(&spi->dev); | 1140 | snd_soc_unregister_codec(&spi->dev); |
1150 | regmap_exit(wm8985->regmap); | ||
1151 | |||
1152 | return 0; | 1141 | return 0; |
1153 | } | 1142 | } |
1154 | 1143 | ||
@@ -1175,33 +1164,22 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c, | |||
1175 | 1164 | ||
1176 | i2c_set_clientdata(i2c, wm8985); | 1165 | i2c_set_clientdata(i2c, wm8985); |
1177 | 1166 | ||
1178 | wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap); | 1167 | wm8985->regmap = devm_regmap_init_i2c(i2c, &wm8985_regmap); |
1179 | if (IS_ERR(wm8985->regmap)) { | 1168 | if (IS_ERR(wm8985->regmap)) { |
1180 | ret = PTR_ERR(wm8985->regmap); | 1169 | ret = PTR_ERR(wm8985->regmap); |
1181 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", | 1170 | dev_err(&i2c->dev, "Failed to allocate register map: %d\n", |
1182 | ret); | 1171 | ret); |
1183 | goto err; | 1172 | return ret; |
1184 | } | 1173 | } |
1185 | 1174 | ||
1186 | ret = snd_soc_register_codec(&i2c->dev, | 1175 | ret = snd_soc_register_codec(&i2c->dev, |
1187 | &soc_codec_dev_wm8985, &wm8985_dai, 1); | 1176 | &soc_codec_dev_wm8985, &wm8985_dai, 1); |
1188 | if (ret != 0) | ||
1189 | goto err; | ||
1190 | |||
1191 | return 0; | ||
1192 | |||
1193 | err: | ||
1194 | regmap_exit(wm8985->regmap); | ||
1195 | return ret; | 1177 | return ret; |
1196 | } | 1178 | } |
1197 | 1179 | ||
1198 | static __devexit int wm8985_i2c_remove(struct i2c_client *i2c) | 1180 | static __devexit int wm8985_i2c_remove(struct i2c_client *i2c) |
1199 | { | 1181 | { |
1200 | struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c); | ||
1201 | |||
1202 | snd_soc_unregister_codec(&i2c->dev); | 1182 | snd_soc_unregister_codec(&i2c->dev); |
1203 | regmap_exit(wm8985->regmap); | ||
1204 | |||
1205 | return 0; | 1183 | return 0; |
1206 | } | 1184 | } |
1207 | 1185 | ||
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c index 1d4c5cf47b06..715788de442e 100644 --- a/sound/soc/codecs/wm8988.c +++ b/sound/soc/codecs/wm8988.c | |||
@@ -882,7 +882,7 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi) | |||
882 | if (wm8988 == NULL) | 882 | if (wm8988 == NULL) |
883 | return -ENOMEM; | 883 | return -ENOMEM; |
884 | 884 | ||
885 | wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap); | 885 | wm8988->regmap = devm_regmap_init_spi(spi, &wm8988_regmap); |
886 | if (IS_ERR(wm8988->regmap)) { | 886 | if (IS_ERR(wm8988->regmap)) { |
887 | ret = PTR_ERR(wm8988->regmap); | 887 | ret = PTR_ERR(wm8988->regmap); |
888 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); | 888 | dev_err(&spi->dev, "Failed to init regmap: %d\n", ret); |
@@ -893,17 +893,12 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi) | |||
893 | 893 | ||
894 | ret = snd_soc_register_codec(&spi->dev, | 894 | ret = snd_soc_register_codec(&spi->dev, |
895 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | 895 | &soc_codec_dev_wm8988, &wm8988_dai, 1); |
896 | if (ret != 0) | ||
897 | regmap_exit(wm8988->regmap); | ||
898 | |||
899 | return ret; | 896 | return ret; |
900 | } | 897 | } |
901 | 898 | ||
902 | static int __devexit wm8988_spi_remove(struct spi_device *spi) | 899 | static int __devexit wm8988_spi_remove(struct spi_device *spi) |
903 | { | 900 | { |
904 | struct wm8988_priv *wm8988 = spi_get_drvdata(spi); | ||
905 | snd_soc_unregister_codec(&spi->dev); | 901 | snd_soc_unregister_codec(&spi->dev); |
906 | regmap_exit(wm8988->regmap); | ||
907 | return 0; | 902 | return 0; |
908 | } | 903 | } |
909 | 904 | ||
@@ -931,7 +926,7 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, | |||
931 | 926 | ||
932 | i2c_set_clientdata(i2c, wm8988); | 927 | i2c_set_clientdata(i2c, wm8988); |
933 | 928 | ||
934 | wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap); | 929 | wm8988->regmap = devm_regmap_init_i2c(i2c, &wm8988_regmap); |
935 | if (IS_ERR(wm8988->regmap)) { | 930 | if (IS_ERR(wm8988->regmap)) { |
936 | ret = PTR_ERR(wm8988->regmap); | 931 | ret = PTR_ERR(wm8988->regmap); |
937 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); | 932 | dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret); |
@@ -940,17 +935,12 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c, | |||
940 | 935 | ||
941 | ret = snd_soc_register_codec(&i2c->dev, | 936 | ret = snd_soc_register_codec(&i2c->dev, |
942 | &soc_codec_dev_wm8988, &wm8988_dai, 1); | 937 | &soc_codec_dev_wm8988, &wm8988_dai, 1); |
943 | if (ret != 0) | ||
944 | regmap_exit(wm8988->regmap); | ||
945 | |||
946 | return ret; | 938 | return ret; |
947 | } | 939 | } |
948 | 940 | ||
949 | static __devexit int wm8988_i2c_remove(struct i2c_client *client) | 941 | static __devexit int wm8988_i2c_remove(struct i2c_client *client) |
950 | { | 942 | { |
951 | struct wm8988_priv *wm8988 = i2c_get_clientdata(client); | ||
952 | snd_soc_unregister_codec(&client->dev); | 943 | snd_soc_unregister_codec(&client->dev); |
953 | regmap_exit(wm8988->regmap); | ||
954 | return 0; | 944 | return 0; |
955 | } | 945 | } |
956 | 946 | ||
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 94737a30716b..347a359a7c86 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1660,7 +1660,7 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1660 | wm8993->dev = &i2c->dev; | 1660 | wm8993->dev = &i2c->dev; |
1661 | init_completion(&wm8993->fll_lock); | 1661 | init_completion(&wm8993->fll_lock); |
1662 | 1662 | ||
1663 | wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap); | 1663 | wm8993->regmap = devm_regmap_init_i2c(i2c, &wm8993_regmap); |
1664 | if (IS_ERR(wm8993->regmap)) { | 1664 | if (IS_ERR(wm8993->regmap)) { |
1665 | ret = PTR_ERR(wm8993->regmap); | 1665 | ret = PTR_ERR(wm8993->regmap); |
1666 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); | 1666 | dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); |
@@ -1672,18 +1672,18 @@ static __devinit int wm8993_i2c_probe(struct i2c_client *i2c, | |||
1672 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) | 1672 | for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++) |
1673 | wm8993->supplies[i].supply = wm8993_supply_names[i]; | 1673 | wm8993->supplies[i].supply = wm8993_supply_names[i]; |
1674 | 1674 | ||
1675 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies), | 1675 | ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies), |
1676 | wm8993->supplies); | 1676 | wm8993->supplies); |
1677 | if (ret != 0) { | 1677 | if (ret != 0) { |
1678 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | 1678 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); |
1679 | goto err; | 1679 | return ret; |
1680 | } | 1680 | } |
1681 | 1681 | ||
1682 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), | 1682 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies), |
1683 | wm8993->supplies); | 1683 | wm8993->supplies); |
1684 | if (ret != 0) { | 1684 | if (ret != 0) { |
1685 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | 1685 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); |
1686 | goto err_get; | 1686 | return ret; |
1687 | } | 1687 | } |
1688 | 1688 | ||
1689 | ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, ®); | 1689 | ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, ®); |
@@ -1742,10 +1742,6 @@ err_irq: | |||
1742 | free_irq(i2c->irq, wm8993); | 1742 | free_irq(i2c->irq, wm8993); |
1743 | err_enable: | 1743 | err_enable: |
1744 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | 1744 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); |
1745 | err_get: | ||
1746 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1747 | err: | ||
1748 | regmap_exit(wm8993->regmap); | ||
1749 | return ret; | 1745 | return ret; |
1750 | } | 1746 | } |
1751 | 1747 | ||
@@ -1756,9 +1752,7 @@ static __devexit int wm8993_i2c_remove(struct i2c_client *i2c) | |||
1756 | snd_soc_unregister_codec(&i2c->dev); | 1752 | snd_soc_unregister_codec(&i2c->dev); |
1757 | if (i2c->irq) | 1753 | if (i2c->irq) |
1758 | free_irq(i2c->irq, wm8993); | 1754 | free_irq(i2c->irq, wm8993); |
1759 | regmap_exit(wm8993->regmap); | ||
1760 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | 1755 | regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); |
1761 | regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies); | ||
1762 | 1756 | ||
1763 | return 0; | 1757 | return 0; |
1764 | } | 1758 | } |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b2b2b37131bd..60b34ff8179b 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -91,8 +91,6 @@ static int wm8994_retune_mobile_base[] = { | |||
91 | WM8994_AIF2_EQ_GAINS_1, | 91 | WM8994_AIF2_EQ_GAINS_1, |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static void wm8958_default_micdet(u16 status, void *data); | ||
95 | |||
96 | static const struct wm8958_micd_rate micdet_rates[] = { | 94 | static const struct wm8958_micd_rate micdet_rates[] = { |
97 | { 32768, true, 1, 4 }, | 95 | { 32768, true, 1, 4 }, |
98 | { 32768, false, 1, 1 }, | 96 | { 32768, false, 1, 1 }, |
@@ -110,15 +108,12 @@ static const struct wm8958_micd_rate jackdet_rates[] = { | |||
110 | static void wm8958_micd_set_rate(struct snd_soc_codec *codec) | 108 | static void wm8958_micd_set_rate(struct snd_soc_codec *codec) |
111 | { | 109 | { |
112 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 110 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
111 | struct wm8994 *control = wm8994->wm8994; | ||
113 | int best, i, sysclk, val; | 112 | int best, i, sysclk, val; |
114 | bool idle; | 113 | bool idle; |
115 | const struct wm8958_micd_rate *rates; | 114 | const struct wm8958_micd_rate *rates; |
116 | int num_rates; | 115 | int num_rates; |
117 | 116 | ||
118 | if (!(wm8994->pdata && wm8994->pdata->micd_rates) && | ||
119 | wm8994->jack_cb != wm8958_default_micdet) | ||
120 | return; | ||
121 | |||
122 | idle = !wm8994->jack_mic; | 117 | idle = !wm8994->jack_mic; |
123 | 118 | ||
124 | sysclk = snd_soc_read(codec, WM8994_CLOCKING_1); | 119 | sysclk = snd_soc_read(codec, WM8994_CLOCKING_1); |
@@ -127,9 +122,9 @@ static void wm8958_micd_set_rate(struct snd_soc_codec *codec) | |||
127 | else | 122 | else |
128 | sysclk = wm8994->aifclk[0]; | 123 | sysclk = wm8994->aifclk[0]; |
129 | 124 | ||
130 | if (wm8994->pdata && wm8994->pdata->micd_rates) { | 125 | if (control->pdata.micd_rates) { |
131 | rates = wm8994->pdata->micd_rates; | 126 | rates = control->pdata.micd_rates; |
132 | num_rates = wm8994->pdata->num_micd_rates; | 127 | num_rates = control->pdata.num_micd_rates; |
133 | } else if (wm8994->jackdet) { | 128 | } else if (wm8994->jackdet) { |
134 | rates = jackdet_rates; | 129 | rates = jackdet_rates; |
135 | num_rates = ARRAY_SIZE(jackdet_rates); | 130 | num_rates = ARRAY_SIZE(jackdet_rates); |
@@ -326,7 +321,8 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | |||
326 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) | 321 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) |
327 | { | 322 | { |
328 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 323 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
329 | struct wm8994_pdata *pdata = wm8994->pdata; | 324 | struct wm8994 *control = wm8994->wm8994; |
325 | struct wm8994_pdata *pdata = &control->pdata; | ||
330 | int base = wm8994_drc_base[drc]; | 326 | int base = wm8994_drc_base[drc]; |
331 | int cfg = wm8994->drc_cfg[drc]; | 327 | int cfg = wm8994->drc_cfg[drc]; |
332 | int save, i; | 328 | int save, i; |
@@ -362,7 +358,8 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
362 | { | 358 | { |
363 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 359 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
364 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 360 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
365 | struct wm8994_pdata *pdata = wm8994->pdata; | 361 | struct wm8994 *control = wm8994->wm8994; |
362 | struct wm8994_pdata *pdata = &control->pdata; | ||
366 | int drc = wm8994_get_drc(kcontrol->id.name); | 363 | int drc = wm8994_get_drc(kcontrol->id.name); |
367 | int value = ucontrol->value.integer.value[0]; | 364 | int value = ucontrol->value.integer.value[0]; |
368 | 365 | ||
@@ -394,7 +391,8 @@ static int wm8994_get_drc_enum(struct snd_kcontrol *kcontrol, | |||
394 | static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block) | 391 | static void wm8994_set_retune_mobile(struct snd_soc_codec *codec, int block) |
395 | { | 392 | { |
396 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 393 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
397 | struct wm8994_pdata *pdata = wm8994->pdata; | 394 | struct wm8994 *control = wm8994->wm8994; |
395 | struct wm8994_pdata *pdata = &control->pdata; | ||
398 | int base = wm8994_retune_mobile_base[block]; | 396 | int base = wm8994_retune_mobile_base[block]; |
399 | int iface, best, best_val, save, i, cfg; | 397 | int iface, best, best_val, save, i, cfg; |
400 | 398 | ||
@@ -465,7 +463,8 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
465 | { | 463 | { |
466 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 464 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
467 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 465 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
468 | struct wm8994_pdata *pdata = wm8994->pdata; | 466 | struct wm8994 *control = wm8994->wm8994; |
467 | struct wm8994_pdata *pdata = &control->pdata; | ||
469 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 468 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
470 | int value = ucontrol->value.integer.value[0]; | 469 | int value = ucontrol->value.integer.value[0]; |
471 | 470 | ||
@@ -736,7 +735,7 @@ static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode) | |||
736 | { | 735 | { |
737 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 736 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
738 | 737 | ||
739 | if (!wm8994->jackdet || !wm8994->jack_cb) | 738 | if (!wm8994->jackdet || !wm8994->micdet[0].jack) |
740 | return; | 739 | return; |
741 | 740 | ||
742 | if (wm8994->active_refcount) | 741 | if (wm8994->active_refcount) |
@@ -862,7 +861,7 @@ static void vmid_reference(struct snd_soc_codec *codec) | |||
862 | WM8994_BIAS_SRC | | 861 | WM8994_BIAS_SRC | |
863 | WM8994_STARTUP_BIAS_ENA | | 862 | WM8994_STARTUP_BIAS_ENA | |
864 | WM8994_VMID_BUF_ENA | | 863 | WM8994_VMID_BUF_ENA | |
865 | (0x3 << WM8994_VMID_RAMP_SHIFT)); | 864 | (0x2 << WM8994_VMID_RAMP_SHIFT)); |
866 | 865 | ||
867 | /* Main bias enable, VMID=2x40k */ | 866 | /* Main bias enable, VMID=2x40k */ |
868 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | 867 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, |
@@ -870,7 +869,7 @@ static void vmid_reference(struct snd_soc_codec *codec) | |||
870 | WM8994_VMID_SEL_MASK, | 869 | WM8994_VMID_SEL_MASK, |
871 | WM8994_BIAS_ENA | 0x2); | 870 | WM8994_BIAS_ENA | 0x2); |
872 | 871 | ||
873 | msleep(50); | 872 | msleep(300); |
874 | 873 | ||
875 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | 874 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, |
876 | WM8994_VMID_RAMP_MASK | | 875 | WM8994_VMID_RAMP_MASK | |
@@ -939,16 +938,10 @@ static void vmid_dereference(struct snd_soc_codec *codec) | |||
939 | WM8994_BIAS_SRC | | 938 | WM8994_BIAS_SRC | |
940 | WM8994_VMID_DISCH); | 939 | WM8994_VMID_DISCH); |
941 | 940 | ||
942 | switch (wm8994->vmid_mode) { | 941 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, |
943 | case WM8994_VMID_FORCE: | 942 | WM8994_VMID_SEL_MASK, 0); |
944 | msleep(350); | ||
945 | break; | ||
946 | default: | ||
947 | break; | ||
948 | } | ||
949 | 943 | ||
950 | snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL, | 944 | msleep(400); |
951 | WM8994_VROI, WM8994_VROI); | ||
952 | 945 | ||
953 | /* Active discharge */ | 946 | /* Active discharge */ |
954 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | 947 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, |
@@ -957,17 +950,12 @@ static void vmid_dereference(struct snd_soc_codec *codec) | |||
957 | WM8994_LINEOUT1_DISCH | | 950 | WM8994_LINEOUT1_DISCH | |
958 | WM8994_LINEOUT2_DISCH); | 951 | WM8994_LINEOUT2_DISCH); |
959 | 952 | ||
960 | msleep(150); | ||
961 | |||
962 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3, | 953 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3, |
963 | WM8994_LINEOUT1N_ENA | | 954 | WM8994_LINEOUT1N_ENA | |
964 | WM8994_LINEOUT1P_ENA | | 955 | WM8994_LINEOUT1P_ENA | |
965 | WM8994_LINEOUT2N_ENA | | 956 | WM8994_LINEOUT2N_ENA | |
966 | WM8994_LINEOUT2P_ENA, 0); | 957 | WM8994_LINEOUT2P_ENA, 0); |
967 | 958 | ||
968 | snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL, | ||
969 | WM8994_VROI, 0); | ||
970 | |||
971 | /* Switch off startup biases */ | 959 | /* Switch off startup biases */ |
972 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | 960 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, |
973 | WM8994_BIAS_SRC | | 961 | WM8994_BIAS_SRC | |
@@ -976,10 +964,7 @@ static void vmid_dereference(struct snd_soc_codec *codec) | |||
976 | WM8994_VMID_RAMP_MASK, 0); | 964 | WM8994_VMID_RAMP_MASK, 0); |
977 | 965 | ||
978 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | 966 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, |
979 | WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); | 967 | WM8994_VMID_SEL_MASK, 0); |
980 | |||
981 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
982 | WM8994_VMID_RAMP_MASK, 0); | ||
983 | } | 968 | } |
984 | 969 | ||
985 | pm_runtime_put(codec->dev); | 970 | pm_runtime_put(codec->dev); |
@@ -2277,6 +2262,18 @@ out: | |||
2277 | 2262 | ||
2278 | configure_clock(codec); | 2263 | configure_clock(codec); |
2279 | 2264 | ||
2265 | /* | ||
2266 | * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers | ||
2267 | * for detection. | ||
2268 | */ | ||
2269 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { | ||
2270 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); | ||
2271 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | ||
2272 | WM8994_AIF1CLK_RATE_MASK, 0x1); | ||
2273 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | ||
2274 | WM8994_AIF2CLK_RATE_MASK, 0x1); | ||
2275 | } | ||
2276 | |||
2280 | return 0; | 2277 | return 0; |
2281 | } | 2278 | } |
2282 | 2279 | ||
@@ -2365,6 +2362,18 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | |||
2365 | 2362 | ||
2366 | configure_clock(codec); | 2363 | configure_clock(codec); |
2367 | 2364 | ||
2365 | /* | ||
2366 | * If SYSCLK will be less than 50kHz adjust AIFnCLK dividers | ||
2367 | * for detection. | ||
2368 | */ | ||
2369 | if (max(wm8994->aifclk[0], wm8994->aifclk[1]) < 50000) { | ||
2370 | dev_dbg(codec->dev, "Configuring AIFs for 128fs\n"); | ||
2371 | snd_soc_update_bits(codec, WM8994_AIF1_RATE, | ||
2372 | WM8994_AIF1CLK_RATE_MASK, 0x1); | ||
2373 | snd_soc_update_bits(codec, WM8994_AIF2_RATE, | ||
2374 | WM8994_AIF2CLK_RATE_MASK, 0x1); | ||
2375 | } | ||
2376 | |||
2368 | return 0; | 2377 | return 0; |
2369 | } | 2378 | } |
2370 | 2379 | ||
@@ -3082,7 +3091,8 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
3082 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3091 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3083 | { | 3092 | { |
3084 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3093 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3085 | struct wm8994_pdata *pdata = wm8994->pdata; | 3094 | struct wm8994 *control = wm8994->wm8994; |
3095 | struct wm8994_pdata *pdata = &control->pdata; | ||
3086 | struct snd_kcontrol_new controls[] = { | 3096 | struct snd_kcontrol_new controls[] = { |
3087 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3097 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
3088 | wm8994->retune_mobile_enum, | 3098 | wm8994->retune_mobile_enum, |
@@ -3149,7 +3159,8 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3149 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3159 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3150 | { | 3160 | { |
3151 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3161 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3152 | struct wm8994_pdata *pdata = wm8994->pdata; | 3162 | struct wm8994 *control = wm8994->wm8994; |
3163 | struct wm8994_pdata *pdata = &control->pdata; | ||
3153 | int ret, i; | 3164 | int ret, i; |
3154 | 3165 | ||
3155 | if (!pdata) | 3166 | if (!pdata) |
@@ -3389,38 +3400,80 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3389 | return IRQ_HANDLED; | 3400 | return IRQ_HANDLED; |
3390 | } | 3401 | } |
3391 | 3402 | ||
3392 | /* Default microphone detection handler for WM8958 - the user can | 3403 | static void wm1811_micd_stop(struct snd_soc_codec *codec) |
3393 | * override this if they wish. | 3404 | { |
3394 | */ | 3405 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3395 | static void wm8958_default_micdet(u16 status, void *data) | 3406 | |
3407 | if (!wm8994->jackdet) | ||
3408 | return; | ||
3409 | |||
3410 | mutex_lock(&wm8994->accdet_lock); | ||
3411 | |||
3412 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, WM8958_MICD_ENA, 0); | ||
3413 | |||
3414 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK); | ||
3415 | |||
3416 | mutex_unlock(&wm8994->accdet_lock); | ||
3417 | |||
3418 | if (wm8994->wm8994->pdata.jd_ext_cap) | ||
3419 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
3420 | "MICBIAS2"); | ||
3421 | } | ||
3422 | |||
3423 | static void wm8958_button_det(struct snd_soc_codec *codec, u16 status) | ||
3396 | { | 3424 | { |
3397 | struct snd_soc_codec *codec = data; | ||
3398 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3425 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3399 | int report; | 3426 | int report; |
3400 | 3427 | ||
3401 | dev_dbg(codec->dev, "MICDET %x\n", status); | 3428 | report = 0; |
3429 | if (status & 0x4) | ||
3430 | report |= SND_JACK_BTN_0; | ||
3431 | |||
3432 | if (status & 0x8) | ||
3433 | report |= SND_JACK_BTN_1; | ||
3434 | |||
3435 | if (status & 0x10) | ||
3436 | report |= SND_JACK_BTN_2; | ||
3437 | |||
3438 | if (status & 0x20) | ||
3439 | report |= SND_JACK_BTN_3; | ||
3440 | |||
3441 | if (status & 0x40) | ||
3442 | report |= SND_JACK_BTN_4; | ||
3443 | |||
3444 | if (status & 0x80) | ||
3445 | report |= SND_JACK_BTN_5; | ||
3446 | |||
3447 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | ||
3448 | wm8994->btn_mask); | ||
3449 | } | ||
3450 | |||
3451 | static void wm8958_mic_id(void *data, u16 status) | ||
3452 | { | ||
3453 | struct snd_soc_codec *codec = data; | ||
3454 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
3402 | 3455 | ||
3403 | /* Either nothing present or just starting detection */ | 3456 | /* Either nothing present or just starting detection */ |
3404 | if (!(status & WM8958_MICD_STS)) { | 3457 | if (!(status & WM8958_MICD_STS)) { |
3405 | if (!wm8994->jackdet) { | 3458 | /* If nothing present then clear our statuses */ |
3406 | /* If nothing present then clear our statuses */ | 3459 | dev_dbg(codec->dev, "Detected open circuit\n"); |
3407 | dev_dbg(codec->dev, "Detected open circuit\n"); | 3460 | wm8994->jack_mic = false; |
3408 | wm8994->jack_mic = false; | 3461 | wm8994->mic_detecting = true; |
3409 | wm8994->mic_detecting = true; | ||
3410 | 3462 | ||
3411 | wm8958_micd_set_rate(codec); | 3463 | wm1811_micd_stop(codec); |
3412 | 3464 | ||
3413 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3465 | wm8958_micd_set_rate(codec); |
3414 | wm8994->btn_mask | | 3466 | |
3415 | SND_JACK_HEADSET); | 3467 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, |
3416 | } | 3468 | wm8994->btn_mask | |
3469 | SND_JACK_HEADSET); | ||
3417 | return; | 3470 | return; |
3418 | } | 3471 | } |
3419 | 3472 | ||
3420 | /* If the measurement is showing a high impedence we've got a | 3473 | /* If the measurement is showing a high impedence we've got a |
3421 | * microphone. | 3474 | * microphone. |
3422 | */ | 3475 | */ |
3423 | if (wm8994->mic_detecting && (status & 0x600)) { | 3476 | if (status & 0x600) { |
3424 | dev_dbg(codec->dev, "Detected microphone\n"); | 3477 | dev_dbg(codec->dev, "Detected microphone\n"); |
3425 | 3478 | ||
3426 | wm8994->mic_detecting = false; | 3479 | wm8994->mic_detecting = false; |
@@ -3433,64 +3486,67 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3433 | } | 3486 | } |
3434 | 3487 | ||
3435 | 3488 | ||
3436 | if (wm8994->mic_detecting && status & 0xfc) { | 3489 | if (status & 0xfc) { |
3437 | dev_dbg(codec->dev, "Detected headphone\n"); | 3490 | dev_dbg(codec->dev, "Detected headphone\n"); |
3438 | wm8994->mic_detecting = false; | 3491 | wm8994->mic_detecting = false; |
3439 | 3492 | ||
3440 | wm8958_micd_set_rate(codec); | 3493 | wm8958_micd_set_rate(codec); |
3441 | 3494 | ||
3442 | /* If we have jackdet that will detect removal */ | 3495 | /* If we have jackdet that will detect removal */ |
3443 | if (wm8994->jackdet) { | 3496 | wm1811_micd_stop(codec); |
3444 | mutex_lock(&wm8994->accdet_lock); | ||
3445 | |||
3446 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3447 | WM8958_MICD_ENA, 0); | ||
3448 | |||
3449 | wm1811_jackdet_set_mode(codec, | ||
3450 | WM1811_JACKDET_MODE_JACK); | ||
3451 | |||
3452 | mutex_unlock(&wm8994->accdet_lock); | ||
3453 | |||
3454 | if (wm8994->pdata->jd_ext_cap) | ||
3455 | snd_soc_dapm_disable_pin(&codec->dapm, | ||
3456 | "MICBIAS2"); | ||
3457 | } | ||
3458 | 3497 | ||
3459 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, | 3498 | snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE, |
3460 | SND_JACK_HEADSET); | 3499 | SND_JACK_HEADSET); |
3461 | } | 3500 | } |
3501 | } | ||
3462 | 3502 | ||
3463 | /* Report short circuit as a button */ | 3503 | /* Deferred mic detection to allow for extra settling time */ |
3464 | if (wm8994->jack_mic) { | 3504 | static void wm1811_mic_work(struct work_struct *work) |
3465 | report = 0; | 3505 | { |
3466 | if (status & 0x4) | 3506 | struct wm8994_priv *wm8994 = container_of(work, struct wm8994_priv, |
3467 | report |= SND_JACK_BTN_0; | 3507 | mic_work.work); |
3508 | struct wm8994 *control = wm8994->wm8994; | ||
3509 | struct snd_soc_codec *codec = wm8994->hubs.codec; | ||
3468 | 3510 | ||
3469 | if (status & 0x8) | 3511 | pm_runtime_get_sync(codec->dev); |
3470 | report |= SND_JACK_BTN_1; | ||
3471 | 3512 | ||
3472 | if (status & 0x10) | 3513 | /* If required for an external cap force MICBIAS on */ |
3473 | report |= SND_JACK_BTN_2; | 3514 | if (control->pdata.jd_ext_cap) { |
3515 | snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
3516 | "MICBIAS2"); | ||
3517 | snd_soc_dapm_sync(&codec->dapm); | ||
3518 | } | ||
3474 | 3519 | ||
3475 | if (status & 0x20) | 3520 | mutex_lock(&wm8994->accdet_lock); |
3476 | report |= SND_JACK_BTN_3; | ||
3477 | 3521 | ||
3478 | if (status & 0x40) | 3522 | dev_dbg(codec->dev, "Starting mic detection\n"); |
3479 | report |= SND_JACK_BTN_4; | ||
3480 | 3523 | ||
3481 | if (status & 0x80) | 3524 | /* Use a user-supplied callback if we have one */ |
3482 | report |= SND_JACK_BTN_5; | 3525 | if (wm8994->micd_cb) { |
3526 | wm8994->micd_cb(wm8994->micd_cb_data); | ||
3527 | } else { | ||
3528 | /* | ||
3529 | * Start off measument of microphone impedence to find out | ||
3530 | * what's actually there. | ||
3531 | */ | ||
3532 | wm8994->mic_detecting = true; | ||
3533 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); | ||
3483 | 3534 | ||
3484 | snd_soc_jack_report(wm8994->micdet[0].jack, report, | 3535 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, |
3485 | wm8994->btn_mask); | 3536 | WM8958_MICD_ENA, WM8958_MICD_ENA); |
3486 | } | 3537 | } |
3538 | |||
3539 | mutex_unlock(&wm8994->accdet_lock); | ||
3540 | |||
3541 | pm_runtime_put(codec->dev); | ||
3487 | } | 3542 | } |
3488 | 3543 | ||
3489 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | 3544 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) |
3490 | { | 3545 | { |
3491 | struct wm8994_priv *wm8994 = data; | 3546 | struct wm8994_priv *wm8994 = data; |
3547 | struct wm8994 *control = wm8994->wm8994; | ||
3492 | struct snd_soc_codec *codec = wm8994->hubs.codec; | 3548 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3493 | int reg; | 3549 | int reg, delay; |
3494 | bool present; | 3550 | bool present; |
3495 | 3551 | ||
3496 | pm_runtime_get_sync(codec->dev); | 3552 | pm_runtime_get_sync(codec->dev); |
@@ -3521,18 +3577,14 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3521 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, | 3577 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, |
3522 | WM1811_JACKDET_DB, 0); | 3578 | WM1811_JACKDET_DB, 0); |
3523 | 3579 | ||
3524 | /* | 3580 | delay = control->pdata.micdet_delay; |
3525 | * Start off measument of microphone impedence to find | 3581 | schedule_delayed_work(&wm8994->mic_work, |
3526 | * out what's actually there. | 3582 | msecs_to_jiffies(delay)); |
3527 | */ | ||
3528 | wm8994->mic_detecting = true; | ||
3529 | wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC); | ||
3530 | |||
3531 | snd_soc_update_bits(codec, WM8958_MIC_DETECT_1, | ||
3532 | WM8958_MICD_ENA, WM8958_MICD_ENA); | ||
3533 | } else { | 3583 | } else { |
3534 | dev_dbg(codec->dev, "Jack not detected\n"); | 3584 | dev_dbg(codec->dev, "Jack not detected\n"); |
3535 | 3585 | ||
3586 | cancel_delayed_work_sync(&wm8994->mic_work); | ||
3587 | |||
3536 | snd_soc_update_bits(codec, WM8958_MICBIAS2, | 3588 | snd_soc_update_bits(codec, WM8958_MICBIAS2, |
3537 | WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); | 3589 | WM8958_MICB2_DISCH, WM8958_MICB2_DISCH); |
3538 | 3590 | ||
@@ -3549,14 +3601,9 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3549 | 3601 | ||
3550 | mutex_unlock(&wm8994->accdet_lock); | 3602 | mutex_unlock(&wm8994->accdet_lock); |
3551 | 3603 | ||
3552 | /* If required for an external cap force MICBIAS on */ | 3604 | /* Turn off MICBIAS if it was on for an external cap */ |
3553 | if (wm8994->pdata->jd_ext_cap) { | 3605 | if (control->pdata.jd_ext_cap && !present) |
3554 | if (present) | 3606 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2"); |
3555 | snd_soc_dapm_force_enable_pin(&codec->dapm, | ||
3556 | "MICBIAS2"); | ||
3557 | else | ||
3558 | snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2"); | ||
3559 | } | ||
3560 | 3607 | ||
3561 | if (present) | 3608 | if (present) |
3562 | snd_soc_jack_report(wm8994->micdet[0].jack, | 3609 | snd_soc_jack_report(wm8994->micdet[0].jack, |
@@ -3599,7 +3646,8 @@ static void wm1811_jackdet_bootstrap(struct work_struct *work) | |||
3599 | * detection algorithm. | 3646 | * detection algorithm. |
3600 | */ | 3647 | */ |
3601 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 3648 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
3602 | wm8958_micdet_cb cb, void *cb_data) | 3649 | wm1811_micdet_cb det_cb, void *det_cb_data, |
3650 | wm1811_mic_id_cb id_cb, void *id_cb_data) | ||
3603 | { | 3651 | { |
3604 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3652 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3605 | struct wm8994 *control = wm8994->wm8994; | 3653 | struct wm8994 *control = wm8994->wm8994; |
@@ -3614,27 +3662,32 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3614 | } | 3662 | } |
3615 | 3663 | ||
3616 | if (jack) { | 3664 | if (jack) { |
3617 | if (!cb) { | ||
3618 | dev_dbg(codec->dev, "Using default micdet callback\n"); | ||
3619 | cb = wm8958_default_micdet; | ||
3620 | cb_data = codec; | ||
3621 | } | ||
3622 | |||
3623 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); | 3665 | snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS"); |
3624 | snd_soc_dapm_sync(&codec->dapm); | 3666 | snd_soc_dapm_sync(&codec->dapm); |
3625 | 3667 | ||
3626 | wm8994->micdet[0].jack = jack; | 3668 | wm8994->micdet[0].jack = jack; |
3627 | wm8994->jack_cb = cb; | ||
3628 | wm8994->jack_cb_data = cb_data; | ||
3629 | 3669 | ||
3630 | wm8994->mic_detecting = true; | 3670 | if (det_cb) { |
3631 | wm8994->jack_mic = false; | 3671 | wm8994->micd_cb = det_cb; |
3672 | wm8994->micd_cb_data = det_cb_data; | ||
3673 | } else { | ||
3674 | wm8994->mic_detecting = true; | ||
3675 | wm8994->jack_mic = false; | ||
3676 | } | ||
3677 | |||
3678 | if (id_cb) { | ||
3679 | wm8994->mic_id_cb = id_cb; | ||
3680 | wm8994->mic_id_cb_data = id_cb_data; | ||
3681 | } else { | ||
3682 | wm8994->mic_id_cb = wm8958_mic_id; | ||
3683 | wm8994->mic_id_cb_data = codec; | ||
3684 | } | ||
3632 | 3685 | ||
3633 | wm8958_micd_set_rate(codec); | 3686 | wm8958_micd_set_rate(codec); |
3634 | 3687 | ||
3635 | /* Detect microphones and short circuits by default */ | 3688 | /* Detect microphones and short circuits by default */ |
3636 | if (wm8994->pdata->micd_lvl_sel) | 3689 | if (control->pdata.micd_lvl_sel) |
3637 | micd_lvl_sel = wm8994->pdata->micd_lvl_sel; | 3690 | micd_lvl_sel = control->pdata.micd_lvl_sel; |
3638 | else | 3691 | else |
3639 | micd_lvl_sel = 0x41; | 3692 | micd_lvl_sel = 0x41; |
3640 | 3693 | ||
@@ -3728,10 +3781,22 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data) | |||
3728 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3781 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
3729 | #endif | 3782 | #endif |
3730 | 3783 | ||
3731 | if (wm8994->jack_cb) | 3784 | /* Avoid a transient report when the accessory is being removed */ |
3732 | wm8994->jack_cb(reg, wm8994->jack_cb_data); | 3785 | if (wm8994->jackdet) { |
3786 | reg = snd_soc_read(codec, WM1811_JACKDET_CTRL); | ||
3787 | if (reg < 0) { | ||
3788 | dev_err(codec->dev, "Failed to read jack status: %d\n", | ||
3789 | reg); | ||
3790 | } else if (!(reg & WM1811_JACKDET_LVL)) { | ||
3791 | dev_dbg(codec->dev, "Ignoring removed jack\n"); | ||
3792 | return IRQ_HANDLED; | ||
3793 | } | ||
3794 | } | ||
3795 | |||
3796 | if (wm8994->mic_detecting) | ||
3797 | wm8994->mic_id_cb(wm8994->mic_id_cb_data, reg); | ||
3733 | else | 3798 | else |
3734 | dev_warn(codec->dev, "Accessory detection with no callback\n"); | 3799 | wm8958_button_det(codec, reg); |
3735 | 3800 | ||
3736 | out: | 3801 | out: |
3737 | pm_runtime_put(codec->dev); | 3802 | pm_runtime_put(codec->dev); |
@@ -3779,15 +3844,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3779 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 3844 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); |
3780 | 3845 | ||
3781 | mutex_init(&wm8994->accdet_lock); | 3846 | mutex_init(&wm8994->accdet_lock); |
3782 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | ||
3783 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | 3847 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, |
3784 | wm1811_jackdet_bootstrap); | 3848 | wm1811_jackdet_bootstrap); |
3785 | 3849 | ||
3850 | switch (control->type) { | ||
3851 | case WM8994: | ||
3852 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | ||
3853 | break; | ||
3854 | case WM1811: | ||
3855 | INIT_DELAYED_WORK(&wm8994->mic_work, wm1811_mic_work); | ||
3856 | break; | ||
3857 | default: | ||
3858 | break; | ||
3859 | } | ||
3860 | |||
3786 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3861 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3787 | init_completion(&wm8994->fll_locked[i]); | 3862 | init_completion(&wm8994->fll_locked[i]); |
3788 | 3863 | ||
3789 | if (wm8994->pdata && wm8994->pdata->micdet_irq) | 3864 | wm8994->micdet_irq = control->pdata.micdet_irq; |
3790 | wm8994->micdet_irq = wm8994->pdata->micdet_irq; | ||
3791 | 3865 | ||
3792 | pm_runtime_enable(codec->dev); | 3866 | pm_runtime_enable(codec->dev); |
3793 | pm_runtime_idle(codec->dev); | 3867 | pm_runtime_idle(codec->dev); |
@@ -3800,8 +3874,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3800 | switch (control->type) { | 3874 | switch (control->type) { |
3801 | case WM8994: | 3875 | case WM8994: |
3802 | /* Single ended line outputs should have VMID on. */ | 3876 | /* Single ended line outputs should have VMID on. */ |
3803 | if (!wm8994->pdata->lineout1_diff || | 3877 | if (!control->pdata.lineout1_diff || |
3804 | !wm8994->pdata->lineout2_diff) | 3878 | !control->pdata.lineout2_diff) |
3805 | codec->dapm.idle_bias_off = 0; | 3879 | codec->dapm.idle_bias_off = 0; |
3806 | 3880 | ||
3807 | switch (wm8994->revision) { | 3881 | switch (wm8994->revision) { |
@@ -3839,20 +3913,8 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3839 | wm8994->hubs.no_cache_dac_hp_direct = true; | 3913 | wm8994->hubs.no_cache_dac_hp_direct = true; |
3840 | wm8994->fll_byp = true; | 3914 | wm8994->fll_byp = true; |
3841 | 3915 | ||
3842 | switch (control->cust_id) { | 3916 | wm8994->hubs.dcs_codes_l = -9; |
3843 | case 0: | 3917 | wm8994->hubs.dcs_codes_r = -7; |
3844 | case 2: | ||
3845 | wm8994->hubs.dcs_codes_l = -9; | ||
3846 | wm8994->hubs.dcs_codes_r = -7; | ||
3847 | break; | ||
3848 | case 1: | ||
3849 | case 3: | ||
3850 | wm8994->hubs.dcs_codes_l = -8; | ||
3851 | wm8994->hubs.dcs_codes_r = -7; | ||
3852 | break; | ||
3853 | default: | ||
3854 | break; | ||
3855 | } | ||
3856 | 3918 | ||
3857 | snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, | 3919 | snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1, |
3858 | WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); | 3920 | WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN); |
@@ -4236,7 +4298,6 @@ static int __devinit wm8994_probe(struct platform_device *pdev) | |||
4236 | platform_set_drvdata(pdev, wm8994); | 4298 | platform_set_drvdata(pdev, wm8994); |
4237 | 4299 | ||
4238 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); | 4300 | wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent); |
4239 | wm8994->pdata = dev_get_platdata(pdev->dev.parent); | ||
4240 | 4301 | ||
4241 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, | 4302 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, |
4242 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); | 4303 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); |
@@ -4266,7 +4327,7 @@ static int wm8994_resume(struct device *dev) | |||
4266 | { | 4327 | { |
4267 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); | 4328 | struct wm8994_priv *wm8994 = dev_get_drvdata(dev); |
4268 | 4329 | ||
4269 | if (wm8994->jackdet && wm8994->jack_cb) | 4330 | if (wm8994->jackdet && wm8994->jackdet_mode) |
4270 | regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, | 4331 | regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2, |
4271 | WM1811_JACKDET_MODE_MASK, | 4332 | WM1811_JACKDET_MODE_MASK, |
4272 | WM1811_JACKDET_MODE_AUDIO); | 4333 | WM1811_JACKDET_MODE_AUDIO); |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index ccbce5791e95..45f192702024 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -39,12 +39,14 @@ enum wm8994_vmid_mode { | |||
39 | WM8994_VMID_FORCE, | 39 | WM8994_VMID_FORCE, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | typedef void (*wm8958_micdet_cb)(u16 status, void *data); | 42 | typedef void (*wm1811_micdet_cb)(void *data); |
43 | typedef void (*wm1811_mic_id_cb)(void *data, u16 status); | ||
43 | 44 | ||
44 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 45 | int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
45 | int micbias); | 46 | int micbias); |
46 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | 47 | int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, |
47 | wm8958_micdet_cb cb, void *cb_data); | 48 | wm1811_micdet_cb cb, void *det_cb_data, |
49 | wm1811_mic_id_cb id_cb, void *id_cb_data); | ||
48 | 50 | ||
49 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode); | 51 | int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode); |
50 | 52 | ||
@@ -138,12 +140,13 @@ struct wm8994_priv { | |||
138 | int jackdet_mode; | 140 | int jackdet_mode; |
139 | struct delayed_work jackdet_bootstrap; | 141 | struct delayed_work jackdet_bootstrap; |
140 | 142 | ||
141 | wm8958_micdet_cb jack_cb; | ||
142 | void *jack_cb_data; | ||
143 | int micdet_irq; | 143 | int micdet_irq; |
144 | wm1811_micdet_cb micd_cb; | ||
145 | void *micd_cb_data; | ||
146 | wm1811_mic_id_cb mic_id_cb; | ||
147 | void *mic_id_cb_data; | ||
144 | 148 | ||
145 | int revision; | 149 | int revision; |
146 | struct wm8994_pdata *pdata; | ||
147 | 150 | ||
148 | unsigned int aif1clk_enable:1; | 151 | unsigned int aif1clk_enable:1; |
149 | unsigned int aif2clk_enable:1; | 152 | unsigned int aif2clk_enable:1; |
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 28c89b094c6e..f1a7cf147af0 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -2261,41 +2261,28 @@ static int __devinit wm8995_spi_probe(struct spi_device *spi) | |||
2261 | struct wm8995_priv *wm8995; | 2261 | struct wm8995_priv *wm8995; |
2262 | int ret; | 2262 | int ret; |
2263 | 2263 | ||
2264 | wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL); | 2264 | wm8995 = devm_kzalloc(&spi->dev, sizeof(*wm8995), GFP_KERNEL); |
2265 | if (!wm8995) | 2265 | if (!wm8995) |
2266 | return -ENOMEM; | 2266 | return -ENOMEM; |
2267 | 2267 | ||
2268 | spi_set_drvdata(spi, wm8995); | 2268 | spi_set_drvdata(spi, wm8995); |
2269 | 2269 | ||
2270 | wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap); | 2270 | wm8995->regmap = devm_regmap_init_spi(spi, &wm8995_regmap); |
2271 | if (IS_ERR(wm8995->regmap)) { | 2271 | if (IS_ERR(wm8995->regmap)) { |
2272 | ret = PTR_ERR(wm8995->regmap); | 2272 | ret = PTR_ERR(wm8995->regmap); |
2273 | dev_err(&spi->dev, "Failed to register regmap: %d\n", ret); | 2273 | dev_err(&spi->dev, "Failed to register regmap: %d\n", ret); |
2274 | goto err_alloc; | 2274 | return ret; |
2275 | } | 2275 | } |
2276 | 2276 | ||
2277 | ret = snd_soc_register_codec(&spi->dev, | 2277 | ret = snd_soc_register_codec(&spi->dev, |
2278 | &soc_codec_dev_wm8995, wm8995_dai, | 2278 | &soc_codec_dev_wm8995, wm8995_dai, |
2279 | ARRAY_SIZE(wm8995_dai)); | 2279 | ARRAY_SIZE(wm8995_dai)); |
2280 | if (ret < 0) | ||
2281 | goto err_regmap; | ||
2282 | |||
2283 | return ret; | ||
2284 | |||
2285 | err_regmap: | ||
2286 | regmap_exit(wm8995->regmap); | ||
2287 | err_alloc: | ||
2288 | kfree(wm8995); | ||
2289 | |||
2290 | return ret; | 2280 | return ret; |
2291 | } | 2281 | } |
2292 | 2282 | ||
2293 | static int __devexit wm8995_spi_remove(struct spi_device *spi) | 2283 | static int __devexit wm8995_spi_remove(struct spi_device *spi) |
2294 | { | 2284 | { |
2295 | struct wm8995_priv *wm8995 = spi_get_drvdata(spi); | ||
2296 | snd_soc_unregister_codec(&spi->dev); | 2285 | snd_soc_unregister_codec(&spi->dev); |
2297 | regmap_exit(wm8995->regmap); | ||
2298 | kfree(wm8995); | ||
2299 | return 0; | 2286 | return 0; |
2300 | } | 2287 | } |
2301 | 2288 | ||
@@ -2316,44 +2303,31 @@ static __devinit int wm8995_i2c_probe(struct i2c_client *i2c, | |||
2316 | struct wm8995_priv *wm8995; | 2303 | struct wm8995_priv *wm8995; |
2317 | int ret; | 2304 | int ret; |
2318 | 2305 | ||
2319 | wm8995 = kzalloc(sizeof *wm8995, GFP_KERNEL); | 2306 | wm8995 = devm_kzalloc(&i2c->dev, sizeof(*wm8995), GFP_KERNEL); |
2320 | if (!wm8995) | 2307 | if (!wm8995) |
2321 | return -ENOMEM; | 2308 | return -ENOMEM; |
2322 | 2309 | ||
2323 | i2c_set_clientdata(i2c, wm8995); | 2310 | i2c_set_clientdata(i2c, wm8995); |
2324 | 2311 | ||
2325 | wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap); | 2312 | wm8995->regmap = devm_regmap_init_i2c(i2c, &wm8995_regmap); |
2326 | if (IS_ERR(wm8995->regmap)) { | 2313 | if (IS_ERR(wm8995->regmap)) { |
2327 | ret = PTR_ERR(wm8995->regmap); | 2314 | ret = PTR_ERR(wm8995->regmap); |
2328 | dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret); | 2315 | dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret); |
2329 | goto err_alloc; | 2316 | return ret; |
2330 | } | 2317 | } |
2331 | 2318 | ||
2332 | ret = snd_soc_register_codec(&i2c->dev, | 2319 | ret = snd_soc_register_codec(&i2c->dev, |
2333 | &soc_codec_dev_wm8995, wm8995_dai, | 2320 | &soc_codec_dev_wm8995, wm8995_dai, |
2334 | ARRAY_SIZE(wm8995_dai)); | 2321 | ARRAY_SIZE(wm8995_dai)); |
2335 | if (ret < 0) { | 2322 | if (ret < 0) |
2336 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); | 2323 | dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret); |
2337 | goto err_regmap; | ||
2338 | } | ||
2339 | |||
2340 | return ret; | ||
2341 | |||
2342 | err_regmap: | ||
2343 | regmap_exit(wm8995->regmap); | ||
2344 | err_alloc: | ||
2345 | kfree(wm8995); | ||
2346 | 2324 | ||
2347 | return ret; | 2325 | return ret; |
2348 | } | 2326 | } |
2349 | 2327 | ||
2350 | static __devexit int wm8995_i2c_remove(struct i2c_client *client) | 2328 | static __devexit int wm8995_i2c_remove(struct i2c_client *client) |
2351 | { | 2329 | { |
2352 | struct wm8995_priv *wm8995 = i2c_get_clientdata(client); | ||
2353 | |||
2354 | snd_soc_unregister_codec(&client->dev); | 2330 | snd_soc_unregister_codec(&client->dev); |
2355 | regmap_exit(wm8995->regmap); | ||
2356 | kfree(wm8995); | ||
2357 | return 0; | 2331 | return 0; |
2358 | } | 2332 | } |
2359 | 2333 | ||
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index 2de74e1ea225..860144e85e06 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1341,28 +1341,27 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | |||
1341 | 1341 | ||
1342 | i2c_set_clientdata(i2c, wm9081); | 1342 | i2c_set_clientdata(i2c, wm9081); |
1343 | 1343 | ||
1344 | wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap); | 1344 | wm9081->regmap = devm_regmap_init_i2c(i2c, &wm9081_regmap); |
1345 | if (IS_ERR(wm9081->regmap)) { | 1345 | if (IS_ERR(wm9081->regmap)) { |
1346 | ret = PTR_ERR(wm9081->regmap); | 1346 | ret = PTR_ERR(wm9081->regmap); |
1347 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); | 1347 | dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret); |
1348 | goto err; | 1348 | return ret; |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, ®); | 1351 | ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, ®); |
1352 | if (ret != 0) { | 1352 | if (ret != 0) { |
1353 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); | 1353 | dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret); |
1354 | goto err_regmap; | 1354 | return ret; |
1355 | } | 1355 | } |
1356 | if (reg != 0x9081) { | 1356 | if (reg != 0x9081) { |
1357 | dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg); | 1357 | dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg); |
1358 | ret = -EINVAL; | 1358 | return -EINVAL; |
1359 | goto err_regmap; | ||
1360 | } | 1359 | } |
1361 | 1360 | ||
1362 | ret = wm9081_reset(wm9081->regmap); | 1361 | ret = wm9081_reset(wm9081->regmap); |
1363 | if (ret < 0) { | 1362 | if (ret < 0) { |
1364 | dev_err(&i2c->dev, "Failed to issue reset\n"); | 1363 | dev_err(&i2c->dev, "Failed to issue reset\n"); |
1365 | goto err_regmap; | 1364 | return ret; |
1366 | } | 1365 | } |
1367 | 1366 | ||
1368 | if (dev_get_platdata(&i2c->dev)) | 1367 | if (dev_get_platdata(&i2c->dev)) |
@@ -1382,23 +1381,14 @@ static __devinit int wm9081_i2c_probe(struct i2c_client *i2c, | |||
1382 | ret = snd_soc_register_codec(&i2c->dev, | 1381 | ret = snd_soc_register_codec(&i2c->dev, |
1383 | &soc_codec_dev_wm9081, &wm9081_dai, 1); | 1382 | &soc_codec_dev_wm9081, &wm9081_dai, 1); |
1384 | if (ret < 0) | 1383 | if (ret < 0) |
1385 | goto err_regmap; | 1384 | return ret; |
1386 | 1385 | ||
1387 | return 0; | 1386 | return 0; |
1388 | |||
1389 | err_regmap: | ||
1390 | regmap_exit(wm9081->regmap); | ||
1391 | err: | ||
1392 | |||
1393 | return ret; | ||
1394 | } | 1387 | } |
1395 | 1388 | ||
1396 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) | 1389 | static __devexit int wm9081_i2c_remove(struct i2c_client *client) |
1397 | { | 1390 | { |
1398 | struct wm9081_priv *wm9081 = i2c_get_clientdata(client); | ||
1399 | |||
1400 | snd_soc_unregister_codec(&client->dev); | 1391 | snd_soc_unregister_codec(&client->dev); |
1401 | regmap_exit(wm9081->regmap); | ||
1402 | return 0; | 1392 | return 0; |
1403 | } | 1393 | } |
1404 | 1394 | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c new file mode 100644 index 000000000000..ffc89fab96fb --- /dev/null +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -0,0 +1,699 @@ | |||
1 | /* | ||
2 | * wm_adsp.c -- Wolfson ADSP support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/delay.h> | ||
17 | #include <linux/firmware.h> | ||
18 | #include <linux/pm.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | #include <linux/regmap.h> | ||
21 | #include <linux/regulator/consumer.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <sound/core.h> | ||
24 | #include <sound/pcm.h> | ||
25 | #include <sound/pcm_params.h> | ||
26 | #include <sound/soc.h> | ||
27 | #include <sound/jack.h> | ||
28 | #include <sound/initval.h> | ||
29 | #include <sound/tlv.h> | ||
30 | |||
31 | #include <linux/mfd/arizona/registers.h> | ||
32 | |||
33 | #include "wm_adsp.h" | ||
34 | |||
35 | #define adsp_crit(_dsp, fmt, ...) \ | ||
36 | dev_crit(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) | ||
37 | #define adsp_err(_dsp, fmt, ...) \ | ||
38 | dev_err(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) | ||
39 | #define adsp_warn(_dsp, fmt, ...) \ | ||
40 | dev_warn(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) | ||
41 | #define adsp_info(_dsp, fmt, ...) \ | ||
42 | dev_info(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) | ||
43 | #define adsp_dbg(_dsp, fmt, ...) \ | ||
44 | dev_dbg(_dsp->dev, "DSP%d: " fmt, _dsp->num, ##__VA_ARGS__) | ||
45 | |||
46 | #define ADSP1_CONTROL_1 0x00 | ||
47 | #define ADSP1_CONTROL_2 0x02 | ||
48 | #define ADSP1_CONTROL_3 0x03 | ||
49 | #define ADSP1_CONTROL_4 0x04 | ||
50 | #define ADSP1_CONTROL_5 0x06 | ||
51 | #define ADSP1_CONTROL_6 0x07 | ||
52 | #define ADSP1_CONTROL_7 0x08 | ||
53 | #define ADSP1_CONTROL_8 0x09 | ||
54 | #define ADSP1_CONTROL_9 0x0A | ||
55 | #define ADSP1_CONTROL_10 0x0B | ||
56 | #define ADSP1_CONTROL_11 0x0C | ||
57 | #define ADSP1_CONTROL_12 0x0D | ||
58 | #define ADSP1_CONTROL_13 0x0F | ||
59 | #define ADSP1_CONTROL_14 0x10 | ||
60 | #define ADSP1_CONTROL_15 0x11 | ||
61 | #define ADSP1_CONTROL_16 0x12 | ||
62 | #define ADSP1_CONTROL_17 0x13 | ||
63 | #define ADSP1_CONTROL_18 0x14 | ||
64 | #define ADSP1_CONTROL_19 0x16 | ||
65 | #define ADSP1_CONTROL_20 0x17 | ||
66 | #define ADSP1_CONTROL_21 0x18 | ||
67 | #define ADSP1_CONTROL_22 0x1A | ||
68 | #define ADSP1_CONTROL_23 0x1B | ||
69 | #define ADSP1_CONTROL_24 0x1C | ||
70 | #define ADSP1_CONTROL_25 0x1E | ||
71 | #define ADSP1_CONTROL_26 0x20 | ||
72 | #define ADSP1_CONTROL_27 0x21 | ||
73 | #define ADSP1_CONTROL_28 0x22 | ||
74 | #define ADSP1_CONTROL_29 0x23 | ||
75 | #define ADSP1_CONTROL_30 0x24 | ||
76 | #define ADSP1_CONTROL_31 0x26 | ||
77 | |||
78 | /* | ||
79 | * ADSP1 Control 19 | ||
80 | */ | ||
81 | #define ADSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ | ||
82 | #define ADSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ | ||
83 | #define ADSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */ | ||
84 | |||
85 | |||
86 | /* | ||
87 | * ADSP1 Control 30 | ||
88 | */ | ||
89 | #define ADSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */ | ||
90 | #define ADSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */ | ||
91 | #define ADSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */ | ||
92 | #define ADSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */ | ||
93 | #define ADSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ | ||
94 | #define ADSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ | ||
95 | #define ADSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ | ||
96 | #define ADSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ | ||
97 | #define ADSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ | ||
98 | #define ADSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ | ||
99 | #define ADSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ | ||
100 | #define ADSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ | ||
101 | #define ADSP1_START 0x0001 /* DSP1_START */ | ||
102 | #define ADSP1_START_MASK 0x0001 /* DSP1_START */ | ||
103 | #define ADSP1_START_SHIFT 0 /* DSP1_START */ | ||
104 | #define ADSP1_START_WIDTH 1 /* DSP1_START */ | ||
105 | |||
106 | #define ADSP2_CONTROL 0 | ||
107 | #define ADSP2_CLOCKING 1 | ||
108 | #define ADSP2_STATUS1 4 | ||
109 | |||
110 | /* | ||
111 | * ADSP2 Control | ||
112 | */ | ||
113 | |||
114 | #define ADSP2_MEM_ENA 0x0010 /* DSP1_MEM_ENA */ | ||
115 | #define ADSP2_MEM_ENA_MASK 0x0010 /* DSP1_MEM_ENA */ | ||
116 | #define ADSP2_MEM_ENA_SHIFT 4 /* DSP1_MEM_ENA */ | ||
117 | #define ADSP2_MEM_ENA_WIDTH 1 /* DSP1_MEM_ENA */ | ||
118 | #define ADSP2_SYS_ENA 0x0004 /* DSP1_SYS_ENA */ | ||
119 | #define ADSP2_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */ | ||
120 | #define ADSP2_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */ | ||
121 | #define ADSP2_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */ | ||
122 | #define ADSP2_CORE_ENA 0x0002 /* DSP1_CORE_ENA */ | ||
123 | #define ADSP2_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */ | ||
124 | #define ADSP2_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */ | ||
125 | #define ADSP2_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */ | ||
126 | #define ADSP2_START 0x0001 /* DSP1_START */ | ||
127 | #define ADSP2_START_MASK 0x0001 /* DSP1_START */ | ||
128 | #define ADSP2_START_SHIFT 0 /* DSP1_START */ | ||
129 | #define ADSP2_START_WIDTH 1 /* DSP1_START */ | ||
130 | |||
131 | /* | ||
132 | * ADSP2 clocking | ||
133 | */ | ||
134 | #define ADSP2_CLK_SEL_MASK 0x0007 /* CLK_SEL_ENA */ | ||
135 | #define ADSP2_CLK_SEL_SHIFT 0 /* CLK_SEL_ENA */ | ||
136 | #define ADSP2_CLK_SEL_WIDTH 3 /* CLK_SEL_ENA */ | ||
137 | |||
138 | /* | ||
139 | * ADSP2 Status 1 | ||
140 | */ | ||
141 | #define ADSP2_RAM_RDY 0x0001 | ||
142 | #define ADSP2_RAM_RDY_MASK 0x0001 | ||
143 | #define ADSP2_RAM_RDY_SHIFT 0 | ||
144 | #define ADSP2_RAM_RDY_WIDTH 1 | ||
145 | |||
146 | |||
147 | static struct wm_adsp_region const *wm_adsp_find_region(struct wm_adsp *dsp, | ||
148 | int type) | ||
149 | { | ||
150 | int i; | ||
151 | |||
152 | for (i = 0; i < dsp->num_mems; i++) | ||
153 | if (dsp->mem[i].type == type) | ||
154 | return &dsp->mem[i]; | ||
155 | |||
156 | return NULL; | ||
157 | } | ||
158 | |||
159 | static int wm_adsp_load(struct wm_adsp *dsp) | ||
160 | { | ||
161 | const struct firmware *firmware; | ||
162 | struct regmap *regmap = dsp->regmap; | ||
163 | unsigned int pos = 0; | ||
164 | const struct wmfw_header *header; | ||
165 | const struct wmfw_adsp1_sizes *adsp1_sizes; | ||
166 | const struct wmfw_adsp2_sizes *adsp2_sizes; | ||
167 | const struct wmfw_footer *footer; | ||
168 | const struct wmfw_region *region; | ||
169 | const struct wm_adsp_region *mem; | ||
170 | const char *region_name; | ||
171 | char *file, *text; | ||
172 | unsigned int reg; | ||
173 | int regions = 0; | ||
174 | int ret, offset, type, sizes; | ||
175 | |||
176 | file = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
177 | if (file == NULL) | ||
178 | return -ENOMEM; | ||
179 | |||
180 | snprintf(file, PAGE_SIZE, "%s-dsp%d.wmfw", dsp->part, dsp->num); | ||
181 | file[PAGE_SIZE - 1] = '\0'; | ||
182 | |||
183 | ret = request_firmware(&firmware, file, dsp->dev); | ||
184 | if (ret != 0) { | ||
185 | adsp_err(dsp, "Failed to request '%s'\n", file); | ||
186 | goto out; | ||
187 | } | ||
188 | ret = -EINVAL; | ||
189 | |||
190 | pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); | ||
191 | if (pos >= firmware->size) { | ||
192 | adsp_err(dsp, "%s: file too short, %zu bytes\n", | ||
193 | file, firmware->size); | ||
194 | goto out_fw; | ||
195 | } | ||
196 | |||
197 | header = (void*)&firmware->data[0]; | ||
198 | |||
199 | if (memcmp(&header->magic[0], "WMFW", 4) != 0) { | ||
200 | adsp_err(dsp, "%s: invalid magic\n", file); | ||
201 | goto out_fw; | ||
202 | } | ||
203 | |||
204 | if (header->ver != 0) { | ||
205 | adsp_err(dsp, "%s: unknown file format %d\n", | ||
206 | file, header->ver); | ||
207 | goto out_fw; | ||
208 | } | ||
209 | |||
210 | if (header->core != dsp->type) { | ||
211 | adsp_err(dsp, "%s: invalid core %d != %d\n", | ||
212 | file, header->core, dsp->type); | ||
213 | goto out_fw; | ||
214 | } | ||
215 | |||
216 | switch (dsp->type) { | ||
217 | case WMFW_ADSP1: | ||
218 | pos = sizeof(*header) + sizeof(*adsp1_sizes) + sizeof(*footer); | ||
219 | adsp1_sizes = (void *)&(header[1]); | ||
220 | footer = (void *)&(adsp1_sizes[1]); | ||
221 | sizes = sizeof(*adsp1_sizes); | ||
222 | |||
223 | adsp_dbg(dsp, "%s: %d DM, %d PM, %d ZM\n", | ||
224 | file, le32_to_cpu(adsp1_sizes->dm), | ||
225 | le32_to_cpu(adsp1_sizes->pm), | ||
226 | le32_to_cpu(adsp1_sizes->zm)); | ||
227 | break; | ||
228 | |||
229 | case WMFW_ADSP2: | ||
230 | pos = sizeof(*header) + sizeof(*adsp2_sizes) + sizeof(*footer); | ||
231 | adsp2_sizes = (void *)&(header[1]); | ||
232 | footer = (void *)&(adsp2_sizes[1]); | ||
233 | sizes = sizeof(*adsp2_sizes); | ||
234 | |||
235 | adsp_dbg(dsp, "%s: %d XM, %d YM %d PM, %d ZM\n", | ||
236 | file, le32_to_cpu(adsp2_sizes->xm), | ||
237 | le32_to_cpu(adsp2_sizes->ym), | ||
238 | le32_to_cpu(adsp2_sizes->pm), | ||
239 | le32_to_cpu(adsp2_sizes->zm)); | ||
240 | break; | ||
241 | |||
242 | default: | ||
243 | BUG_ON(NULL == "Unknown DSP type"); | ||
244 | goto out_fw; | ||
245 | } | ||
246 | |||
247 | if (le32_to_cpu(header->len) != sizeof(*header) + | ||
248 | sizes + sizeof(*footer)) { | ||
249 | adsp_err(dsp, "%s: unexpected header length %d\n", | ||
250 | file, le32_to_cpu(header->len)); | ||
251 | goto out_fw; | ||
252 | } | ||
253 | |||
254 | adsp_dbg(dsp, "%s: timestamp %llu\n", file, | ||
255 | le64_to_cpu(footer->timestamp)); | ||
256 | |||
257 | while (pos < firmware->size && | ||
258 | pos - firmware->size > sizeof(*region)) { | ||
259 | region = (void *)&(firmware->data[pos]); | ||
260 | region_name = "Unknown"; | ||
261 | reg = 0; | ||
262 | text = NULL; | ||
263 | offset = le32_to_cpu(region->offset) & 0xffffff; | ||
264 | type = be32_to_cpu(region->type) & 0xff; | ||
265 | mem = wm_adsp_find_region(dsp, type); | ||
266 | |||
267 | switch (type) { | ||
268 | case WMFW_NAME_TEXT: | ||
269 | region_name = "Firmware name"; | ||
270 | text = kzalloc(le32_to_cpu(region->len) + 1, | ||
271 | GFP_KERNEL); | ||
272 | break; | ||
273 | case WMFW_INFO_TEXT: | ||
274 | region_name = "Information"; | ||
275 | text = kzalloc(le32_to_cpu(region->len) + 1, | ||
276 | GFP_KERNEL); | ||
277 | break; | ||
278 | case WMFW_ABSOLUTE: | ||
279 | region_name = "Absolute"; | ||
280 | reg = offset; | ||
281 | break; | ||
282 | case WMFW_ADSP1_PM: | ||
283 | BUG_ON(!mem); | ||
284 | region_name = "PM"; | ||
285 | reg = mem->base + (offset * 3); | ||
286 | break; | ||
287 | case WMFW_ADSP1_DM: | ||
288 | BUG_ON(!mem); | ||
289 | region_name = "DM"; | ||
290 | reg = mem->base + (offset * 2); | ||
291 | break; | ||
292 | case WMFW_ADSP2_XM: | ||
293 | BUG_ON(!mem); | ||
294 | region_name = "XM"; | ||
295 | reg = mem->base + (offset * 2); | ||
296 | break; | ||
297 | case WMFW_ADSP2_YM: | ||
298 | BUG_ON(!mem); | ||
299 | region_name = "YM"; | ||
300 | reg = mem->base + (offset * 2); | ||
301 | break; | ||
302 | case WMFW_ADSP1_ZM: | ||
303 | BUG_ON(!mem); | ||
304 | region_name = "ZM"; | ||
305 | reg = mem->base + (offset * 2); | ||
306 | break; | ||
307 | default: | ||
308 | adsp_warn(dsp, | ||
309 | "%s.%d: Unknown region type %x at %d(%x)\n", | ||
310 | file, regions, type, pos, pos); | ||
311 | break; | ||
312 | } | ||
313 | |||
314 | adsp_dbg(dsp, "%s.%d: %d bytes at %d in %s\n", file, | ||
315 | regions, le32_to_cpu(region->len), offset, | ||
316 | region_name); | ||
317 | |||
318 | if (text) { | ||
319 | memcpy(text, region->data, le32_to_cpu(region->len)); | ||
320 | adsp_info(dsp, "%s: %s\n", file, text); | ||
321 | kfree(text); | ||
322 | } | ||
323 | |||
324 | if (reg) { | ||
325 | ret = regmap_raw_write(regmap, reg, region->data, | ||
326 | le32_to_cpu(region->len)); | ||
327 | if (ret != 0) { | ||
328 | adsp_err(dsp, | ||
329 | "%s.%d: Failed to write %d bytes at %d in %s: %d\n", | ||
330 | file, regions, | ||
331 | le32_to_cpu(region->len), offset, | ||
332 | region_name, ret); | ||
333 | goto out_fw; | ||
334 | } | ||
335 | } | ||
336 | |||
337 | pos += le32_to_cpu(region->len) + sizeof(*region); | ||
338 | regions++; | ||
339 | } | ||
340 | |||
341 | if (pos > firmware->size) | ||
342 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", | ||
343 | file, regions, pos - firmware->size); | ||
344 | |||
345 | out_fw: | ||
346 | release_firmware(firmware); | ||
347 | out: | ||
348 | kfree(file); | ||
349 | |||
350 | return ret; | ||
351 | } | ||
352 | |||
353 | static int wm_adsp_load_coeff(struct wm_adsp *dsp) | ||
354 | { | ||
355 | struct regmap *regmap = dsp->regmap; | ||
356 | struct wmfw_coeff_hdr *hdr; | ||
357 | struct wmfw_coeff_item *blk; | ||
358 | const struct firmware *firmware; | ||
359 | const char *region_name; | ||
360 | int ret, pos, blocks, type, offset, reg; | ||
361 | char *file; | ||
362 | |||
363 | file = kzalloc(PAGE_SIZE, GFP_KERNEL); | ||
364 | if (file == NULL) | ||
365 | return -ENOMEM; | ||
366 | |||
367 | snprintf(file, PAGE_SIZE, "%s-dsp%d.bin", dsp->part, dsp->num); | ||
368 | file[PAGE_SIZE - 1] = '\0'; | ||
369 | |||
370 | ret = request_firmware(&firmware, file, dsp->dev); | ||
371 | if (ret != 0) { | ||
372 | adsp_warn(dsp, "Failed to request '%s'\n", file); | ||
373 | ret = 0; | ||
374 | goto out; | ||
375 | } | ||
376 | ret = -EINVAL; | ||
377 | |||
378 | if (sizeof(*hdr) >= firmware->size) { | ||
379 | adsp_err(dsp, "%s: file too short, %zu bytes\n", | ||
380 | file, firmware->size); | ||
381 | goto out_fw; | ||
382 | } | ||
383 | |||
384 | hdr = (void*)&firmware->data[0]; | ||
385 | if (memcmp(hdr->magic, "WMDR", 4) != 0) { | ||
386 | adsp_err(dsp, "%s: invalid magic\n", file); | ||
387 | return -EINVAL; | ||
388 | } | ||
389 | |||
390 | adsp_dbg(dsp, "%s: v%d.%d.%d\n", file, | ||
391 | (le32_to_cpu(hdr->ver) >> 16) & 0xff, | ||
392 | (le32_to_cpu(hdr->ver) >> 8) & 0xff, | ||
393 | le32_to_cpu(hdr->ver) & 0xff); | ||
394 | |||
395 | pos = le32_to_cpu(hdr->len); | ||
396 | |||
397 | blocks = 0; | ||
398 | while (pos < firmware->size && | ||
399 | pos - firmware->size > sizeof(*blk)) { | ||
400 | blk = (void*)(&firmware->data[pos]); | ||
401 | |||
402 | type = be32_to_cpu(blk->type) & 0xff; | ||
403 | offset = le32_to_cpu(blk->offset) & 0xffffff; | ||
404 | |||
405 | adsp_dbg(dsp, "%s.%d: %x v%d.%d.%d\n", | ||
406 | file, blocks, le32_to_cpu(blk->id), | ||
407 | (le32_to_cpu(blk->ver) >> 16) & 0xff, | ||
408 | (le32_to_cpu(blk->ver) >> 8) & 0xff, | ||
409 | le32_to_cpu(blk->ver) & 0xff); | ||
410 | adsp_dbg(dsp, "%s.%d: %d bytes at 0x%x in %x\n", | ||
411 | file, blocks, le32_to_cpu(blk->len), offset, type); | ||
412 | |||
413 | reg = 0; | ||
414 | region_name = "Unknown"; | ||
415 | switch (type) { | ||
416 | case WMFW_NAME_TEXT: | ||
417 | case WMFW_INFO_TEXT: | ||
418 | break; | ||
419 | case WMFW_ABSOLUTE: | ||
420 | region_name = "register"; | ||
421 | reg = offset; | ||
422 | break; | ||
423 | default: | ||
424 | adsp_err(dsp, "Unknown region type %x\n", type); | ||
425 | break; | ||
426 | } | ||
427 | |||
428 | if (reg) { | ||
429 | ret = regmap_raw_write(regmap, reg, blk->data, | ||
430 | le32_to_cpu(blk->len)); | ||
431 | if (ret != 0) { | ||
432 | adsp_err(dsp, | ||
433 | "%s.%d: Failed to write to %x in %s\n", | ||
434 | file, blocks, reg, region_name); | ||
435 | } | ||
436 | } | ||
437 | |||
438 | pos += le32_to_cpu(blk->len) + sizeof(*blk); | ||
439 | blocks++; | ||
440 | } | ||
441 | |||
442 | if (pos > firmware->size) | ||
443 | adsp_warn(dsp, "%s.%d: %zu bytes at end of file\n", | ||
444 | file, blocks, pos - firmware->size); | ||
445 | |||
446 | out_fw: | ||
447 | release_firmware(firmware); | ||
448 | out: | ||
449 | kfree(file); | ||
450 | return 0; | ||
451 | } | ||
452 | |||
453 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, | ||
454 | struct snd_kcontrol *kcontrol, | ||
455 | int event) | ||
456 | { | ||
457 | struct snd_soc_codec *codec = w->codec; | ||
458 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | ||
459 | struct wm_adsp *dsp = &dsps[w->shift]; | ||
460 | int ret; | ||
461 | |||
462 | switch (event) { | ||
463 | case SND_SOC_DAPM_POST_PMU: | ||
464 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | ||
465 | ADSP1_SYS_ENA, ADSP1_SYS_ENA); | ||
466 | |||
467 | ret = wm_adsp_load(dsp); | ||
468 | if (ret != 0) | ||
469 | goto err; | ||
470 | |||
471 | ret = wm_adsp_load_coeff(dsp); | ||
472 | if (ret != 0) | ||
473 | goto err; | ||
474 | |||
475 | /* Start the core running */ | ||
476 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | ||
477 | ADSP1_CORE_ENA | ADSP1_START, | ||
478 | ADSP1_CORE_ENA | ADSP1_START); | ||
479 | break; | ||
480 | |||
481 | case SND_SOC_DAPM_PRE_PMD: | ||
482 | /* Halt the core */ | ||
483 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | ||
484 | ADSP1_CORE_ENA | ADSP1_START, 0); | ||
485 | |||
486 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_19, | ||
487 | ADSP1_WDMA_BUFFER_LENGTH_MASK, 0); | ||
488 | |||
489 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | ||
490 | ADSP1_SYS_ENA, 0); | ||
491 | break; | ||
492 | |||
493 | default: | ||
494 | break; | ||
495 | } | ||
496 | |||
497 | return 0; | ||
498 | |||
499 | err: | ||
500 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | ||
501 | ADSP1_SYS_ENA, 0); | ||
502 | return ret; | ||
503 | } | ||
504 | EXPORT_SYMBOL_GPL(wm_adsp1_event); | ||
505 | |||
506 | static int wm_adsp2_ena(struct wm_adsp *dsp) | ||
507 | { | ||
508 | unsigned int val; | ||
509 | int ret, count; | ||
510 | |||
511 | ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | ||
512 | ADSP2_SYS_ENA, ADSP2_SYS_ENA); | ||
513 | if (ret != 0) | ||
514 | return ret; | ||
515 | |||
516 | /* Wait for the RAM to start, should be near instantaneous */ | ||
517 | count = 0; | ||
518 | do { | ||
519 | ret = regmap_read(dsp->regmap, dsp->base + ADSP2_STATUS1, | ||
520 | &val); | ||
521 | if (ret != 0) | ||
522 | return ret; | ||
523 | } while (!(val & ADSP2_RAM_RDY) && ++count < 10); | ||
524 | |||
525 | if (!(val & ADSP2_RAM_RDY)) { | ||
526 | adsp_err(dsp, "Failed to start DSP RAM\n"); | ||
527 | return -EBUSY; | ||
528 | } | ||
529 | |||
530 | adsp_dbg(dsp, "RAM ready after %d polls\n", count); | ||
531 | adsp_info(dsp, "RAM ready after %d polls\n", count); | ||
532 | |||
533 | return 0; | ||
534 | } | ||
535 | |||
536 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | ||
537 | struct snd_kcontrol *kcontrol, int event) | ||
538 | { | ||
539 | struct snd_soc_codec *codec = w->codec; | ||
540 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | ||
541 | struct wm_adsp *dsp = &dsps[w->shift]; | ||
542 | unsigned int val; | ||
543 | int ret; | ||
544 | |||
545 | switch (event) { | ||
546 | case SND_SOC_DAPM_POST_PMU: | ||
547 | /* | ||
548 | * For simplicity set the DSP clock rate to be the | ||
549 | * SYSCLK rate rather than making it configurable. | ||
550 | */ | ||
551 | ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); | ||
552 | if (ret != 0) { | ||
553 | adsp_err(dsp, "Failed to read SYSCLK state: %d\n", | ||
554 | ret); | ||
555 | return ret; | ||
556 | } | ||
557 | val = (val & ARIZONA_SYSCLK_FREQ_MASK) | ||
558 | >> ARIZONA_SYSCLK_FREQ_SHIFT; | ||
559 | |||
560 | ret = regmap_update_bits(dsp->regmap, | ||
561 | dsp->base + ADSP2_CLOCKING, | ||
562 | ADSP2_CLK_SEL_MASK, val); | ||
563 | if (ret != 0) { | ||
564 | adsp_err(dsp, "Failed to set clock rate: %d\n", | ||
565 | ret); | ||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | if (dsp->dvfs) { | ||
570 | ret = regmap_read(dsp->regmap, | ||
571 | dsp->base + ADSP2_CLOCKING, &val); | ||
572 | if (ret != 0) { | ||
573 | dev_err(dsp->dev, | ||
574 | "Failed to read clocking: %d\n", ret); | ||
575 | return ret; | ||
576 | } | ||
577 | |||
578 | if ((val & ADSP2_CLK_SEL_MASK) >= 3) { | ||
579 | ret = regulator_enable(dsp->dvfs); | ||
580 | if (ret != 0) { | ||
581 | dev_err(dsp->dev, | ||
582 | "Failed to enable supply: %d\n", | ||
583 | ret); | ||
584 | return ret; | ||
585 | } | ||
586 | |||
587 | ret = regulator_set_voltage(dsp->dvfs, | ||
588 | 1800000, | ||
589 | 1800000); | ||
590 | if (ret != 0) { | ||
591 | dev_err(dsp->dev, | ||
592 | "Failed to raise supply: %d\n", | ||
593 | ret); | ||
594 | return ret; | ||
595 | } | ||
596 | } | ||
597 | } | ||
598 | |||
599 | ret = wm_adsp2_ena(dsp); | ||
600 | if (ret != 0) | ||
601 | return ret; | ||
602 | |||
603 | ret = wm_adsp_load(dsp); | ||
604 | if (ret != 0) | ||
605 | goto err; | ||
606 | |||
607 | ret = wm_adsp_load_coeff(dsp); | ||
608 | if (ret != 0) | ||
609 | goto err; | ||
610 | |||
611 | ret = regmap_update_bits(dsp->regmap, | ||
612 | dsp->base + ADSP2_CONTROL, | ||
613 | ADSP2_CORE_ENA | ADSP2_START, | ||
614 | ADSP2_CORE_ENA | ADSP2_START); | ||
615 | if (ret != 0) | ||
616 | goto err; | ||
617 | break; | ||
618 | |||
619 | case SND_SOC_DAPM_PRE_PMD: | ||
620 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | ||
621 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | | ||
622 | ADSP2_START, 0); | ||
623 | |||
624 | if (dsp->dvfs) { | ||
625 | ret = regulator_set_voltage(dsp->dvfs, 1200000, | ||
626 | 1800000); | ||
627 | if (ret != 0) | ||
628 | dev_warn(dsp->dev, | ||
629 | "Failed to lower supply: %d\n", | ||
630 | ret); | ||
631 | |||
632 | ret = regulator_disable(dsp->dvfs); | ||
633 | if (ret != 0) | ||
634 | dev_err(dsp->dev, | ||
635 | "Failed to enable supply: %d\n", | ||
636 | ret); | ||
637 | } | ||
638 | break; | ||
639 | |||
640 | default: | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | return 0; | ||
645 | err: | ||
646 | regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, | ||
647 | ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0); | ||
648 | return ret; | ||
649 | } | ||
650 | EXPORT_SYMBOL_GPL(wm_adsp2_event); | ||
651 | |||
652 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | ||
653 | { | ||
654 | int ret; | ||
655 | |||
656 | /* | ||
657 | * Disable the DSP memory by default when in reset for a small | ||
658 | * power saving. | ||
659 | */ | ||
660 | ret = regmap_update_bits(adsp->regmap, adsp->base + ADSP2_CONTROL, | ||
661 | ADSP2_MEM_ENA, 0); | ||
662 | if (ret != 0) { | ||
663 | adsp_err(adsp, "Failed to clear memory retention: %d\n", ret); | ||
664 | return ret; | ||
665 | } | ||
666 | |||
667 | if (dvfs) { | ||
668 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | ||
669 | if (IS_ERR(adsp->dvfs)) { | ||
670 | ret = PTR_ERR(adsp->dvfs); | ||
671 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | ret = regulator_enable(adsp->dvfs); | ||
676 | if (ret != 0) { | ||
677 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", | ||
678 | ret); | ||
679 | return ret; | ||
680 | } | ||
681 | |||
682 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); | ||
683 | if (ret != 0) { | ||
684 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", | ||
685 | ret); | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | ret = regulator_disable(adsp->dvfs); | ||
690 | if (ret != 0) { | ||
691 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", | ||
692 | ret); | ||
693 | return ret; | ||
694 | } | ||
695 | } | ||
696 | |||
697 | return 0; | ||
698 | } | ||
699 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | ||
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h new file mode 100644 index 000000000000..ffd29a4609e2 --- /dev/null +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -0,0 +1,59 @@ | |||
1 | /* | ||
2 | * wm_adsp.h -- Wolfson ADSP support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __WM_ADSP_H | ||
14 | #define __WM_ADSP_H | ||
15 | |||
16 | #include <sound/soc.h> | ||
17 | #include <sound/soc-dapm.h> | ||
18 | |||
19 | #include "wmfw.h" | ||
20 | |||
21 | struct regulator; | ||
22 | |||
23 | struct wm_adsp_region { | ||
24 | int type; | ||
25 | unsigned int base; | ||
26 | }; | ||
27 | |||
28 | struct wm_adsp { | ||
29 | const char *part; | ||
30 | int num; | ||
31 | int type; | ||
32 | struct device *dev; | ||
33 | struct regmap *regmap; | ||
34 | |||
35 | int base; | ||
36 | |||
37 | const struct wm_adsp_region *mem; | ||
38 | int num_mems; | ||
39 | |||
40 | struct regulator *dvfs; | ||
41 | }; | ||
42 | |||
43 | #define WM_ADSP1(wname, num) \ | ||
44 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | ||
45 | .shift = num, .event = wm_adsp1_event, \ | ||
46 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
47 | |||
48 | #define WM_ADSP2(wname, num) \ | ||
49 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | ||
50 | .shift = num, .event = wm_adsp2_event, \ | ||
51 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
52 | |||
53 | int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs); | ||
54 | int wm_adsp1_event(struct snd_soc_dapm_widget *w, | ||
55 | struct snd_kcontrol *kcontrol, int event); | ||
56 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | ||
57 | struct snd_kcontrol *kcontrol, int event); | ||
58 | |||
59 | #endif | ||
diff --git a/sound/soc/codecs/wmfw.h b/sound/soc/codecs/wmfw.h new file mode 100644 index 000000000000..5632ded67fdd --- /dev/null +++ b/sound/soc/codecs/wmfw.h | |||
@@ -0,0 +1,128 @@ | |||
1 | /* | ||
2 | * wmfw.h - Wolfson firmware format information | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #ifndef __WMFW_H | ||
14 | #define __WMFW_H | ||
15 | |||
16 | #include <linux/types.h> | ||
17 | |||
18 | struct wmfw_header { | ||
19 | char magic[4]; | ||
20 | __le32 len; | ||
21 | __le16 rev; | ||
22 | u8 core; | ||
23 | u8 ver; | ||
24 | } __packed; | ||
25 | |||
26 | struct wmfw_footer { | ||
27 | __le64 timestamp; | ||
28 | __le32 checksum; | ||
29 | } __packed; | ||
30 | |||
31 | struct wmfw_adsp1_sizes { | ||
32 | __le32 dm; | ||
33 | __le32 pm; | ||
34 | __le32 zm; | ||
35 | } __packed; | ||
36 | |||
37 | struct wmfw_adsp2_sizes { | ||
38 | __le32 xm; | ||
39 | __le32 ym; | ||
40 | __le32 pm; | ||
41 | __le32 zm; | ||
42 | } __packed; | ||
43 | |||
44 | struct wmfw_region { | ||
45 | union { | ||
46 | __be32 type; | ||
47 | __le32 offset; | ||
48 | }; | ||
49 | __le32 len; | ||
50 | u8 data[]; | ||
51 | } __packed; | ||
52 | |||
53 | struct wmfw_id_hdr { | ||
54 | __be32 core_id; | ||
55 | __be32 core_rev; | ||
56 | __be32 id; | ||
57 | __be32 ver; | ||
58 | } __packed; | ||
59 | |||
60 | struct wmfw_adsp1_id_hdr { | ||
61 | struct wmfw_id_hdr fw; | ||
62 | __be32 zm; | ||
63 | __be32 dm; | ||
64 | __be32 algs; | ||
65 | } __packed; | ||
66 | |||
67 | struct wmfw_adsp2_id_hdr { | ||
68 | struct wmfw_id_hdr fw; | ||
69 | __be32 zm; | ||
70 | __be32 xm; | ||
71 | __be32 ym; | ||
72 | __be32 algs; | ||
73 | } __packed; | ||
74 | |||
75 | struct wmfw_alg_hdr { | ||
76 | __be32 id; | ||
77 | __be32 ver; | ||
78 | } __packed; | ||
79 | |||
80 | struct wmfw_adsp1_alg_hdr { | ||
81 | struct wmfw_alg_hdr alg; | ||
82 | __be32 zm; | ||
83 | __be32 dm; | ||
84 | } __packed; | ||
85 | |||
86 | struct wmfw_adsp2_alg_hdr { | ||
87 | struct wmfw_alg_hdr alg; | ||
88 | __be32 zm; | ||
89 | __be32 xm; | ||
90 | __be32 ym; | ||
91 | } __packed; | ||
92 | |||
93 | struct wmfw_coeff_hdr { | ||
94 | u8 magic[4]; | ||
95 | __le32 len; | ||
96 | __le32 ver; | ||
97 | u8 data[]; | ||
98 | } __packed; | ||
99 | |||
100 | struct wmfw_coeff_item { | ||
101 | union { | ||
102 | __be32 type; | ||
103 | __le32 offset; | ||
104 | }; | ||
105 | __le32 id; | ||
106 | __le32 ver; | ||
107 | __le32 sr; | ||
108 | __le32 len; | ||
109 | u8 data[]; | ||
110 | } __packed; | ||
111 | |||
112 | #define WMFW_ADSP1 1 | ||
113 | #define WMFW_ADSP2 2 | ||
114 | |||
115 | #define WMFW_ABSOLUTE 0xf0 | ||
116 | #define WMFW_NAME_TEXT 0xfe | ||
117 | #define WMFW_INFO_TEXT 0xff | ||
118 | |||
119 | #define WMFW_ADSP1_PM 2 | ||
120 | #define WMFW_ADSP1_DM 3 | ||
121 | #define WMFW_ADSP1_ZM 4 | ||
122 | |||
123 | #define WMFW_ADSP2_PM 2 | ||
124 | #define WMFW_ADSP2_ZM 4 | ||
125 | #define WMFW_ADSP2_XM 5 | ||
126 | #define WMFW_ADSP2_YM 6 | ||
127 | |||
128 | #endif | ||