diff options
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/au1x/ac97c.c | 21 | ||||
-rw-r--r-- | sound/soc/au1x/psc-ac97.c | 33 | ||||
-rw-r--r-- | sound/soc/blackfin/bf5xx-ac97.c | 29 | ||||
-rw-r--r-- | sound/soc/cirrus/ep93xx-ac97.c | 12 | ||||
-rw-r--r-- | sound/soc/codecs/ac97.c | 7 | ||||
-rw-r--r-- | sound/soc/codecs/ad1980.c | 12 | ||||
-rw-r--r-- | sound/soc/codecs/adau1701.c | 321 | ||||
-rw-r--r-- | sound/soc/codecs/stac9766.c | 26 | ||||
-rw-r--r-- | sound/soc/codecs/wm9705.c | 16 | ||||
-rw-r--r-- | sound/soc/codecs/wm9712.c | 18 | ||||
-rw-r--r-- | sound/soc/codecs/wm9713.c | 18 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 459 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.h | 3 | ||||
-rw-r--r-- | sound/soc/fsl/imx-ssi.c | 11 | ||||
-rw-r--r-- | sound/soc/fsl/mpc5200_psc_ac97.c | 10 | ||||
-rw-r--r-- | sound/soc/nuc900/nuc900-ac97.c | 60 | ||||
-rw-r--r-- | sound/soc/pxa/pxa2xx-ac97.c | 10 | ||||
-rw-r--r-- | sound/soc/pxa/pxa2xx-ac97.h | 3 | ||||
-rw-r--r-- | sound/soc/samsung/ac97.c | 42 | ||||
-rw-r--r-- | sound/soc/sh/hac.c | 8 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 17 | ||||
-rw-r--r-- | sound/soc/tegra/tegra20_ac97.c | 67 | ||||
-rw-r--r-- | sound/soc/txx9/txx9aclc-ac97.c | 17 |
23 files changed, 935 insertions, 285 deletions
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index 44b8dcecf571..d6f7694fcad4 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c | |||
@@ -179,13 +179,12 @@ static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) | |||
179 | } | 179 | } |
180 | 180 | ||
181 | /* AC97 controller operations */ | 181 | /* AC97 controller operations */ |
182 | struct snd_ac97_bus_ops soc_ac97_ops = { | 182 | static struct snd_ac97_bus_ops ac97c_bus_ops = { |
183 | .read = au1xac97c_ac97_read, | 183 | .read = au1xac97c_ac97_read, |
184 | .write = au1xac97c_ac97_write, | 184 | .write = au1xac97c_ac97_write, |
185 | .reset = au1xac97c_ac97_cold_reset, | 185 | .reset = au1xac97c_ac97_cold_reset, |
186 | .warm_reset = au1xac97c_ac97_warm_reset, | 186 | .warm_reset = au1xac97c_ac97_warm_reset, |
187 | }; | 187 | }; |
188 | EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ | ||
189 | 188 | ||
190 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, | 189 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, |
191 | struct snd_soc_dai *dai) | 190 | struct snd_soc_dai *dai) |
@@ -272,6 +271,10 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) | |||
272 | 271 | ||
273 | platform_set_drvdata(pdev, ctx); | 272 | platform_set_drvdata(pdev, ctx); |
274 | 273 | ||
274 | ret = snd_soc_set_ac97_ops(&ac97c_bus_ops); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
275 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, | 278 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, |
276 | &au1xac97c_dai_driver, 1); | 279 | &au1xac97c_dai_driver, 1); |
277 | if (ret) | 280 | if (ret) |
@@ -338,19 +341,7 @@ static struct platform_driver au1xac97c_driver = { | |||
338 | .remove = au1xac97c_drvremove, | 341 | .remove = au1xac97c_drvremove, |
339 | }; | 342 | }; |
340 | 343 | ||
341 | static int __init au1xac97c_load(void) | 344 | module_platform_driver(&au1xac97c_driver); |
342 | { | ||
343 | ac97c_workdata = NULL; | ||
344 | return platform_driver_register(&au1xac97c_driver); | ||
345 | } | ||
346 | |||
347 | static void __exit au1xac97c_unload(void) | ||
348 | { | ||
349 | platform_driver_unregister(&au1xac97c_driver); | ||
350 | } | ||
351 | |||
352 | module_init(au1xac97c_load); | ||
353 | module_exit(au1xac97c_unload); | ||
354 | 345 | ||
355 | MODULE_LICENSE("GPL"); | 346 | MODULE_LICENSE("GPL"); |
356 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); | 347 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 8f1862aa7333..a822ab822bb7 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -201,13 +201,12 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
201 | } | 201 | } |
202 | 202 | ||
203 | /* AC97 controller operations */ | 203 | /* AC97 controller operations */ |
204 | struct snd_ac97_bus_ops soc_ac97_ops = { | 204 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
205 | .read = au1xpsc_ac97_read, | 205 | .read = au1xpsc_ac97_read, |
206 | .write = au1xpsc_ac97_write, | 206 | .write = au1xpsc_ac97_write, |
207 | .reset = au1xpsc_ac97_cold_reset, | 207 | .reset = au1xpsc_ac97_cold_reset, |
208 | .warm_reset = au1xpsc_ac97_warm_reset, | 208 | .warm_reset = au1xpsc_ac97_warm_reset, |
209 | }; | 209 | }; |
210 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
211 | 210 | ||
212 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | 211 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, |
213 | struct snd_pcm_hw_params *params, | 212 | struct snd_pcm_hw_params *params, |
@@ -383,15 +382,9 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
383 | if (!iores) | 382 | if (!iores) |
384 | return -ENODEV; | 383 | return -ENODEV; |
385 | 384 | ||
386 | if (!devm_request_mem_region(&pdev->dev, iores->start, | 385 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); |
387 | resource_size(iores), | 386 | if (IS_ERR(wd->mmio)) |
388 | pdev->name)) | 387 | return PTR_ERR(wd->mmio); |
389 | return -EBUSY; | ||
390 | |||
391 | wd->mmio = devm_ioremap(&pdev->dev, iores->start, | ||
392 | resource_size(iores)); | ||
393 | if (!wd->mmio) | ||
394 | return -EBUSY; | ||
395 | 388 | ||
396 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 389 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
397 | if (!dmares) | 390 | if (!dmares) |
@@ -423,6 +416,10 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
423 | 416 | ||
424 | platform_set_drvdata(pdev, wd); | 417 | platform_set_drvdata(pdev, wd); |
425 | 418 | ||
419 | ret = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
420 | if (ret) | ||
421 | return ret; | ||
422 | |||
426 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, | 423 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, |
427 | &wd->dai_drv, 1); | 424 | &wd->dai_drv, 1); |
428 | if (ret) | 425 | if (ret) |
@@ -503,19 +500,7 @@ static struct platform_driver au1xpsc_ac97_driver = { | |||
503 | .remove = au1xpsc_ac97_drvremove, | 500 | .remove = au1xpsc_ac97_drvremove, |
504 | }; | 501 | }; |
505 | 502 | ||
506 | static int __init au1xpsc_ac97_load(void) | 503 | module_platform_driver(au1xpsc_ac97_driver); |
507 | { | ||
508 | au1xpsc_ac97_workdata = NULL; | ||
509 | return platform_driver_register(&au1xpsc_ac97_driver); | ||
510 | } | ||
511 | |||
512 | static void __exit au1xpsc_ac97_unload(void) | ||
513 | { | ||
514 | platform_driver_unregister(&au1xpsc_ac97_driver); | ||
515 | } | ||
516 | |||
517 | module_init(au1xpsc_ac97_load); | ||
518 | module_exit(au1xpsc_ac97_unload); | ||
519 | 504 | ||
520 | MODULE_LICENSE("GPL"); | 505 | MODULE_LICENSE("GPL"); |
521 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); | 506 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index 490217325975..c5af677ba49c 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -198,13 +198,12 @@ static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
198 | #endif | 198 | #endif |
199 | } | 199 | } |
200 | 200 | ||
201 | struct snd_ac97_bus_ops soc_ac97_ops = { | 201 | static struct snd_ac97_bus_ops bf5xx_ac97_ops = { |
202 | .read = bf5xx_ac97_read, | 202 | .read = bf5xx_ac97_read, |
203 | .write = bf5xx_ac97_write, | 203 | .write = bf5xx_ac97_write, |
204 | .warm_reset = bf5xx_ac97_warm_reset, | 204 | .warm_reset = bf5xx_ac97_warm_reset, |
205 | .reset = bf5xx_ac97_cold_reset, | 205 | .reset = bf5xx_ac97_cold_reset, |
206 | }; | 206 | }; |
207 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
208 | 207 | ||
209 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
210 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) | 209 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
@@ -293,13 +292,14 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
293 | 292 | ||
294 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 293 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
295 | /* Request PB3 as reset pin */ | 294 | /* Request PB3 as reset pin */ |
296 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 295 | ret = devm_gpio_request_one(&pdev->dev, |
297 | pr_err("Failed to request GPIO_%d for reset\n", | 296 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, |
298 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 297 | GPIOF_OUT_INIT_HIGH, "SND_AD198x RESET") { |
299 | ret = -1; | 298 | dev_err(&pdev->dev, |
299 | "Failed to request GPIO_%d for reset: %d\n", | ||
300 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, ret); | ||
300 | goto gpio_err; | 301 | goto gpio_err; |
301 | } | 302 | } |
302 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | ||
303 | #endif | 303 | #endif |
304 | 304 | ||
305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), | 305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), |
@@ -335,6 +335,12 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
335 | goto sport_config_err; | 335 | goto sport_config_err; |
336 | } | 336 | } |
337 | 337 | ||
338 | ret = snd_soc_set_ac97_ops(&bf5xx_ac97_ops); | ||
339 | if (ret != 0) { | ||
340 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
341 | goto sport_config_err; | ||
342 | } | ||
343 | |||
338 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, | 344 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, |
339 | &bfin_ac97_dai, 1); | 345 | &bfin_ac97_dai, 1); |
340 | if (ret) { | 346 | if (ret) { |
@@ -349,10 +355,7 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
349 | sport_config_err: | 355 | sport_config_err: |
350 | sport_done(sport_handle); | 356 | sport_done(sport_handle); |
351 | sport_err: | 357 | sport_err: |
352 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 358 | snd_soc_set_ac97_ops(NULL); |
353 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
354 | gpio_err: | ||
355 | #endif | ||
356 | 359 | ||
357 | return ret; | 360 | return ret; |
358 | } | 361 | } |
@@ -363,9 +366,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev) | |||
363 | 366 | ||
364 | snd_soc_unregister_component(&pdev->dev); | 367 | snd_soc_unregister_component(&pdev->dev); |
365 | sport_done(sport_handle); | 368 | sport_done(sport_handle); |
366 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 369 | snd_soc_set_ac97_ops(NULL); |
367 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
368 | #endif | ||
369 | 370 | ||
370 | return 0; | 371 | return 0; |
371 | } | 372 | } |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 7798fbd5e81d..4bc9490e2c84 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -237,13 +237,12 @@ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) | |||
237 | return IRQ_HANDLED; | 237 | return IRQ_HANDLED; |
238 | } | 238 | } |
239 | 239 | ||
240 | struct snd_ac97_bus_ops soc_ac97_ops = { | 240 | static struct snd_ac97_bus_ops ep93xx_ac97_ops = { |
241 | .read = ep93xx_ac97_read, | 241 | .read = ep93xx_ac97_read, |
242 | .write = ep93xx_ac97_write, | 242 | .write = ep93xx_ac97_write, |
243 | .reset = ep93xx_ac97_cold_reset, | 243 | .reset = ep93xx_ac97_cold_reset, |
244 | .warm_reset = ep93xx_ac97_warm_reset, | 244 | .warm_reset = ep93xx_ac97_warm_reset, |
245 | }; | 245 | }; |
246 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
247 | 246 | ||
248 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | 247 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, |
249 | int cmd, struct snd_soc_dai *dai) | 248 | int cmd, struct snd_soc_dai *dai) |
@@ -395,6 +394,10 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
395 | ep93xx_ac97_info = info; | 394 | ep93xx_ac97_info = info; |
396 | platform_set_drvdata(pdev, info); | 395 | platform_set_drvdata(pdev, info); |
397 | 396 | ||
397 | ret = snd_soc_set_ac97_ops(&ep93xx_ac97_ops); | ||
398 | if (ret) | ||
399 | goto fail; | ||
400 | |||
398 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, | 401 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, |
399 | &ep93xx_ac97_dai, 1); | 402 | &ep93xx_ac97_dai, 1); |
400 | if (ret) | 403 | if (ret) |
@@ -405,7 +408,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
405 | fail: | 408 | fail: |
406 | platform_set_drvdata(pdev, NULL); | 409 | platform_set_drvdata(pdev, NULL); |
407 | ep93xx_ac97_info = NULL; | 410 | ep93xx_ac97_info = NULL; |
408 | dev_set_drvdata(&pdev->dev, NULL); | 411 | snd_soc_set_ac97_ops(NULL); |
409 | return ret; | 412 | return ret; |
410 | } | 413 | } |
411 | 414 | ||
@@ -420,7 +423,8 @@ static int ep93xx_ac97_remove(struct platform_device *pdev) | |||
420 | 423 | ||
421 | platform_set_drvdata(pdev, NULL); | 424 | platform_set_drvdata(pdev, NULL); |
422 | ep93xx_ac97_info = NULL; | 425 | ep93xx_ac97_info = NULL; |
423 | dev_set_drvdata(&pdev->dev, NULL); | 426 | |
427 | snd_soc_set_ac97_ops(NULL); | ||
424 | 428 | ||
425 | return 0; | 429 | return 0; |
426 | } | 430 | } |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index ef2ae32ffc66..ec7351803c24 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
62 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 62 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
63 | unsigned int reg) | 63 | unsigned int reg) |
64 | { | 64 | { |
65 | return soc_ac97_ops.read(codec->ac97, reg); | 65 | return soc_ac97_ops->read(codec->ac97, reg); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
69 | unsigned int val) | 69 | unsigned int val) |
70 | { | 70 | { |
71 | soc_ac97_ops.write(codec->ac97, reg, val); | 71 | soc_ac97_ops->write(codec->ac97, reg, val); |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
@@ -79,7 +79,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
79 | int ret; | 79 | int ret; |
80 | 80 | ||
81 | /* add codec as bus device for standard ac97 */ | 81 | /* add codec as bus device for standard ac97 */ |
82 | ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); | 82 | ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL, |
83 | &ac97_bus); | ||
83 | if (ret < 0) | 84 | if (ret < 0) |
84 | return ret; | 85 | return ret; |
85 | 86 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index f385342947d3..89fcf7d6e7b8 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -108,7 +108,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
108 | case AC97_EXTENDED_STATUS: | 108 | case AC97_EXTENDED_STATUS: |
109 | case AC97_VENDOR_ID1: | 109 | case AC97_VENDOR_ID1: |
110 | case AC97_VENDOR_ID2: | 110 | case AC97_VENDOR_ID2: |
111 | return soc_ac97_ops.read(codec->ac97, reg); | 111 | return soc_ac97_ops->read(codec->ac97, reg); |
112 | default: | 112 | default: |
113 | reg = reg >> 1; | 113 | reg = reg >> 1; |
114 | 114 | ||
@@ -124,7 +124,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
124 | { | 124 | { |
125 | u16 *cache = codec->reg_cache; | 125 | u16 *cache = codec->reg_cache; |
126 | 126 | ||
127 | soc_ac97_ops.write(codec->ac97, reg, val); | 127 | soc_ac97_ops->write(codec->ac97, reg, val); |
128 | reg = reg >> 1; | 128 | reg = reg >> 1; |
129 | if (reg < ARRAY_SIZE(ad1980_reg)) | 129 | if (reg < ARRAY_SIZE(ad1980_reg)) |
130 | cache[reg] = val; | 130 | cache[reg] = val; |
@@ -154,13 +154,13 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | |||
154 | u16 retry_cnt = 0; | 154 | u16 retry_cnt = 0; |
155 | 155 | ||
156 | retry: | 156 | retry: |
157 | if (try_warm && soc_ac97_ops.warm_reset) { | 157 | if (try_warm && soc_ac97_ops->warm_reset) { |
158 | soc_ac97_ops.warm_reset(codec->ac97); | 158 | soc_ac97_ops->warm_reset(codec->ac97); |
159 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 159 | if (ac97_read(codec, AC97_RESET) == 0x0090) |
160 | return 1; | 160 | return 1; |
161 | } | 161 | } |
162 | 162 | ||
163 | soc_ac97_ops.reset(codec->ac97); | 163 | soc_ac97_ops->reset(codec->ac97); |
164 | /* Set bit 16slot in register 74h, then every slot will has only 16 | 164 | /* Set bit 16slot in register 74h, then every slot will has only 16 |
165 | * bits. This command is sent out in 20bit mode, in which case the | 165 | * bits. This command is sent out in 20bit mode, in which case the |
166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ | 166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ |
@@ -186,7 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
186 | 186 | ||
187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
188 | 188 | ||
189 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 189 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
190 | if (ret < 0) { | 190 | if (ret < 0) { |
191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
192 | return ret; | 192 | return ret; |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index dafdbe87edeb..d1124a5b3471 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -13,6 +13,10 @@ | |||
13 | #include <linux/i2c.h> | 13 | #include <linux/i2c.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/of.h> | ||
17 | #include <linux/of_gpio.h> | ||
18 | #include <linux/of_device.h> | ||
19 | #include <linux/regmap.h> | ||
16 | #include <sound/core.h> | 20 | #include <sound/core.h> |
17 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
18 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -21,16 +25,19 @@ | |||
21 | #include "sigmadsp.h" | 25 | #include "sigmadsp.h" |
22 | #include "adau1701.h" | 26 | #include "adau1701.h" |
23 | 27 | ||
24 | #define ADAU1701_DSPCTRL 0x1c | 28 | #define ADAU1701_DSPCTRL 0x081c |
25 | #define ADAU1701_SEROCTL 0x1e | 29 | #define ADAU1701_SEROCTL 0x081e |
26 | #define ADAU1701_SERICTL 0x1f | 30 | #define ADAU1701_SERICTL 0x081f |
27 | 31 | ||
28 | #define ADAU1701_AUXNPOW 0x22 | 32 | #define ADAU1701_AUXNPOW 0x0822 |
33 | #define ADAU1701_PINCONF_0 0x0820 | ||
34 | #define ADAU1701_PINCONF_1 0x0821 | ||
35 | #define ADAU1701_AUXNPOW 0x0822 | ||
29 | 36 | ||
30 | #define ADAU1701_OSCIPOW 0x26 | 37 | #define ADAU1701_OSCIPOW 0x0826 |
31 | #define ADAU1701_DACSET 0x27 | 38 | #define ADAU1701_DACSET 0x0827 |
32 | 39 | ||
33 | #define ADAU1701_NUM_REGS 0x28 | 40 | #define ADAU1701_MAX_REGISTER 0x0828 |
34 | 41 | ||
35 | #define ADAU1701_DSPCTRL_CR (1 << 2) | 42 | #define ADAU1701_DSPCTRL_CR (1 << 2) |
36 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | 43 | #define ADAU1701_DSPCTRL_DAM (1 << 3) |
@@ -84,10 +91,18 @@ | |||
84 | #define ADAU1701_OSCIPOW_OPD 0x04 | 91 | #define ADAU1701_OSCIPOW_OPD 0x04 |
85 | #define ADAU1701_DACSET_DACINIT 1 | 92 | #define ADAU1701_DACSET_DACINIT 1 |
86 | 93 | ||
94 | #define ADAU1707_CLKDIV_UNSET (-1UL) | ||
95 | |||
87 | #define ADAU1701_FIRMWARE "adau1701.bin" | 96 | #define ADAU1701_FIRMWARE "adau1701.bin" |
88 | 97 | ||
89 | struct adau1701 { | 98 | struct adau1701 { |
99 | int gpio_nreset; | ||
100 | int gpio_pll_mode[2]; | ||
90 | unsigned int dai_fmt; | 101 | unsigned int dai_fmt; |
102 | unsigned int pll_clkdiv; | ||
103 | unsigned int sysclk; | ||
104 | struct regmap *regmap; | ||
105 | u8 pin_config[12]; | ||
91 | }; | 106 | }; |
92 | 107 | ||
93 | static const struct snd_kcontrol_new adau1701_controls[] = { | 108 | static const struct snd_kcontrol_new adau1701_controls[] = { |
@@ -119,10 +134,13 @@ static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { | |||
119 | { "ADC", NULL, "IN1" }, | 134 | { "ADC", NULL, "IN1" }, |
120 | }; | 135 | }; |
121 | 136 | ||
122 | static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | 137 | static unsigned int adau1701_register_size(struct device *dev, |
123 | unsigned int reg) | 138 | unsigned int reg) |
124 | { | 139 | { |
125 | switch (reg) { | 140 | switch (reg) { |
141 | case ADAU1701_PINCONF_0: | ||
142 | case ADAU1701_PINCONF_1: | ||
143 | return 3; | ||
126 | case ADAU1701_DSPCTRL: | 144 | case ADAU1701_DSPCTRL: |
127 | case ADAU1701_SEROCTL: | 145 | case ADAU1701_SEROCTL: |
128 | case ADAU1701_AUXNPOW: | 146 | case ADAU1701_AUXNPOW: |
@@ -133,33 +151,42 @@ static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | |||
133 | return 1; | 151 | return 1; |
134 | } | 152 | } |
135 | 153 | ||
136 | dev_err(codec->dev, "Unsupported register address: %d\n", reg); | 154 | dev_err(dev, "Unsupported register address: %d\n", reg); |
137 | return 0; | 155 | return 0; |
138 | } | 156 | } |
139 | 157 | ||
140 | static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | 158 | static bool adau1701_volatile_reg(struct device *dev, unsigned int reg) |
141 | unsigned int value) | 159 | { |
160 | switch (reg) { | ||
161 | case ADAU1701_DACSET: | ||
162 | return true; | ||
163 | default: | ||
164 | return false; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static int adau1701_reg_write(void *context, unsigned int reg, | ||
169 | unsigned int value) | ||
142 | { | 170 | { |
171 | struct i2c_client *client = context; | ||
143 | unsigned int i; | 172 | unsigned int i; |
144 | unsigned int size; | 173 | unsigned int size; |
145 | uint8_t buf[4]; | 174 | uint8_t buf[5]; |
146 | int ret; | 175 | int ret; |
147 | 176 | ||
148 | size = adau1701_register_size(codec, reg); | 177 | size = adau1701_register_size(&client->dev, reg); |
149 | if (size == 0) | 178 | if (size == 0) |
150 | return -EINVAL; | 179 | return -EINVAL; |
151 | 180 | ||
152 | snd_soc_cache_write(codec, reg, value); | 181 | buf[0] = reg >> 8; |
153 | 182 | buf[1] = reg & 0xff; | |
154 | buf[0] = 0x08; | ||
155 | buf[1] = reg; | ||
156 | 183 | ||
157 | for (i = size + 1; i >= 2; --i) { | 184 | for (i = size + 1; i >= 2; --i) { |
158 | buf[i] = value; | 185 | buf[i] = value; |
159 | value >>= 8; | 186 | value >>= 8; |
160 | } | 187 | } |
161 | 188 | ||
162 | ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); | 189 | ret = i2c_master_send(client, buf, size + 2); |
163 | if (ret == size + 2) | 190 | if (ret == size + 2) |
164 | return 0; | 191 | return 0; |
165 | else if (ret < 0) | 192 | else if (ret < 0) |
@@ -168,21 +195,107 @@ static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | |||
168 | return -EIO; | 195 | return -EIO; |
169 | } | 196 | } |
170 | 197 | ||
171 | static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) | 198 | static int adau1701_reg_read(void *context, unsigned int reg, |
199 | unsigned int *value) | ||
172 | { | 200 | { |
173 | unsigned int value; | 201 | int ret; |
174 | unsigned int ret; | 202 | unsigned int i; |
203 | unsigned int size; | ||
204 | uint8_t send_buf[2], recv_buf[3]; | ||
205 | struct i2c_client *client = context; | ||
206 | struct i2c_msg msgs[2]; | ||
207 | |||
208 | size = adau1701_register_size(&client->dev, reg); | ||
209 | if (size == 0) | ||
210 | return -EINVAL; | ||
175 | 211 | ||
176 | ret = snd_soc_cache_read(codec, reg, &value); | 212 | send_buf[0] = reg >> 8; |
177 | if (ret) | 213 | send_buf[1] = reg & 0xff; |
214 | |||
215 | msgs[0].addr = client->addr; | ||
216 | msgs[0].len = sizeof(send_buf); | ||
217 | msgs[0].buf = send_buf; | ||
218 | msgs[0].flags = 0; | ||
219 | |||
220 | msgs[1].addr = client->addr; | ||
221 | msgs[1].len = size; | ||
222 | msgs[1].buf = recv_buf; | ||
223 | msgs[1].flags = I2C_M_RD; | ||
224 | |||
225 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
226 | if (ret < 0) | ||
178 | return ret; | 227 | return ret; |
228 | else if (ret != ARRAY_SIZE(msgs)) | ||
229 | return -EIO; | ||
179 | 230 | ||
180 | return value; | 231 | *value = 0; |
232 | |||
233 | for (i = 0; i < size; i++) | ||
234 | *value |= recv_buf[i] << (i * 8); | ||
235 | |||
236 | return 0; | ||
181 | } | 237 | } |
182 | 238 | ||
183 | static int adau1701_load_firmware(struct snd_soc_codec *codec) | 239 | static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) |
184 | { | 240 | { |
185 | return process_sigma_firmware(codec->control_data, ADAU1701_FIRMWARE); | 241 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
242 | struct i2c_client *client = to_i2c_client(codec->dev); | ||
243 | int ret; | ||
244 | |||
245 | if (clkdiv != ADAU1707_CLKDIV_UNSET && | ||
246 | gpio_is_valid(adau1701->gpio_pll_mode[0]) && | ||
247 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { | ||
248 | switch (clkdiv) { | ||
249 | case 64: | ||
250 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
251 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
252 | break; | ||
253 | case 256: | ||
254 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
255 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
256 | break; | ||
257 | case 384: | ||
258 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
259 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
260 | break; | ||
261 | case 0: /* fallback */ | ||
262 | case 512: | ||
263 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
264 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
265 | break; | ||
266 | } | ||
267 | } | ||
268 | |||
269 | adau1701->pll_clkdiv = clkdiv; | ||
270 | |||
271 | if (gpio_is_valid(adau1701->gpio_nreset)) { | ||
272 | gpio_set_value(adau1701->gpio_nreset, 0); | ||
273 | /* minimum reset time is 20ns */ | ||
274 | udelay(1); | ||
275 | gpio_set_value(adau1701->gpio_nreset, 1); | ||
276 | /* power-up time may be as long as 85ms */ | ||
277 | mdelay(85); | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Postpone the firmware download to a point in time when we | ||
282 | * know the correct PLL setup | ||
283 | */ | ||
284 | if (clkdiv != ADAU1707_CLKDIV_UNSET) { | ||
285 | ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); | ||
286 | if (ret) { | ||
287 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
288 | return ret; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | regmap_write(adau1701->regmap, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | ||
293 | regmap_write(adau1701->regmap, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
294 | |||
295 | regcache_mark_dirty(adau1701->regmap); | ||
296 | regcache_sync(adau1701->regmap); | ||
297 | |||
298 | return 0; | ||
186 | } | 299 | } |
187 | 300 | ||
188 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | 301 | static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, |
@@ -221,7 +334,7 @@ static int adau1701_set_capture_pcm_format(struct snd_soc_codec *codec, | |||
221 | mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; | 334 | mask |= ADAU1701_SEROCTL_MSB_DEALY_MASK; |
222 | } | 335 | } |
223 | 336 | ||
224 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, mask, val); | 337 | regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, mask, val); |
225 | 338 | ||
226 | return 0; | 339 | return 0; |
227 | } | 340 | } |
@@ -249,7 +362,7 @@ static int adau1701_set_playback_pcm_format(struct snd_soc_codec *codec, | |||
249 | return -EINVAL; | 362 | return -EINVAL; |
250 | } | 363 | } |
251 | 364 | ||
252 | snd_soc_update_bits(codec, ADAU1701_SERICTL, | 365 | regmap_update_bits(adau1701->regmap, ADAU1701_SERICTL, |
253 | ADAU1701_SERICTL_MODE_MASK, val); | 366 | ADAU1701_SERICTL_MODE_MASK, val); |
254 | 367 | ||
255 | return 0; | 368 | return 0; |
@@ -259,8 +372,22 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
259 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 372 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
260 | { | 373 | { |
261 | struct snd_soc_codec *codec = dai->codec; | 374 | struct snd_soc_codec *codec = dai->codec; |
375 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
376 | unsigned int clkdiv = adau1701->sysclk / params_rate(params); | ||
262 | snd_pcm_format_t format; | 377 | snd_pcm_format_t format; |
263 | unsigned int val; | 378 | unsigned int val; |
379 | int ret; | ||
380 | |||
381 | /* | ||
382 | * If the mclk/lrclk ratio changes, the chip needs updated PLL | ||
383 | * mode GPIO settings, and a full reset cycle, including a new | ||
384 | * firmware upload. | ||
385 | */ | ||
386 | if (clkdiv != adau1701->pll_clkdiv) { | ||
387 | ret = adau1701_reset(codec, clkdiv); | ||
388 | if (ret < 0) | ||
389 | return ret; | ||
390 | } | ||
264 | 391 | ||
265 | switch (params_rate(params)) { | 392 | switch (params_rate(params)) { |
266 | case 192000: | 393 | case 192000: |
@@ -276,7 +403,7 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
276 | return -EINVAL; | 403 | return -EINVAL; |
277 | } | 404 | } |
278 | 405 | ||
279 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, | 406 | regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, |
280 | ADAU1701_DSPCTRL_SR_MASK, val); | 407 | ADAU1701_DSPCTRL_SR_MASK, val); |
281 | 408 | ||
282 | format = params_format(params); | 409 | format = params_format(params); |
@@ -352,8 +479,8 @@ static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
352 | 479 | ||
353 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | 480 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
354 | 481 | ||
355 | snd_soc_write(codec, ADAU1701_SERICTL, serictl); | 482 | regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl); |
356 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, | 483 | regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, |
357 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); | 484 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); |
358 | 485 | ||
359 | return 0; | 486 | return 0; |
@@ -363,6 +490,7 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec, | |||
363 | enum snd_soc_bias_level level) | 490 | enum snd_soc_bias_level level) |
364 | { | 491 | { |
365 | unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; | 492 | unsigned int mask = ADAU1701_AUXNPOW_VBPD | ADAU1701_AUXNPOW_VRPD; |
493 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
366 | 494 | ||
367 | switch (level) { | 495 | switch (level) { |
368 | case SND_SOC_BIAS_ON: | 496 | case SND_SOC_BIAS_ON: |
@@ -371,11 +499,13 @@ static int adau1701_set_bias_level(struct snd_soc_codec *codec, | |||
371 | break; | 499 | break; |
372 | case SND_SOC_BIAS_STANDBY: | 500 | case SND_SOC_BIAS_STANDBY: |
373 | /* Enable VREF and VREF buffer */ | 501 | /* Enable VREF and VREF buffer */ |
374 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, 0x00); | 502 | regmap_update_bits(adau1701->regmap, |
503 | ADAU1701_AUXNPOW, mask, 0x00); | ||
375 | break; | 504 | break; |
376 | case SND_SOC_BIAS_OFF: | 505 | case SND_SOC_BIAS_OFF: |
377 | /* Disable VREF and VREF buffer */ | 506 | /* Disable VREF and VREF buffer */ |
378 | snd_soc_update_bits(codec, ADAU1701_AUXNPOW, mask, mask); | 507 | regmap_update_bits(adau1701->regmap, |
508 | ADAU1701_AUXNPOW, mask, mask); | ||
379 | break; | 509 | break; |
380 | } | 510 | } |
381 | 511 | ||
@@ -387,6 +517,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) | |||
387 | { | 517 | { |
388 | struct snd_soc_codec *codec = dai->codec; | 518 | struct snd_soc_codec *codec = dai->codec; |
389 | unsigned int mask = ADAU1701_DSPCTRL_DAM; | 519 | unsigned int mask = ADAU1701_DSPCTRL_DAM; |
520 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
390 | unsigned int val; | 521 | unsigned int val; |
391 | 522 | ||
392 | if (mute) | 523 | if (mute) |
@@ -394,7 +525,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute) | |||
394 | else | 525 | else |
395 | val = mask; | 526 | val = mask; |
396 | 527 | ||
397 | snd_soc_update_bits(codec, ADAU1701_DSPCTRL, mask, val); | 528 | regmap_update_bits(adau1701->regmap, ADAU1701_DSPCTRL, mask, val); |
398 | 529 | ||
399 | return 0; | 530 | return 0; |
400 | } | 531 | } |
@@ -403,6 +534,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
403 | int source, unsigned int freq, int dir) | 534 | int source, unsigned int freq, int dir) |
404 | { | 535 | { |
405 | unsigned int val; | 536 | unsigned int val; |
537 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
406 | 538 | ||
407 | switch (clk_id) { | 539 | switch (clk_id) { |
408 | case ADAU1701_CLK_SRC_OSC: | 540 | case ADAU1701_CLK_SRC_OSC: |
@@ -415,7 +547,9 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
415 | return -EINVAL; | 547 | return -EINVAL; |
416 | } | 548 | } |
417 | 549 | ||
418 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); | 550 | regmap_update_bits(adau1701->regmap, ADAU1701_OSCIPOW, |
551 | ADAU1701_OSCIPOW_OPD, val); | ||
552 | adau1701->sysclk = freq; | ||
419 | 553 | ||
420 | return 0; | 554 | return 0; |
421 | } | 555 | } |
@@ -452,18 +586,45 @@ static struct snd_soc_dai_driver adau1701_dai = { | |||
452 | .symmetric_rates = 1, | 586 | .symmetric_rates = 1, |
453 | }; | 587 | }; |
454 | 588 | ||
589 | #ifdef CONFIG_OF | ||
590 | static const struct of_device_id adau1701_dt_ids[] = { | ||
591 | { .compatible = "adi,adau1701", }, | ||
592 | { } | ||
593 | }; | ||
594 | MODULE_DEVICE_TABLE(of, adau1701_dt_ids); | ||
595 | #endif | ||
596 | |||
455 | static int adau1701_probe(struct snd_soc_codec *codec) | 597 | static int adau1701_probe(struct snd_soc_codec *codec) |
456 | { | 598 | { |
457 | int ret; | 599 | int i, ret; |
600 | unsigned int val; | ||
601 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
602 | |||
603 | /* | ||
604 | * Let the pll_clkdiv variable default to something that won't happen | ||
605 | * at runtime. That way, we can postpone the firmware download from | ||
606 | * adau1701_reset() to a point in time when we know the correct PLL | ||
607 | * mode parameters. | ||
608 | */ | ||
609 | adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; | ||
610 | |||
611 | /* initalize with pre-configured pll mode settings */ | ||
612 | ret = adau1701_reset(codec, adau1701->pll_clkdiv); | ||
613 | if (ret < 0) | ||
614 | return ret; | ||
615 | |||
616 | /* set up pin config */ | ||
617 | val = 0; | ||
618 | for (i = 0; i < 6; i++) | ||
619 | val |= adau1701->pin_config[i] << (i * 4); | ||
458 | 620 | ||
459 | codec->control_data = to_i2c_client(codec->dev); | 621 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_0, val); |
460 | 622 | ||
461 | ret = adau1701_load_firmware(codec); | 623 | val = 0; |
462 | if (ret) | 624 | for (i = 0; i < 6; i++) |
463 | dev_warn(codec->dev, "Failed to load firmware\n"); | 625 | val |= adau1701->pin_config[i + 6] << (i * 4); |
464 | 626 | ||
465 | snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | 627 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); |
466 | snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
467 | 628 | ||
468 | return 0; | 629 | return 0; |
469 | } | 630 | } |
@@ -473,9 +634,6 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
473 | .set_bias_level = adau1701_set_bias_level, | 634 | .set_bias_level = adau1701_set_bias_level, |
474 | .idle_bias_off = true, | 635 | .idle_bias_off = true, |
475 | 636 | ||
476 | .reg_cache_size = ADAU1701_NUM_REGS, | ||
477 | .reg_word_size = sizeof(u16), | ||
478 | |||
479 | .controls = adau1701_controls, | 637 | .controls = adau1701_controls, |
480 | .num_controls = ARRAY_SIZE(adau1701_controls), | 638 | .num_controls = ARRAY_SIZE(adau1701_controls), |
481 | .dapm_widgets = adau1701_dapm_widgets, | 639 | .dapm_widgets = adau1701_dapm_widgets, |
@@ -483,22 +641,86 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
483 | .dapm_routes = adau1701_dapm_routes, | 641 | .dapm_routes = adau1701_dapm_routes, |
484 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), | 642 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), |
485 | 643 | ||
486 | .write = adau1701_write, | ||
487 | .read = adau1701_read, | ||
488 | |||
489 | .set_sysclk = adau1701_set_sysclk, | 644 | .set_sysclk = adau1701_set_sysclk, |
490 | }; | 645 | }; |
491 | 646 | ||
647 | static const struct regmap_config adau1701_regmap = { | ||
648 | .reg_bits = 16, | ||
649 | .val_bits = 32, | ||
650 | .max_register = ADAU1701_MAX_REGISTER, | ||
651 | .cache_type = REGCACHE_RBTREE, | ||
652 | .volatile_reg = adau1701_volatile_reg, | ||
653 | .reg_write = adau1701_reg_write, | ||
654 | .reg_read = adau1701_reg_read, | ||
655 | }; | ||
656 | |||
492 | static int adau1701_i2c_probe(struct i2c_client *client, | 657 | static int adau1701_i2c_probe(struct i2c_client *client, |
493 | const struct i2c_device_id *id) | 658 | const struct i2c_device_id *id) |
494 | { | 659 | { |
495 | struct adau1701 *adau1701; | 660 | struct adau1701 *adau1701; |
661 | struct device *dev = &client->dev; | ||
662 | int gpio_nreset = -EINVAL; | ||
663 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; | ||
496 | int ret; | 664 | int ret; |
497 | 665 | ||
498 | adau1701 = devm_kzalloc(&client->dev, sizeof(*adau1701), GFP_KERNEL); | 666 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); |
499 | if (!adau1701) | 667 | if (!adau1701) |
500 | return -ENOMEM; | 668 | return -ENOMEM; |
501 | 669 | ||
670 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | ||
671 | &adau1701_regmap); | ||
672 | if (IS_ERR(adau1701->regmap)) | ||
673 | return PTR_ERR(adau1701->regmap); | ||
674 | |||
675 | if (dev->of_node) { | ||
676 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); | ||
677 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) | ||
678 | return gpio_nreset; | ||
679 | |||
680 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, | ||
681 | "adi,pll-mode-gpios", 0); | ||
682 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) | ||
683 | return gpio_pll_mode[0]; | ||
684 | |||
685 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, | ||
686 | "adi,pll-mode-gpios", 1); | ||
687 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) | ||
688 | return gpio_pll_mode[1]; | ||
689 | |||
690 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", | ||
691 | &adau1701->pll_clkdiv); | ||
692 | |||
693 | of_property_read_u8_array(dev->of_node, "adi,pin-config", | ||
694 | adau1701->pin_config, | ||
695 | ARRAY_SIZE(adau1701->pin_config)); | ||
696 | } | ||
697 | |||
698 | if (gpio_is_valid(gpio_nreset)) { | ||
699 | ret = devm_gpio_request_one(dev, gpio_nreset, GPIOF_OUT_INIT_LOW, | ||
700 | "ADAU1701 Reset"); | ||
701 | if (ret < 0) | ||
702 | return ret; | ||
703 | } | ||
704 | |||
705 | if (gpio_is_valid(gpio_pll_mode[0]) && | ||
706 | gpio_is_valid(gpio_pll_mode[1])) { | ||
707 | ret = devm_gpio_request_one(dev, gpio_pll_mode[0], | ||
708 | GPIOF_OUT_INIT_LOW, | ||
709 | "ADAU1701 PLL mode 0"); | ||
710 | if (ret < 0) | ||
711 | return ret; | ||
712 | |||
713 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], | ||
714 | GPIOF_OUT_INIT_LOW, | ||
715 | "ADAU1701 PLL mode 1"); | ||
716 | if (ret < 0) | ||
717 | return ret; | ||
718 | } | ||
719 | |||
720 | adau1701->gpio_nreset = gpio_nreset; | ||
721 | adau1701->gpio_pll_mode[0] = gpio_pll_mode[0]; | ||
722 | adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; | ||
723 | |||
502 | i2c_set_clientdata(client, adau1701); | 724 | i2c_set_clientdata(client, adau1701); |
503 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 725 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
504 | &adau1701_dai, 1); | 726 | &adau1701_dai, 1); |
@@ -521,6 +743,7 @@ static struct i2c_driver adau1701_i2c_driver = { | |||
521 | .driver = { | 743 | .driver = { |
522 | .name = "adau1701", | 744 | .name = "adau1701", |
523 | .owner = THIS_MODULE, | 745 | .owner = THIS_MODULE, |
746 | .of_match_table = of_match_ptr(adau1701_dt_ids), | ||
524 | }, | 747 | }, |
525 | .probe = adau1701_i2c_probe, | 748 | .probe = adau1701_i2c_probe, |
526 | .remove = adau1701_i2c_remove, | 749 | .remove = adau1701_i2c_remove, |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 2eda85ba79ac..a5455c1aea42 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -28,8 +28,6 @@ | |||
28 | 28 | ||
29 | #include "stac9766.h" | 29 | #include "stac9766.h" |
30 | 30 | ||
31 | #define STAC9766_VERSION "0.10" | ||
32 | |||
33 | /* | 31 | /* |
34 | * STAC9766 register cache | 32 | * STAC9766 register cache |
35 | */ | 33 | */ |
@@ -145,14 +143,14 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
145 | 143 | ||
146 | if (reg > AC97_STAC_PAGE0) { | 144 | if (reg > AC97_STAC_PAGE0) { |
147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
148 | soc_ac97_ops.write(codec->ac97, reg, val); | 146 | soc_ac97_ops->write(codec->ac97, reg, val); |
149 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
150 | return 0; | 148 | return 0; |
151 | } | 149 | } |
152 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
153 | return -EIO; | 151 | return -EIO; |
154 | 152 | ||
155 | soc_ac97_ops.write(codec->ac97, reg, val); | 153 | soc_ac97_ops->write(codec->ac97, reg, val); |
156 | cache[reg / 2] = val; | 154 | cache[reg / 2] = val; |
157 | return 0; | 155 | return 0; |
158 | } | 156 | } |
@@ -164,7 +162,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
164 | 162 | ||
165 | if (reg > AC97_STAC_PAGE0) { | 163 | if (reg > AC97_STAC_PAGE0) { |
166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
167 | val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); | 165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); |
168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
169 | return val; | 167 | return val; |
170 | } | 168 | } |
@@ -175,7 +173,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
176 | reg == AC97_VENDOR_ID2) { | 174 | reg == AC97_VENDOR_ID2) { |
177 | 175 | ||
178 | val = soc_ac97_ops.read(codec->ac97, reg); | 176 | val = soc_ac97_ops->read(codec->ac97, reg); |
179 | return val; | 177 | return val; |
180 | } | 178 | } |
181 | return cache[reg / 2]; | 179 | return cache[reg / 2]; |
@@ -242,15 +240,15 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
242 | 240 | ||
243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
244 | { | 242 | { |
245 | if (try_warm && soc_ac97_ops.warm_reset) { | 243 | if (try_warm && soc_ac97_ops->warm_reset) { |
246 | soc_ac97_ops.warm_reset(codec->ac97); | 244 | soc_ac97_ops->warm_reset(codec->ac97); |
247 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
248 | return 1; | 246 | return 1; |
249 | } | 247 | } |
250 | 248 | ||
251 | soc_ac97_ops.reset(codec->ac97); | 249 | soc_ac97_ops->reset(codec->ac97); |
252 | if (soc_ac97_ops.warm_reset) | 250 | if (soc_ac97_ops->warm_reset) |
253 | soc_ac97_ops.warm_reset(codec->ac97); | 251 | soc_ac97_ops->warm_reset(codec->ac97); |
254 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
255 | return -EIO; | 253 | return -EIO; |
256 | return 0; | 254 | return 0; |
@@ -274,7 +272,7 @@ reset: | |||
274 | return -EIO; | 272 | return -EIO; |
275 | } | 273 | } |
276 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 274 | codec->ac97->bus->ops->warm_reset(codec->ac97); |
277 | id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2); | 275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); |
278 | if (id != 0x4c13) { | 276 | if (id != 0x4c13) { |
279 | stac9766_reset(codec, 0); | 277 | stac9766_reset(codec, 0); |
280 | reset++; | 278 | reset++; |
@@ -338,9 +336,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
338 | { | 336 | { |
339 | int ret = 0; | 337 | int ret = 0; |
340 | 338 | ||
341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
342 | |||
343 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
344 | if (ret < 0) | 340 | if (ret < 0) |
345 | goto codec_err; | 341 | goto codec_err; |
346 | 342 | ||
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 05b1f346695b..70ce6793c5bd 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -209,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
209 | case AC97_RESET: | 209 | case AC97_RESET: |
210 | case AC97_VENDOR_ID1: | 210 | case AC97_VENDOR_ID1: |
211 | case AC97_VENDOR_ID2: | 211 | case AC97_VENDOR_ID2: |
212 | return soc_ac97_ops.read(codec->ac97, reg); | 212 | return soc_ac97_ops->read(codec->ac97, reg); |
213 | default: | 213 | default: |
214 | reg = reg >> 1; | 214 | reg = reg >> 1; |
215 | 215 | ||
@@ -225,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
225 | { | 225 | { |
226 | u16 *cache = codec->reg_cache; | 226 | u16 *cache = codec->reg_cache; |
227 | 227 | ||
228 | soc_ac97_ops.write(codec->ac97, reg, val); | 228 | soc_ac97_ops->write(codec->ac97, reg, val); |
229 | reg = reg >> 1; | 229 | reg = reg >> 1; |
230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 230 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | cache[reg] = val; | 231 | cache[reg] = val; |
@@ -294,8 +294,8 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
294 | 294 | ||
295 | static int wm9705_reset(struct snd_soc_codec *codec) | 295 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | { | 296 | { |
297 | if (soc_ac97_ops.reset) { | 297 | if (soc_ac97_ops->reset) { |
298 | soc_ac97_ops.reset(codec->ac97); | 298 | soc_ac97_ops->reset(codec->ac97); |
299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 299 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | return 0; /* Success */ | 300 | return 0; /* Success */ |
301 | } | 301 | } |
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec) | |||
306 | #ifdef CONFIG_PM | 306 | #ifdef CONFIG_PM |
307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
308 | { | 308 | { |
309 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); | 309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); |
310 | 310 | ||
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
@@ -323,7 +323,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
323 | } | 323 | } |
324 | 324 | ||
325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
326 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
327 | } | 327 | } |
328 | 328 | ||
329 | return 0; | 329 | return 0; |
@@ -337,9 +337,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) | |||
337 | { | 337 | { |
338 | int ret = 0; | 338 | int ret = 0; |
339 | 339 | ||
340 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | 340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
341 | |||
342 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
343 | if (ret < 0) { | 341 | if (ret < 0) { |
344 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
345 | return ret; | 343 | return ret; |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 8e9a6a3eeb1a..c5eb746087b4 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -455,7 +455,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | reg == AC97_REC_GAIN) | 457 | reg == AC97_REC_GAIN) |
458 | return soc_ac97_ops.read(codec->ac97, reg); | 458 | return soc_ac97_ops->read(codec->ac97, reg); |
459 | else { | 459 | else { |
460 | reg = reg >> 1; | 460 | reg = reg >> 1; |
461 | 461 | ||
@@ -472,7 +472,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
472 | u16 *cache = codec->reg_cache; | 472 | u16 *cache = codec->reg_cache; |
473 | 473 | ||
474 | if (reg < 0x7c) | 474 | if (reg < 0x7c) |
475 | soc_ac97_ops.write(codec->ac97, reg, val); | 475 | soc_ac97_ops->write(codec->ac97, reg, val); |
476 | reg = reg >> 1; | 476 | reg = reg >> 1; |
477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 477 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | cache[reg] = val; | 478 | cache[reg] = val; |
@@ -581,15 +581,15 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
581 | 581 | ||
582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | { | 583 | { |
584 | if (try_warm && soc_ac97_ops.warm_reset) { | 584 | if (try_warm && soc_ac97_ops->warm_reset) { |
585 | soc_ac97_ops.warm_reset(codec->ac97); | 585 | soc_ac97_ops->warm_reset(codec->ac97); |
586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 586 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | return 1; | 587 | return 1; |
588 | } | 588 | } |
589 | 589 | ||
590 | soc_ac97_ops.reset(codec->ac97); | 590 | soc_ac97_ops->reset(codec->ac97); |
591 | if (soc_ac97_ops.warm_reset) | 591 | if (soc_ac97_ops->warm_reset) |
592 | soc_ac97_ops.warm_reset(codec->ac97); | 592 | soc_ac97_ops->warm_reset(codec->ac97); |
593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 593 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | goto err; | 594 | goto err; |
595 | return 0; | 595 | return 0; |
@@ -624,7 +624,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | (i > 0x58 && i != 0x5c)) | 625 | (i > 0x58 && i != 0x5c)) |
626 | continue; | 626 | continue; |
627 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
628 | } | 628 | } |
629 | } | 629 | } |
630 | 630 | ||
@@ -635,7 +635,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
635 | { | 635 | { |
636 | int ret = 0; | 636 | int ret = 0; |
637 | 637 | ||
638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
639 | if (ret < 0) { | 639 | if (ret < 0) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
641 | return ret; | 641 | return ret; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f7afa68d8c7f..a53e175c015a 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -652,7 +652,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | reg == AC97_CD) | 654 | reg == AC97_CD) |
655 | return soc_ac97_ops.read(codec->ac97, reg); | 655 | return soc_ac97_ops->read(codec->ac97, reg); |
656 | else { | 656 | else { |
657 | reg = reg >> 1; | 657 | reg = reg >> 1; |
658 | 658 | ||
@@ -668,7 +668,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
668 | { | 668 | { |
669 | u16 *cache = codec->reg_cache; | 669 | u16 *cache = codec->reg_cache; |
670 | if (reg < 0x7c) | 670 | if (reg < 0x7c) |
671 | soc_ac97_ops.write(codec->ac97, reg, val); | 671 | soc_ac97_ops->write(codec->ac97, reg, val); |
672 | reg = reg >> 1; | 672 | reg = reg >> 1; |
673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 673 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | cache[reg] = val; | 674 | cache[reg] = val; |
@@ -1095,15 +1095,15 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1095 | 1095 | ||
1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | { | 1097 | { |
1098 | if (try_warm && soc_ac97_ops.warm_reset) { | 1098 | if (try_warm && soc_ac97_ops->warm_reset) { |
1099 | soc_ac97_ops.warm_reset(codec->ac97); | 1099 | soc_ac97_ops->warm_reset(codec->ac97); |
1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | return 1; | 1101 | return 1; |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | soc_ac97_ops.reset(codec->ac97); | 1104 | soc_ac97_ops->reset(codec->ac97); |
1105 | if (soc_ac97_ops.warm_reset) | 1105 | if (soc_ac97_ops->warm_reset) |
1106 | soc_ac97_ops.warm_reset(codec->ac97); | 1106 | soc_ac97_ops->warm_reset(codec->ac97); |
1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) |
1108 | return -EIO; | 1108 | return -EIO; |
1109 | return 0; | 1109 | return 0; |
@@ -1180,7 +1180,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | continue; | 1182 | continue; |
1183 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
1184 | } | 1184 | } |
1185 | } | 1185 | } |
1186 | 1186 | ||
@@ -1197,7 +1197,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1197 | return -ENOMEM; | 1197 | return -ENOMEM; |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | 1198 | snd_soc_codec_set_drvdata(codec, wm9713); |
1199 | 1199 | ||
1200 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
1201 | if (ret < 0) | 1201 | if (ret < 0) |
1202 | goto codec_err; | 1202 | goto codec_err; |
1203 | 1203 | ||
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 3470b649c0b2..ddba3fea39eb 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/regmap.h> | 21 | #include <linux/regmap.h> |
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/workqueue.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -215,6 +216,36 @@ static struct { | |||
215 | [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, | 216 | [WM_ADSP_FW_RX_ANC] = { .file = "rx-anc" }, |
216 | }; | 217 | }; |
217 | 218 | ||
219 | struct wm_coeff_ctl_ops { | ||
220 | int (*xget)(struct snd_kcontrol *kcontrol, | ||
221 | struct snd_ctl_elem_value *ucontrol); | ||
222 | int (*xput)(struct snd_kcontrol *kcontrol, | ||
223 | struct snd_ctl_elem_value *ucontrol); | ||
224 | int (*xinfo)(struct snd_kcontrol *kcontrol, | ||
225 | struct snd_ctl_elem_info *uinfo); | ||
226 | }; | ||
227 | |||
228 | struct wm_coeff { | ||
229 | struct device *dev; | ||
230 | struct list_head ctl_list; | ||
231 | struct regmap *regmap; | ||
232 | }; | ||
233 | |||
234 | struct wm_coeff_ctl { | ||
235 | const char *name; | ||
236 | struct snd_card *card; | ||
237 | struct wm_adsp_alg_region region; | ||
238 | struct wm_coeff_ctl_ops ops; | ||
239 | struct wm_adsp *adsp; | ||
240 | void *private; | ||
241 | unsigned int enabled:1; | ||
242 | struct list_head list; | ||
243 | void *cache; | ||
244 | size_t len; | ||
245 | unsigned int set:1; | ||
246 | struct snd_kcontrol *kcontrol; | ||
247 | }; | ||
248 | |||
218 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, | 249 | static int wm_adsp_fw_get(struct snd_kcontrol *kcontrol, |
219 | struct snd_ctl_elem_value *ucontrol) | 250 | struct snd_ctl_elem_value *ucontrol) |
220 | { | 251 | { |
@@ -334,6 +365,181 @@ static unsigned int wm_adsp_region_to_reg(struct wm_adsp_region const *region, | |||
334 | } | 365 | } |
335 | } | 366 | } |
336 | 367 | ||
368 | static int wm_coeff_info(struct snd_kcontrol *kcontrol, | ||
369 | struct snd_ctl_elem_info *uinfo) | ||
370 | { | ||
371 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
372 | |||
373 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | ||
374 | uinfo->count = ctl->len; | ||
375 | return 0; | ||
376 | } | ||
377 | |||
378 | static int wm_coeff_write_control(struct snd_kcontrol *kcontrol, | ||
379 | const void *buf, size_t len) | ||
380 | { | ||
381 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
382 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
383 | struct wm_adsp_alg_region *region = &ctl->region; | ||
384 | const struct wm_adsp_region *mem; | ||
385 | struct wm_adsp *adsp = ctl->adsp; | ||
386 | void *scratch; | ||
387 | int ret; | ||
388 | unsigned int reg; | ||
389 | |||
390 | mem = wm_adsp_find_region(adsp, region->type); | ||
391 | if (!mem) { | ||
392 | adsp_err(adsp, "No base for region %x\n", | ||
393 | region->type); | ||
394 | return -EINVAL; | ||
395 | } | ||
396 | |||
397 | reg = ctl->region.base; | ||
398 | reg = wm_adsp_region_to_reg(mem, reg); | ||
399 | |||
400 | scratch = kmemdup(buf, ctl->len, GFP_KERNEL | GFP_DMA); | ||
401 | if (!scratch) | ||
402 | return -ENOMEM; | ||
403 | |||
404 | ret = regmap_raw_write(wm_coeff->regmap, reg, scratch, | ||
405 | ctl->len); | ||
406 | if (ret) { | ||
407 | adsp_err(adsp, "Failed to write %zu bytes to %x\n", | ||
408 | ctl->len, reg); | ||
409 | kfree(scratch); | ||
410 | return ret; | ||
411 | } | ||
412 | |||
413 | kfree(scratch); | ||
414 | |||
415 | return 0; | ||
416 | } | ||
417 | |||
418 | static int wm_coeff_put(struct snd_kcontrol *kcontrol, | ||
419 | struct snd_ctl_elem_value *ucontrol) | ||
420 | { | ||
421 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
422 | char *p = ucontrol->value.bytes.data; | ||
423 | |||
424 | memcpy(ctl->cache, p, ctl->len); | ||
425 | |||
426 | if (!ctl->enabled) { | ||
427 | ctl->set = 1; | ||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | return wm_coeff_write_control(kcontrol, p, ctl->len); | ||
432 | } | ||
433 | |||
434 | static int wm_coeff_read_control(struct snd_kcontrol *kcontrol, | ||
435 | void *buf, size_t len) | ||
436 | { | ||
437 | struct wm_coeff *wm_coeff= snd_kcontrol_chip(kcontrol); | ||
438 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
439 | struct wm_adsp_alg_region *region = &ctl->region; | ||
440 | const struct wm_adsp_region *mem; | ||
441 | struct wm_adsp *adsp = ctl->adsp; | ||
442 | void *scratch; | ||
443 | int ret; | ||
444 | unsigned int reg; | ||
445 | |||
446 | mem = wm_adsp_find_region(adsp, region->type); | ||
447 | if (!mem) { | ||
448 | adsp_err(adsp, "No base for region %x\n", | ||
449 | region->type); | ||
450 | return -EINVAL; | ||
451 | } | ||
452 | |||
453 | reg = ctl->region.base; | ||
454 | reg = wm_adsp_region_to_reg(mem, reg); | ||
455 | |||
456 | scratch = kmalloc(ctl->len, GFP_KERNEL | GFP_DMA); | ||
457 | if (!scratch) | ||
458 | return -ENOMEM; | ||
459 | |||
460 | ret = regmap_raw_read(wm_coeff->regmap, reg, scratch, ctl->len); | ||
461 | if (ret) { | ||
462 | adsp_err(adsp, "Failed to read %zu bytes from %x\n", | ||
463 | ctl->len, reg); | ||
464 | kfree(scratch); | ||
465 | return ret; | ||
466 | } | ||
467 | |||
468 | memcpy(buf, scratch, ctl->len); | ||
469 | kfree(scratch); | ||
470 | |||
471 | return 0; | ||
472 | } | ||
473 | |||
474 | static int wm_coeff_get(struct snd_kcontrol *kcontrol, | ||
475 | struct snd_ctl_elem_value *ucontrol) | ||
476 | { | ||
477 | struct wm_coeff_ctl *ctl = (struct wm_coeff_ctl *)kcontrol->private_value; | ||
478 | char *p = ucontrol->value.bytes.data; | ||
479 | |||
480 | memcpy(p, ctl->cache, ctl->len); | ||
481 | return 0; | ||
482 | } | ||
483 | |||
484 | static int wm_coeff_add_kcontrol(struct wm_coeff *wm_coeff, | ||
485 | struct wm_coeff_ctl *ctl, | ||
486 | const struct snd_kcontrol_new *kctl) | ||
487 | { | ||
488 | int ret; | ||
489 | struct snd_kcontrol *kcontrol; | ||
490 | |||
491 | kcontrol = snd_ctl_new1(kctl, wm_coeff); | ||
492 | ret = snd_ctl_add(ctl->card, kcontrol); | ||
493 | if (ret < 0) { | ||
494 | dev_err(wm_coeff->dev, "Failed to add %s: %d\n", | ||
495 | kctl->name, ret); | ||
496 | return ret; | ||
497 | } | ||
498 | ctl->kcontrol = kcontrol; | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | struct wmfw_ctl_work { | ||
503 | struct wm_coeff *wm_coeff; | ||
504 | struct wm_coeff_ctl *ctl; | ||
505 | struct work_struct work; | ||
506 | }; | ||
507 | |||
508 | static int wmfw_add_ctl(struct wm_coeff *wm_coeff, | ||
509 | struct wm_coeff_ctl *ctl) | ||
510 | { | ||
511 | struct snd_kcontrol_new *kcontrol; | ||
512 | int ret; | ||
513 | |||
514 | if (!wm_coeff || !ctl || !ctl->name || !ctl->card) | ||
515 | return -EINVAL; | ||
516 | |||
517 | kcontrol = kzalloc(sizeof(*kcontrol), GFP_KERNEL); | ||
518 | if (!kcontrol) | ||
519 | return -ENOMEM; | ||
520 | kcontrol->iface = SNDRV_CTL_ELEM_IFACE_MIXER; | ||
521 | |||
522 | kcontrol->name = ctl->name; | ||
523 | kcontrol->info = wm_coeff_info; | ||
524 | kcontrol->get = wm_coeff_get; | ||
525 | kcontrol->put = wm_coeff_put; | ||
526 | kcontrol->private_value = (unsigned long)ctl; | ||
527 | |||
528 | ret = wm_coeff_add_kcontrol(wm_coeff, | ||
529 | ctl, kcontrol); | ||
530 | if (ret < 0) | ||
531 | goto err_kcontrol; | ||
532 | |||
533 | kfree(kcontrol); | ||
534 | |||
535 | list_add(&ctl->list, &wm_coeff->ctl_list); | ||
536 | return 0; | ||
537 | |||
538 | err_kcontrol: | ||
539 | kfree(kcontrol); | ||
540 | return ret; | ||
541 | } | ||
542 | |||
337 | static int wm_adsp_load(struct wm_adsp *dsp) | 543 | static int wm_adsp_load(struct wm_adsp *dsp) |
338 | { | 544 | { |
339 | LIST_HEAD(buf_list); | 545 | LIST_HEAD(buf_list); |
@@ -547,7 +753,157 @@ out: | |||
547 | return ret; | 753 | return ret; |
548 | } | 754 | } |
549 | 755 | ||
550 | static int wm_adsp_setup_algs(struct wm_adsp *dsp) | 756 | static int wm_coeff_init_control_caches(struct wm_coeff *wm_coeff) |
757 | { | ||
758 | struct wm_coeff_ctl *ctl; | ||
759 | int ret; | ||
760 | |||
761 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | ||
762 | list) { | ||
763 | if (!ctl->enabled || ctl->set) | ||
764 | continue; | ||
765 | ret = wm_coeff_read_control(ctl->kcontrol, | ||
766 | ctl->cache, | ||
767 | ctl->len); | ||
768 | if (ret < 0) | ||
769 | return ret; | ||
770 | } | ||
771 | |||
772 | return 0; | ||
773 | } | ||
774 | |||
775 | static int wm_coeff_sync_controls(struct wm_coeff *wm_coeff) | ||
776 | { | ||
777 | struct wm_coeff_ctl *ctl; | ||
778 | int ret; | ||
779 | |||
780 | list_for_each_entry(ctl, &wm_coeff->ctl_list, | ||
781 | list) { | ||
782 | if (!ctl->enabled) | ||
783 | continue; | ||
784 | if (ctl->set) { | ||
785 | ret = wm_coeff_write_control(ctl->kcontrol, | ||
786 | ctl->cache, | ||
787 | ctl->len); | ||
788 | if (ret < 0) | ||
789 | return ret; | ||
790 | } | ||
791 | } | ||
792 | |||
793 | return 0; | ||
794 | } | ||
795 | |||
796 | static void wm_adsp_ctl_work(struct work_struct *work) | ||
797 | { | ||
798 | struct wmfw_ctl_work *ctl_work = container_of(work, | ||
799 | struct wmfw_ctl_work, | ||
800 | work); | ||
801 | |||
802 | wmfw_add_ctl(ctl_work->wm_coeff, ctl_work->ctl); | ||
803 | kfree(ctl_work); | ||
804 | } | ||
805 | |||
806 | static int wm_adsp_create_control(struct snd_soc_codec *codec, | ||
807 | const struct wm_adsp_alg_region *region) | ||
808 | |||
809 | { | ||
810 | struct wm_adsp *dsp = snd_soc_codec_get_drvdata(codec); | ||
811 | struct wm_coeff_ctl *ctl; | ||
812 | struct wmfw_ctl_work *ctl_work; | ||
813 | char *name; | ||
814 | char *region_name; | ||
815 | int ret; | ||
816 | |||
817 | name = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
818 | if (!name) | ||
819 | return -ENOMEM; | ||
820 | |||
821 | switch (region->type) { | ||
822 | case WMFW_ADSP1_PM: | ||
823 | region_name = "PM"; | ||
824 | break; | ||
825 | case WMFW_ADSP1_DM: | ||
826 | region_name = "DM"; | ||
827 | break; | ||
828 | case WMFW_ADSP2_XM: | ||
829 | region_name = "XM"; | ||
830 | break; | ||
831 | case WMFW_ADSP2_YM: | ||
832 | region_name = "YM"; | ||
833 | break; | ||
834 | case WMFW_ADSP1_ZM: | ||
835 | region_name = "ZM"; | ||
836 | break; | ||
837 | default: | ||
838 | ret = -EINVAL; | ||
839 | goto err_name; | ||
840 | } | ||
841 | |||
842 | snprintf(name, PAGE_SIZE, "DSP%d %s %x", | ||
843 | dsp->num, region_name, region->alg); | ||
844 | |||
845 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
846 | list) { | ||
847 | if (!strcmp(ctl->name, name)) { | ||
848 | if (!ctl->enabled) | ||
849 | ctl->enabled = 1; | ||
850 | goto found; | ||
851 | } | ||
852 | } | ||
853 | |||
854 | ctl = kzalloc(sizeof(*ctl), GFP_KERNEL); | ||
855 | if (!ctl) { | ||
856 | ret = -ENOMEM; | ||
857 | goto err_name; | ||
858 | } | ||
859 | ctl->region = *region; | ||
860 | ctl->name = kmemdup(name, strlen(name) + 1, GFP_KERNEL); | ||
861 | if (!ctl->name) { | ||
862 | ret = -ENOMEM; | ||
863 | goto err_ctl; | ||
864 | } | ||
865 | ctl->enabled = 1; | ||
866 | ctl->set = 0; | ||
867 | ctl->ops.xget = wm_coeff_get; | ||
868 | ctl->ops.xput = wm_coeff_put; | ||
869 | ctl->card = codec->card->snd_card; | ||
870 | ctl->adsp = dsp; | ||
871 | |||
872 | ctl->len = region->len; | ||
873 | ctl->cache = kzalloc(ctl->len, GFP_KERNEL); | ||
874 | if (!ctl->cache) { | ||
875 | ret = -ENOMEM; | ||
876 | goto err_ctl_name; | ||
877 | } | ||
878 | |||
879 | ctl_work = kzalloc(sizeof(*ctl_work), GFP_KERNEL); | ||
880 | if (!ctl_work) { | ||
881 | ret = -ENOMEM; | ||
882 | goto err_ctl_cache; | ||
883 | } | ||
884 | |||
885 | ctl_work->wm_coeff = dsp->wm_coeff; | ||
886 | ctl_work->ctl = ctl; | ||
887 | INIT_WORK(&ctl_work->work, wm_adsp_ctl_work); | ||
888 | schedule_work(&ctl_work->work); | ||
889 | |||
890 | found: | ||
891 | kfree(name); | ||
892 | |||
893 | return 0; | ||
894 | |||
895 | err_ctl_cache: | ||
896 | kfree(ctl->cache); | ||
897 | err_ctl_name: | ||
898 | kfree(ctl->name); | ||
899 | err_ctl: | ||
900 | kfree(ctl); | ||
901 | err_name: | ||
902 | kfree(name); | ||
903 | return ret; | ||
904 | } | ||
905 | |||
906 | static int wm_adsp_setup_algs(struct wm_adsp *dsp, struct snd_soc_codec *codec) | ||
551 | { | 907 | { |
552 | struct regmap *regmap = dsp->regmap; | 908 | struct regmap *regmap = dsp->regmap; |
553 | struct wmfw_adsp1_id_hdr adsp1_id; | 909 | struct wmfw_adsp1_id_hdr adsp1_id; |
@@ -730,7 +1086,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
730 | region->type = WMFW_ADSP1_DM; | 1086 | region->type = WMFW_ADSP1_DM; |
731 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1087 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
732 | region->base = be32_to_cpu(adsp1_alg[i].dm); | 1088 | region->base = be32_to_cpu(adsp1_alg[i].dm); |
1089 | region->len = 0; | ||
733 | list_add_tail(®ion->list, &dsp->alg_regions); | 1090 | list_add_tail(®ion->list, &dsp->alg_regions); |
1091 | if (i + 1 < algs) { | ||
1092 | region->len = be32_to_cpu(adsp1_alg[i + 1].dm); | ||
1093 | region->len -= be32_to_cpu(adsp1_alg[i].dm); | ||
1094 | wm_adsp_create_control(codec, region); | ||
1095 | } else { | ||
1096 | adsp_warn(dsp, "Missing length info for region DM with ID %x\n", | ||
1097 | be32_to_cpu(adsp1_alg[i].alg.id)); | ||
1098 | } | ||
734 | 1099 | ||
735 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1100 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
736 | if (!region) | 1101 | if (!region) |
@@ -738,7 +1103,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
738 | region->type = WMFW_ADSP1_ZM; | 1103 | region->type = WMFW_ADSP1_ZM; |
739 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); | 1104 | region->alg = be32_to_cpu(adsp1_alg[i].alg.id); |
740 | region->base = be32_to_cpu(adsp1_alg[i].zm); | 1105 | region->base = be32_to_cpu(adsp1_alg[i].zm); |
1106 | region->len = 0; | ||
741 | list_add_tail(®ion->list, &dsp->alg_regions); | 1107 | list_add_tail(®ion->list, &dsp->alg_regions); |
1108 | if (i + 1 < algs) { | ||
1109 | region->len = be32_to_cpu(adsp1_alg[i + 1].zm); | ||
1110 | region->len -= be32_to_cpu(adsp1_alg[i].zm); | ||
1111 | wm_adsp_create_control(codec, region); | ||
1112 | } else { | ||
1113 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | ||
1114 | be32_to_cpu(adsp1_alg[i].alg.id)); | ||
1115 | } | ||
742 | break; | 1116 | break; |
743 | 1117 | ||
744 | case WMFW_ADSP2: | 1118 | case WMFW_ADSP2: |
@@ -758,7 +1132,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
758 | region->type = WMFW_ADSP2_XM; | 1132 | region->type = WMFW_ADSP2_XM; |
759 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1133 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
760 | region->base = be32_to_cpu(adsp2_alg[i].xm); | 1134 | region->base = be32_to_cpu(adsp2_alg[i].xm); |
1135 | region->len = 0; | ||
761 | list_add_tail(®ion->list, &dsp->alg_regions); | 1136 | list_add_tail(®ion->list, &dsp->alg_regions); |
1137 | if (i + 1 < algs) { | ||
1138 | region->len = be32_to_cpu(adsp2_alg[i + 1].xm); | ||
1139 | region->len -= be32_to_cpu(adsp2_alg[i].xm); | ||
1140 | wm_adsp_create_control(codec, region); | ||
1141 | } else { | ||
1142 | adsp_warn(dsp, "Missing length info for region XM with ID %x\n", | ||
1143 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
1144 | } | ||
762 | 1145 | ||
763 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1146 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
764 | if (!region) | 1147 | if (!region) |
@@ -766,7 +1149,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
766 | region->type = WMFW_ADSP2_YM; | 1149 | region->type = WMFW_ADSP2_YM; |
767 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1150 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
768 | region->base = be32_to_cpu(adsp2_alg[i].ym); | 1151 | region->base = be32_to_cpu(adsp2_alg[i].ym); |
1152 | region->len = 0; | ||
769 | list_add_tail(®ion->list, &dsp->alg_regions); | 1153 | list_add_tail(®ion->list, &dsp->alg_regions); |
1154 | if (i + 1 < algs) { | ||
1155 | region->len = be32_to_cpu(adsp2_alg[i + 1].ym); | ||
1156 | region->len -= be32_to_cpu(adsp2_alg[i].ym); | ||
1157 | wm_adsp_create_control(codec, region); | ||
1158 | } else { | ||
1159 | adsp_warn(dsp, "Missing length info for region YM with ID %x\n", | ||
1160 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
1161 | } | ||
770 | 1162 | ||
771 | region = kzalloc(sizeof(*region), GFP_KERNEL); | 1163 | region = kzalloc(sizeof(*region), GFP_KERNEL); |
772 | if (!region) | 1164 | if (!region) |
@@ -774,7 +1166,16 @@ static int wm_adsp_setup_algs(struct wm_adsp *dsp) | |||
774 | region->type = WMFW_ADSP2_ZM; | 1166 | region->type = WMFW_ADSP2_ZM; |
775 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); | 1167 | region->alg = be32_to_cpu(adsp2_alg[i].alg.id); |
776 | region->base = be32_to_cpu(adsp2_alg[i].zm); | 1168 | region->base = be32_to_cpu(adsp2_alg[i].zm); |
1169 | region->len = 0; | ||
777 | list_add_tail(®ion->list, &dsp->alg_regions); | 1170 | list_add_tail(®ion->list, &dsp->alg_regions); |
1171 | if (i + 1 < algs) { | ||
1172 | region->len = be32_to_cpu(adsp2_alg[i + 1].zm); | ||
1173 | region->len -= be32_to_cpu(adsp2_alg[i].zm); | ||
1174 | wm_adsp_create_control(codec, region); | ||
1175 | } else { | ||
1176 | adsp_warn(dsp, "Missing length info for region ZM with ID %x\n", | ||
1177 | be32_to_cpu(adsp2_alg[i].alg.id)); | ||
1178 | } | ||
778 | break; | 1179 | break; |
779 | } | 1180 | } |
780 | } | 1181 | } |
@@ -986,6 +1387,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
986 | struct snd_soc_codec *codec = w->codec; | 1387 | struct snd_soc_codec *codec = w->codec; |
987 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1388 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
988 | struct wm_adsp *dsp = &dsps[w->shift]; | 1389 | struct wm_adsp *dsp = &dsps[w->shift]; |
1390 | struct wm_coeff_ctl *ctl; | ||
989 | int ret; | 1391 | int ret; |
990 | int val; | 1392 | int val; |
991 | 1393 | ||
@@ -1023,7 +1425,7 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1023 | if (ret != 0) | 1425 | if (ret != 0) |
1024 | goto err; | 1426 | goto err; |
1025 | 1427 | ||
1026 | ret = wm_adsp_setup_algs(dsp); | 1428 | ret = wm_adsp_setup_algs(dsp, codec); |
1027 | if (ret != 0) | 1429 | if (ret != 0) |
1028 | goto err; | 1430 | goto err; |
1029 | 1431 | ||
@@ -1031,6 +1433,16 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1031 | if (ret != 0) | 1433 | if (ret != 0) |
1032 | goto err; | 1434 | goto err; |
1033 | 1435 | ||
1436 | /* Initialize caches for enabled and unset controls */ | ||
1437 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | ||
1438 | if (ret != 0) | ||
1439 | goto err; | ||
1440 | |||
1441 | /* Sync set controls */ | ||
1442 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | ||
1443 | if (ret != 0) | ||
1444 | goto err; | ||
1445 | |||
1034 | /* Start the core running */ | 1446 | /* Start the core running */ |
1035 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1447 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
1036 | ADSP1_CORE_ENA | ADSP1_START, | 1448 | ADSP1_CORE_ENA | ADSP1_START, |
@@ -1047,6 +1459,11 @@ int wm_adsp1_event(struct snd_soc_dapm_widget *w, | |||
1047 | 1459 | ||
1048 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, | 1460 | regmap_update_bits(dsp->regmap, dsp->base + ADSP1_CONTROL_30, |
1049 | ADSP1_SYS_ENA, 0); | 1461 | ADSP1_SYS_ENA, 0); |
1462 | |||
1463 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
1464 | list) { | ||
1465 | ctl->enabled = 0; | ||
1466 | } | ||
1050 | break; | 1467 | break; |
1051 | 1468 | ||
1052 | default: | 1469 | default: |
@@ -1099,6 +1516,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1099 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); | 1516 | struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); |
1100 | struct wm_adsp *dsp = &dsps[w->shift]; | 1517 | struct wm_adsp *dsp = &dsps[w->shift]; |
1101 | struct wm_adsp_alg_region *alg_region; | 1518 | struct wm_adsp_alg_region *alg_region; |
1519 | struct wm_coeff_ctl *ctl; | ||
1102 | unsigned int val; | 1520 | unsigned int val; |
1103 | int ret; | 1521 | int ret; |
1104 | 1522 | ||
@@ -1164,7 +1582,7 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1164 | if (ret != 0) | 1582 | if (ret != 0) |
1165 | goto err; | 1583 | goto err; |
1166 | 1584 | ||
1167 | ret = wm_adsp_setup_algs(dsp); | 1585 | ret = wm_adsp_setup_algs(dsp, codec); |
1168 | if (ret != 0) | 1586 | if (ret != 0) |
1169 | goto err; | 1587 | goto err; |
1170 | 1588 | ||
@@ -1172,6 +1590,16 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1172 | if (ret != 0) | 1590 | if (ret != 0) |
1173 | goto err; | 1591 | goto err; |
1174 | 1592 | ||
1593 | /* Initialize caches for enabled and unset controls */ | ||
1594 | ret = wm_coeff_init_control_caches(dsp->wm_coeff); | ||
1595 | if (ret != 0) | ||
1596 | goto err; | ||
1597 | |||
1598 | /* Sync set controls */ | ||
1599 | ret = wm_coeff_sync_controls(dsp->wm_coeff); | ||
1600 | if (ret != 0) | ||
1601 | goto err; | ||
1602 | |||
1175 | ret = regmap_update_bits(dsp->regmap, | 1603 | ret = regmap_update_bits(dsp->regmap, |
1176 | dsp->base + ADSP2_CONTROL, | 1604 | dsp->base + ADSP2_CONTROL, |
1177 | ADSP2_CORE_ENA | ADSP2_START, | 1605 | ADSP2_CORE_ENA | ADSP2_START, |
@@ -1209,6 +1637,11 @@ int wm_adsp2_event(struct snd_soc_dapm_widget *w, | |||
1209 | ret); | 1637 | ret); |
1210 | } | 1638 | } |
1211 | 1639 | ||
1640 | list_for_each_entry(ctl, &dsp->wm_coeff->ctl_list, | ||
1641 | list) { | ||
1642 | ctl->enabled = 0; | ||
1643 | } | ||
1644 | |||
1212 | while (!list_empty(&dsp->alg_regions)) { | 1645 | while (!list_empty(&dsp->alg_regions)) { |
1213 | alg_region = list_first_entry(&dsp->alg_regions, | 1646 | alg_region = list_first_entry(&dsp->alg_regions, |
1214 | struct wm_adsp_alg_region, | 1647 | struct wm_adsp_alg_region, |
@@ -1247,36 +1680,48 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs) | |||
1247 | 1680 | ||
1248 | INIT_LIST_HEAD(&adsp->alg_regions); | 1681 | INIT_LIST_HEAD(&adsp->alg_regions); |
1249 | 1682 | ||
1683 | adsp->wm_coeff = kzalloc(sizeof(*adsp->wm_coeff), | ||
1684 | GFP_KERNEL); | ||
1685 | if (!adsp->wm_coeff) | ||
1686 | return -ENOMEM; | ||
1687 | adsp->wm_coeff->regmap = adsp->regmap; | ||
1688 | adsp->wm_coeff->dev = adsp->dev; | ||
1689 | INIT_LIST_HEAD(&adsp->wm_coeff->ctl_list); | ||
1690 | |||
1250 | if (dvfs) { | 1691 | if (dvfs) { |
1251 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); | 1692 | adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); |
1252 | if (IS_ERR(adsp->dvfs)) { | 1693 | if (IS_ERR(adsp->dvfs)) { |
1253 | ret = PTR_ERR(adsp->dvfs); | 1694 | ret = PTR_ERR(adsp->dvfs); |
1254 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); | 1695 | dev_err(adsp->dev, "Failed to get DCVDD: %d\n", ret); |
1255 | return ret; | 1696 | goto out_coeff; |
1256 | } | 1697 | } |
1257 | 1698 | ||
1258 | ret = regulator_enable(adsp->dvfs); | 1699 | ret = regulator_enable(adsp->dvfs); |
1259 | if (ret != 0) { | 1700 | if (ret != 0) { |
1260 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", | 1701 | dev_err(adsp->dev, "Failed to enable DCVDD: %d\n", |
1261 | ret); | 1702 | ret); |
1262 | return ret; | 1703 | goto out_coeff; |
1263 | } | 1704 | } |
1264 | 1705 | ||
1265 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); | 1706 | ret = regulator_set_voltage(adsp->dvfs, 1200000, 1800000); |
1266 | if (ret != 0) { | 1707 | if (ret != 0) { |
1267 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", | 1708 | dev_err(adsp->dev, "Failed to initialise DVFS: %d\n", |
1268 | ret); | 1709 | ret); |
1269 | return ret; | 1710 | goto out_coeff; |
1270 | } | 1711 | } |
1271 | 1712 | ||
1272 | ret = regulator_disable(adsp->dvfs); | 1713 | ret = regulator_disable(adsp->dvfs); |
1273 | if (ret != 0) { | 1714 | if (ret != 0) { |
1274 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", | 1715 | dev_err(adsp->dev, "Failed to disable DCVDD: %d\n", |
1275 | ret); | 1716 | ret); |
1276 | return ret; | 1717 | goto out_coeff; |
1277 | } | 1718 | } |
1278 | } | 1719 | } |
1279 | 1720 | ||
1280 | return 0; | 1721 | return 0; |
1722 | |||
1723 | out_coeff: | ||
1724 | kfree(adsp->wm_coeff); | ||
1725 | return ret; | ||
1281 | } | 1726 | } |
1282 | EXPORT_SYMBOL_GPL(wm_adsp2_init); | 1727 | EXPORT_SYMBOL_GPL(wm_adsp2_init); |
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 36533eac420e..9f922c82536c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -30,6 +30,7 @@ struct wm_adsp_alg_region { | |||
30 | unsigned int alg; | 30 | unsigned int alg; |
31 | int type; | 31 | int type; |
32 | unsigned int base; | 32 | unsigned int base; |
33 | size_t len; | ||
33 | }; | 34 | }; |
34 | 35 | ||
35 | struct wm_adsp { | 36 | struct wm_adsp { |
@@ -55,6 +56,8 @@ struct wm_adsp { | |||
55 | bool running; | 56 | bool running; |
56 | 57 | ||
57 | struct regulator *dvfs; | 58 | struct regulator *dvfs; |
59 | |||
60 | struct wm_coeff *wm_coeff; | ||
58 | }; | 61 | }; |
59 | 62 | ||
60 | #define WM_ADSP1(wname, num) \ | 63 | #define WM_ADSP1(wname, num) \ |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index c6fa03e2114a..bd40849454a8 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -501,13 +501,12 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) | |||
501 | imx_ssi_ac97_read(ac97, 0); | 501 | imx_ssi_ac97_read(ac97, 0); |
502 | } | 502 | } |
503 | 503 | ||
504 | struct snd_ac97_bus_ops soc_ac97_ops = { | 504 | static struct snd_ac97_bus_ops imx_ssi_ac97_ops = { |
505 | .read = imx_ssi_ac97_read, | 505 | .read = imx_ssi_ac97_read, |
506 | .write = imx_ssi_ac97_write, | 506 | .write = imx_ssi_ac97_write, |
507 | .reset = imx_ssi_ac97_reset, | 507 | .reset = imx_ssi_ac97_reset, |
508 | .warm_reset = imx_ssi_ac97_warm_reset | 508 | .warm_reset = imx_ssi_ac97_warm_reset |
509 | }; | 509 | }; |
510 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
511 | 510 | ||
512 | static int imx_ssi_probe(struct platform_device *pdev) | 511 | static int imx_ssi_probe(struct platform_device *pdev) |
513 | { | 512 | { |
@@ -583,6 +582,12 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
583 | 582 | ||
584 | platform_set_drvdata(pdev, ssi); | 583 | platform_set_drvdata(pdev, ssi); |
585 | 584 | ||
585 | ret = snd_soc_set_ac97_ops(&imx_ssi_ac97_ops); | ||
586 | if (ret != 0) { | ||
587 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
588 | goto failed_register; | ||
589 | } | ||
590 | |||
586 | ret = snd_soc_register_component(&pdev->dev, &imx_component, | 591 | ret = snd_soc_register_component(&pdev->dev, &imx_component, |
587 | dai, 1); | 592 | dai, 1); |
588 | if (ret) { | 593 | if (ret) { |
@@ -630,6 +635,7 @@ failed_register: | |||
630 | release_mem_region(res->start, resource_size(res)); | 635 | release_mem_region(res->start, resource_size(res)); |
631 | clk_disable_unprepare(ssi->clk); | 636 | clk_disable_unprepare(ssi->clk); |
632 | failed_clk: | 637 | failed_clk: |
638 | snd_soc_set_ac97_ops(NULL); | ||
633 | 639 | ||
634 | return ret; | 640 | return ret; |
635 | } | 641 | } |
@@ -649,6 +655,7 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
649 | 655 | ||
650 | release_mem_region(res->start, resource_size(res)); | 656 | release_mem_region(res->start, resource_size(res)); |
651 | clk_disable_unprepare(ssi->clk); | 657 | clk_disable_unprepare(ssi->clk); |
658 | snd_soc_set_ac97_ops(NULL); | ||
652 | 659 | ||
653 | return 0; | 660 | return 0; |
654 | } | 661 | } |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 4141b35ef0bb..3ef7a0c92efa 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -131,13 +131,12 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
131 | psc_ac97_warm_reset(ac97); | 131 | psc_ac97_warm_reset(ac97); |
132 | } | 132 | } |
133 | 133 | ||
134 | struct snd_ac97_bus_ops soc_ac97_ops = { | 134 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
135 | .read = psc_ac97_read, | 135 | .read = psc_ac97_read, |
136 | .write = psc_ac97_write, | 136 | .write = psc_ac97_write, |
137 | .reset = psc_ac97_cold_reset, | 137 | .reset = psc_ac97_cold_reset, |
138 | .warm_reset = psc_ac97_warm_reset, | 138 | .warm_reset = psc_ac97_warm_reset, |
139 | }; | 139 | }; |
140 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
141 | 140 | ||
142 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, | 141 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, |
143 | struct snd_pcm_hw_params *params, | 142 | struct snd_pcm_hw_params *params, |
@@ -290,6 +289,12 @@ static int psc_ac97_of_probe(struct platform_device *op) | |||
290 | if (rc != 0) | 289 | if (rc != 0) |
291 | return rc; | 290 | return rc; |
292 | 291 | ||
292 | rc = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
293 | if (rc != 0) { | ||
294 | dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
295 | return rc; | ||
296 | } | ||
297 | |||
293 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, | 298 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, |
294 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | 299 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
295 | if (rc != 0) { | 300 | if (rc != 0) { |
@@ -318,6 +323,7 @@ static int psc_ac97_of_remove(struct platform_device *op) | |||
318 | { | 323 | { |
319 | mpc5200_audio_dma_destroy(op); | 324 | mpc5200_audio_dma_destroy(op); |
320 | snd_soc_unregister_component(&op->dev); | 325 | snd_soc_unregister_component(&op->dev); |
326 | snd_soc_set_ac97_ops(NULL); | ||
321 | return 0; | 327 | return 0; |
322 | } | 328 | } |
323 | 329 | ||
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index fe3285ceaf5b..f4c2417a8730 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -197,13 +197,12 @@ static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* AC97 controller operations */ | 199 | /* AC97 controller operations */ |
200 | struct snd_ac97_bus_ops soc_ac97_ops = { | 200 | static struct snd_ac97_bus_ops nuc900_ac97_ops = { |
201 | .read = nuc900_ac97_read, | 201 | .read = nuc900_ac97_read, |
202 | .write = nuc900_ac97_write, | 202 | .write = nuc900_ac97_write, |
203 | .reset = nuc900_ac97_cold_reset, | 203 | .reset = nuc900_ac97_cold_reset, |
204 | .warm_reset = nuc900_ac97_warm_reset, | 204 | .warm_reset = nuc900_ac97_warm_reset, |
205 | } | 205 | }; |
206 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
207 | 206 | ||
208 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, | 207 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, |
209 | int cmd, struct snd_soc_dai *dai) | 208 | int cmd, struct snd_soc_dai *dai) |
@@ -326,64 +325,52 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
326 | if (nuc900_ac97_data) | 325 | if (nuc900_ac97_data) |
327 | return -EBUSY; | 326 | return -EBUSY; |
328 | 327 | ||
329 | nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL); | 328 | nuc900_audio = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_audio), |
329 | GFP_KERNEL); | ||
330 | if (!nuc900_audio) | 330 | if (!nuc900_audio) |
331 | return -ENOMEM; | 331 | return -ENOMEM; |
332 | 332 | ||
333 | spin_lock_init(&nuc900_audio->lock); | 333 | spin_lock_init(&nuc900_audio->lock); |
334 | 334 | ||
335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
336 | if (!nuc900_audio->res) { | 336 | if (!nuc900_audio->res) |
337 | ret = -ENODEV; | 337 | return ret; |
338 | goto out0; | ||
339 | } | ||
340 | |||
341 | if (!request_mem_region(nuc900_audio->res->start, | ||
342 | resource_size(nuc900_audio->res), pdev->name)) { | ||
343 | ret = -EBUSY; | ||
344 | goto out0; | ||
345 | } | ||
346 | 338 | ||
347 | nuc900_audio->mmio = ioremap(nuc900_audio->res->start, | 339 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, |
348 | resource_size(nuc900_audio->res)); | 340 | nuc900_audio->res); |
349 | if (!nuc900_audio->mmio) { | 341 | if (IS_ERR(nuc900_audio->mmio)) |
350 | ret = -ENOMEM; | 342 | return PTR_ERR(nuc900_audio->mmio); |
351 | goto out1; | ||
352 | } | ||
353 | 343 | ||
354 | nuc900_audio->clk = clk_get(&pdev->dev, NULL); | 344 | nuc900_audio->clk = devm_clk_get(&pdev->dev, NULL); |
355 | if (IS_ERR(nuc900_audio->clk)) { | 345 | if (IS_ERR(nuc900_audio->clk)) { |
356 | ret = PTR_ERR(nuc900_audio->clk); | 346 | ret = PTR_ERR(nuc900_audio->clk); |
357 | goto out2; | 347 | goto out; |
358 | } | 348 | } |
359 | 349 | ||
360 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); | 350 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); |
361 | if (!nuc900_audio->irq_num) { | 351 | if (!nuc900_audio->irq_num) { |
362 | ret = -EBUSY; | 352 | ret = -EBUSY; |
363 | goto out3; | 353 | goto out; |
364 | } | 354 | } |
365 | 355 | ||
366 | nuc900_ac97_data = nuc900_audio; | 356 | nuc900_ac97_data = nuc900_audio; |
367 | 357 | ||
358 | ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); | ||
359 | if (ret) | ||
360 | goto out; | ||
361 | |||
368 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, | 362 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, |
369 | &nuc900_ac97_dai, 1); | 363 | &nuc900_ac97_dai, 1); |
370 | if (ret) | 364 | if (ret) |
371 | goto out3; | 365 | goto out; |
372 | 366 | ||
373 | /* enbale ac97 multifunction pin */ | 367 | /* enbale ac97 multifunction pin */ |
374 | mfp_set_groupg(nuc900_audio->dev, NULL); | 368 | mfp_set_groupg(nuc900_audio->dev, NULL); |
375 | 369 | ||
376 | return 0; | 370 | return 0; |
377 | 371 | ||
378 | out3: | 372 | out: |
379 | clk_put(nuc900_audio->clk); | 373 | snd_soc_set_ac97_ops(NULL); |
380 | out2: | ||
381 | iounmap(nuc900_audio->mmio); | ||
382 | out1: | ||
383 | release_mem_region(nuc900_audio->res->start, | ||
384 | resource_size(nuc900_audio->res)); | ||
385 | out0: | ||
386 | kfree(nuc900_audio); | ||
387 | return ret; | 374 | return ret; |
388 | } | 375 | } |
389 | 376 | ||
@@ -391,13 +378,8 @@ static int nuc900_ac97_drvremove(struct platform_device *pdev) | |||
391 | { | 378 | { |
392 | snd_soc_unregister_component(&pdev->dev); | 379 | snd_soc_unregister_component(&pdev->dev); |
393 | 380 | ||
394 | clk_put(nuc900_ac97_data->clk); | ||
395 | iounmap(nuc900_ac97_data->mmio); | ||
396 | release_mem_region(nuc900_ac97_data->res->start, | ||
397 | resource_size(nuc900_ac97_data->res)); | ||
398 | |||
399 | kfree(nuc900_ac97_data); | ||
400 | nuc900_ac97_data = NULL; | 381 | nuc900_ac97_data = NULL; |
382 | snd_soc_set_ac97_ops(NULL); | ||
401 | 383 | ||
402 | return 0; | 384 | return 0; |
403 | } | 385 | } |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 57ea8e6c5488..1475515712e6 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -41,13 +41,12 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
41 | pxa2xx_ac97_finish_reset(ac97); | 41 | pxa2xx_ac97_finish_reset(ac97); |
42 | } | 42 | } |
43 | 43 | ||
44 | struct snd_ac97_bus_ops soc_ac97_ops = { | 44 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { |
45 | .read = pxa2xx_ac97_read, | 45 | .read = pxa2xx_ac97_read, |
46 | .write = pxa2xx_ac97_write, | 46 | .write = pxa2xx_ac97_write, |
47 | .warm_reset = pxa2xx_ac97_warm_reset, | 47 | .warm_reset = pxa2xx_ac97_warm_reset, |
48 | .reset = pxa2xx_ac97_cold_reset, | 48 | .reset = pxa2xx_ac97_cold_reset, |
49 | }; | 49 | }; |
50 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
51 | 50 | ||
52 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { | 51 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { |
53 | .name = "AC97 PCM Stereo out", | 52 | .name = "AC97 PCM Stereo out", |
@@ -239,11 +238,17 @@ static const struct snd_soc_component_driver pxa_ac97_component = { | |||
239 | 238 | ||
240 | static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | 239 | static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) |
241 | { | 240 | { |
241 | int ret; | ||
242 | |||
242 | if (pdev->id != -1) { | 243 | if (pdev->id != -1) { |
243 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); | 244 | dev_err(&pdev->dev, "PXA2xx has only one AC97 port.\n"); |
244 | return -ENXIO; | 245 | return -ENXIO; |
245 | } | 246 | } |
246 | 247 | ||
248 | ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); | ||
249 | if (ret != 0) | ||
250 | return ret; | ||
251 | |||
247 | /* Punt most of the init to the SoC probe; we may need the machine | 252 | /* Punt most of the init to the SoC probe; we may need the machine |
248 | * driver to do interesting things with the clocking to get us up | 253 | * driver to do interesting things with the clocking to get us up |
249 | * and running. | 254 | * and running. |
@@ -255,6 +260,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
255 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) | 260 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
256 | { | 261 | { |
257 | snd_soc_unregister_component(&pdev->dev); | 262 | snd_soc_unregister_component(&pdev->dev); |
263 | snd_soc_set_ac97_ops(NULL); | ||
258 | return 0; | 264 | return 0; |
259 | } | 265 | } |
260 | 266 | ||
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h index eda891e6f31b..a49c21ba3842 100644 --- a/sound/soc/pxa/pxa2xx-ac97.h +++ b/sound/soc/pxa/pxa2xx-ac97.h | |||
@@ -14,7 +14,4 @@ | |||
14 | #define PXA2XX_DAI_AC97_AUX 1 | 14 | #define PXA2XX_DAI_AC97_AUX 1 |
15 | #define PXA2XX_DAI_AC97_MIC 2 | 15 | #define PXA2XX_DAI_AC97_MIC 2 |
16 | 16 | ||
17 | /* platform data */ | ||
18 | extern struct snd_ac97_bus_ops pxa2xx_ac97_ops; | ||
19 | |||
20 | #endif | 17 | #endif |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index cb88ead98917..2dd623fa3882 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -214,13 +214,12 @@ static irqreturn_t s3c_ac97_irq(int irq, void *dev_id) | |||
214 | return IRQ_HANDLED; | 214 | return IRQ_HANDLED; |
215 | } | 215 | } |
216 | 216 | ||
217 | struct snd_ac97_bus_ops soc_ac97_ops = { | 217 | static struct snd_ac97_bus_ops s3c_ac97_ops = { |
218 | .read = s3c_ac97_read, | 218 | .read = s3c_ac97_read, |
219 | .write = s3c_ac97_write, | 219 | .write = s3c_ac97_write, |
220 | .warm_reset = s3c_ac97_warm_reset, | 220 | .warm_reset = s3c_ac97_warm_reset, |
221 | .reset = s3c_ac97_cold_reset, | 221 | .reset = s3c_ac97_cold_reset, |
222 | }; | 222 | }; |
223 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
224 | 223 | ||
225 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | 224 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, |
226 | struct snd_pcm_hw_params *params, | 225 | struct snd_pcm_hw_params *params, |
@@ -417,11 +416,9 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
417 | return -ENXIO; | 416 | return -ENXIO; |
418 | } | 417 | } |
419 | 418 | ||
420 | if (!request_mem_region(mem_res->start, | 419 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); |
421 | resource_size(mem_res), "ac97")) { | 420 | if (IS_ERR(s3c_ac97.regs)) |
422 | dev_err(&pdev->dev, "Unable to request register region\n"); | 421 | return PTR_ERR(s3c_ac97.regs); |
423 | return -EBUSY; | ||
424 | } | ||
425 | 422 | ||
426 | s3c_ac97_pcm_out.channel = dmatx_res->start; | 423 | s3c_ac97_pcm_out.channel = dmatx_res->start; |
427 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; | 424 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; |
@@ -433,14 +430,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
433 | init_completion(&s3c_ac97.done); | 430 | init_completion(&s3c_ac97.done); |
434 | mutex_init(&s3c_ac97.lock); | 431 | mutex_init(&s3c_ac97.lock); |
435 | 432 | ||
436 | s3c_ac97.regs = ioremap(mem_res->start, resource_size(mem_res)); | 433 | s3c_ac97.ac97_clk = devm_clk_get(&pdev->dev, "ac97"); |
437 | if (s3c_ac97.regs == NULL) { | ||
438 | dev_err(&pdev->dev, "Unable to ioremap register region\n"); | ||
439 | ret = -ENXIO; | ||
440 | goto err1; | ||
441 | } | ||
442 | |||
443 | s3c_ac97.ac97_clk = clk_get(&pdev->dev, "ac97"); | ||
444 | if (IS_ERR(s3c_ac97.ac97_clk)) { | 434 | if (IS_ERR(s3c_ac97.ac97_clk)) { |
445 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); | 435 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); |
446 | ret = -ENODEV; | 436 | ret = -ENODEV; |
@@ -461,6 +451,12 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
461 | goto err4; | 451 | goto err4; |
462 | } | 452 | } |
463 | 453 | ||
454 | ret = snd_soc_set_ac97_ops(&s3c_ac97_ops); | ||
455 | if (ret != 0) { | ||
456 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
457 | goto err4; | ||
458 | } | ||
459 | |||
464 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, | 460 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, |
465 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | 461 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); |
466 | if (ret) | 462 | if (ret) |
@@ -480,18 +476,14 @@ err5: | |||
480 | err4: | 476 | err4: |
481 | err3: | 477 | err3: |
482 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 478 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
483 | clk_put(s3c_ac97.ac97_clk); | ||
484 | err2: | 479 | err2: |
485 | iounmap(s3c_ac97.regs); | 480 | snd_soc_set_ac97_ops(NULL); |
486 | err1: | ||
487 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
488 | |||
489 | return ret; | 481 | return ret; |
490 | } | 482 | } |
491 | 483 | ||
492 | static int s3c_ac97_remove(struct platform_device *pdev) | 484 | static int s3c_ac97_remove(struct platform_device *pdev) |
493 | { | 485 | { |
494 | struct resource *mem_res, *irq_res; | 486 | struct resource *irq_res; |
495 | 487 | ||
496 | asoc_dma_platform_unregister(&pdev->dev); | 488 | asoc_dma_platform_unregister(&pdev->dev); |
497 | snd_soc_unregister_component(&pdev->dev); | 489 | snd_soc_unregister_component(&pdev->dev); |
@@ -501,13 +493,7 @@ static int s3c_ac97_remove(struct platform_device *pdev) | |||
501 | free_irq(irq_res->start, NULL); | 493 | free_irq(irq_res->start, NULL); |
502 | 494 | ||
503 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 495 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
504 | clk_put(s3c_ac97.ac97_clk); | 496 | snd_soc_set_ac97_ops(NULL); |
505 | |||
506 | iounmap(s3c_ac97.regs); | ||
507 | |||
508 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
509 | if (mem_res) | ||
510 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
511 | 497 | ||
512 | return 0; | 498 | return 0; |
513 | } | 499 | } |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index af19f77b7bf0..0af2e4dfd139 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -227,13 +227,12 @@ static void hac_ac97_coldrst(struct snd_ac97 *ac97) | |||
227 | hac_ac97_warmrst(ac97); | 227 | hac_ac97_warmrst(ac97); |
228 | } | 228 | } |
229 | 229 | ||
230 | struct snd_ac97_bus_ops soc_ac97_ops = { | 230 | static struct snd_ac97_bus_ops hac_ac97_ops = { |
231 | .read = hac_ac97_read, | 231 | .read = hac_ac97_read, |
232 | .write = hac_ac97_write, | 232 | .write = hac_ac97_write, |
233 | .reset = hac_ac97_coldrst, | 233 | .reset = hac_ac97_coldrst, |
234 | .warm_reset = hac_ac97_warmrst, | 234 | .warm_reset = hac_ac97_warmrst, |
235 | }; | 235 | }; |
236 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
237 | 236 | ||
238 | static int hac_hw_params(struct snd_pcm_substream *substream, | 237 | static int hac_hw_params(struct snd_pcm_substream *substream, |
239 | struct snd_pcm_hw_params *params, | 238 | struct snd_pcm_hw_params *params, |
@@ -316,6 +315,10 @@ static const struct snd_soc_component_driver sh4_hac_component = { | |||
316 | 315 | ||
317 | static int hac_soc_platform_probe(struct platform_device *pdev) | 316 | static int hac_soc_platform_probe(struct platform_device *pdev) |
318 | { | 317 | { |
318 | ret = snd_soc_set_ac97_ops(&hac_ac97_ops); | ||
319 | if (ret != 0) | ||
320 | return ret; | ||
321 | |||
319 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, | 322 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, |
320 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); |
321 | } | 324 | } |
@@ -323,6 +326,7 @@ static int hac_soc_platform_probe(struct platform_device *pdev) | |||
323 | static int hac_soc_platform_remove(struct platform_device *pdev) | 326 | static int hac_soc_platform_remove(struct platform_device *pdev) |
324 | { | 327 | { |
325 | snd_soc_unregister_component(&pdev->dev); | 328 | snd_soc_unregister_component(&pdev->dev); |
329 | snd_soc_set_ac97_ops(NULL); | ||
326 | return 0; | 330 | return 0; |
327 | } | 331 | } |
328 | 332 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d56bbea6e75e..0a8a5f50b466 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2079,6 +2079,23 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
2079 | } | 2079 | } |
2080 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 2080 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
2081 | 2081 | ||
2082 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
2083 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
2084 | |||
2085 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
2086 | { | ||
2087 | if (ops == soc_ac97_ops) | ||
2088 | return 0; | ||
2089 | |||
2090 | if (soc_ac97_ops && ops) | ||
2091 | return -EBUSY; | ||
2092 | |||
2093 | soc_ac97_ops = ops; | ||
2094 | |||
2095 | return 0; | ||
2096 | } | ||
2097 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
2098 | |||
2082 | /** | 2099 | /** |
2083 | * snd_soc_free_ac97_codec - free AC97 codec device | 2100 | * snd_soc_free_ac97_codec - free AC97 codec device |
2084 | * @codec: audio codec | 2101 | * @codec: audio codec |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 2f70ea7f6618..e58233f7df61 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -142,13 +142,12 @@ static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, | |||
142 | } while (!time_after(jiffies, timeout)); | 142 | } while (!time_after(jiffies, timeout)); |
143 | } | 143 | } |
144 | 144 | ||
145 | struct snd_ac97_bus_ops soc_ac97_ops = { | 145 | static struct snd_ac97_bus_ops tegra20_ac97_ops = { |
146 | .read = tegra20_ac97_codec_read, | 146 | .read = tegra20_ac97_codec_read, |
147 | .write = tegra20_ac97_codec_write, | 147 | .write = tegra20_ac97_codec_write, |
148 | .reset = tegra20_ac97_codec_reset, | 148 | .reset = tegra20_ac97_codec_reset, |
149 | .warm_reset = tegra20_ac97_codec_warm_reset, | 149 | .warm_reset = tegra20_ac97_codec_warm_reset, |
150 | }; | 150 | }; |
151 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
152 | 151 | ||
153 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) | 152 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) |
154 | { | 153 | { |
@@ -313,7 +312,7 @@ static const struct regmap_config tegra20_ac97_regmap_config = { | |||
313 | static int tegra20_ac97_platform_probe(struct platform_device *pdev) | 312 | static int tegra20_ac97_platform_probe(struct platform_device *pdev) |
314 | { | 313 | { |
315 | struct tegra20_ac97 *ac97; | 314 | struct tegra20_ac97 *ac97; |
316 | struct resource *mem, *memregion; | 315 | struct resource *mem; |
317 | u32 of_dma[2]; | 316 | u32 of_dma[2]; |
318 | void __iomem *regs; | 317 | void __iomem *regs; |
319 | int ret = 0; | 318 | int ret = 0; |
@@ -327,7 +326,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
327 | } | 326 | } |
328 | dev_set_drvdata(&pdev->dev, ac97); | 327 | dev_set_drvdata(&pdev->dev, ac97); |
329 | 328 | ||
330 | ac97->clk_ac97 = clk_get(&pdev->dev, NULL); | 329 | ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); |
331 | if (IS_ERR(ac97->clk_ac97)) { | 330 | if (IS_ERR(ac97->clk_ac97)) { |
332 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); | 331 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); |
333 | ret = PTR_ERR(ac97->clk_ac97); | 332 | ret = PTR_ERR(ac97->clk_ac97); |
@@ -341,18 +340,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
341 | goto err_clk_put; | 340 | goto err_clk_put; |
342 | } | 341 | } |
343 | 342 | ||
344 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | 343 | regs = devm_ioremap_resource(&pdev->dev, mem); |
345 | resource_size(mem), DRV_NAME); | 344 | if (IS_ERR(regs)) { |
346 | if (!memregion) { | 345 | ret = PTR_ERR(regs); |
347 | dev_err(&pdev->dev, "Memory region already claimed\n"); | ||
348 | ret = -EBUSY; | ||
349 | goto err_clk_put; | ||
350 | } | ||
351 | |||
352 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
353 | if (!regs) { | ||
354 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
355 | ret = -ENOMEM; | ||
356 | goto err_clk_put; | 346 | goto err_clk_put; |
357 | } | 347 | } |
358 | 348 | ||
@@ -403,23 +393,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
403 | ac97->capture_dma_data.maxburst = 4; | 393 | ac97->capture_dma_data.maxburst = 4; |
404 | ac97->capture_dma_data.slave_id = of_dma[0]; | 394 | ac97->capture_dma_data.slave_id = of_dma[0]; |
405 | 395 | ||
406 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
407 | &tegra20_ac97_dai, 1); | ||
408 | if (ret) { | ||
409 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
410 | ret = -ENOMEM; | ||
411 | goto err_clk_put; | ||
412 | } | ||
413 | |||
414 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
415 | if (ret) { | ||
416 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
417 | goto err_unregister_component; | ||
418 | } | ||
419 | |||
420 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); | 396 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); |
421 | if (ret) | 397 | if (ret) |
422 | goto err_unregister_pcm; | 398 | goto err_clk_put; |
423 | 399 | ||
424 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); | 400 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); |
425 | if (ret) | 401 | if (ret) |
@@ -431,20 +407,40 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
431 | goto err_asoc_utils_fini; | 407 | goto err_asoc_utils_fini; |
432 | } | 408 | } |
433 | 409 | ||
410 | ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); | ||
411 | if (ret) { | ||
412 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
413 | goto err_asoc_utils_fini; | ||
414 | } | ||
415 | |||
416 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
417 | &tegra20_ac97_dai, 1); | ||
418 | if (ret) { | ||
419 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
420 | ret = -ENOMEM; | ||
421 | goto err_asoc_utils_fini; | ||
422 | } | ||
423 | |||
424 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
425 | if (ret) { | ||
426 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
427 | goto err_unregister_component; | ||
428 | } | ||
429 | |||
434 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ | 430 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ |
435 | workdata = ac97; | 431 | workdata = ac97; |
436 | 432 | ||
437 | return 0; | 433 | return 0; |
438 | 434 | ||
439 | err_asoc_utils_fini: | ||
440 | tegra_asoc_utils_fini(&ac97->util_data); | ||
441 | err_unregister_pcm: | 435 | err_unregister_pcm: |
442 | tegra_pcm_platform_unregister(&pdev->dev); | 436 | tegra_pcm_platform_unregister(&pdev->dev); |
443 | err_unregister_component: | 437 | err_unregister_component: |
444 | snd_soc_unregister_component(&pdev->dev); | 438 | snd_soc_unregister_component(&pdev->dev); |
439 | err_asoc_utils_fini: | ||
440 | tegra_asoc_utils_fini(&ac97->util_data); | ||
445 | err_clk_put: | 441 | err_clk_put: |
446 | clk_put(ac97->clk_ac97); | ||
447 | err: | 442 | err: |
443 | snd_soc_set_ac97_ops(NULL); | ||
448 | return ret; | 444 | return ret; |
449 | } | 445 | } |
450 | 446 | ||
@@ -458,7 +454,8 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) | |||
458 | tegra_asoc_utils_fini(&ac97->util_data); | 454 | tegra_asoc_utils_fini(&ac97->util_data); |
459 | 455 | ||
460 | clk_disable_unprepare(ac97->clk_ac97); | 456 | clk_disable_unprepare(ac97->clk_ac97); |
461 | clk_put(ac97->clk_ac97); | 457 | |
458 | snd_soc_set_ac97_ops(NULL); | ||
462 | 459 | ||
463 | return 0; | 460 | return 0; |
464 | } | 461 | } |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 8a2840304d28..4bcce8a3cded 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -119,12 +119,11 @@ static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | /* AC97 controller operations */ | 121 | /* AC97 controller operations */ |
122 | struct snd_ac97_bus_ops soc_ac97_ops = { | 122 | static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { |
123 | .read = txx9aclc_ac97_read, | 123 | .read = txx9aclc_ac97_read, |
124 | .write = txx9aclc_ac97_write, | 124 | .write = txx9aclc_ac97_write, |
125 | .reset = txx9aclc_ac97_cold_reset, | 125 | .reset = txx9aclc_ac97_cold_reset, |
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
128 | 127 | ||
129 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) | 128 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) |
130 | { | 129 | { |
@@ -188,9 +187,9 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
188 | if (!r) | 187 | if (!r) |
189 | return -EBUSY; | 188 | return -EBUSY; |
190 | 189 | ||
191 | if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), | 190 | drvdata->base = devm_ioremap_resource(&pdev->dev, r); |
192 | dev_name(&pdev->dev))) | 191 | if (IS_ERR(drvdata->base)) |
193 | return -EBUSY; | 192 | return PTR_ERR(drvdata->base); |
194 | 193 | ||
195 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | 194 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); |
196 | if (!drvdata) | 195 | if (!drvdata) |
@@ -201,14 +200,15 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
201 | r->start >= TXX9_DIRECTMAP_BASE && | 200 | r->start >= TXX9_DIRECTMAP_BASE && |
202 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) | 201 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) |
203 | drvdata->physbase |= 0xf00000000ull; | 202 | drvdata->physbase |= 0xf00000000ull; |
204 | drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); | ||
205 | if (!drvdata->base) | ||
206 | return -EBUSY; | ||
207 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, | 203 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, |
208 | 0, dev_name(&pdev->dev), drvdata); | 204 | 0, dev_name(&pdev->dev), drvdata); |
209 | if (err < 0) | 205 | if (err < 0) |
210 | return err; | 206 | return err; |
211 | 207 | ||
208 | err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); | ||
209 | if (err < 0) | ||
210 | return err; | ||
211 | |||
212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, | 212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, |
213 | &txx9aclc_ac97_dai, 1); | 213 | &txx9aclc_ac97_dai, 1); |
214 | } | 214 | } |
@@ -216,6 +216,7 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) | 216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
217 | { | 217 | { |
218 | snd_soc_unregister_component(&pdev->dev); | 218 | snd_soc_unregister_component(&pdev->dev); |
219 | snd_soc_set_ac97_ops(NULL); | ||
219 | return 0; | 220 | return 0; |
220 | } | 221 | } |
221 | 222 | ||