aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/au1x/dbdma2.c117
-rw-r--r--sound/soc/au1x/psc-ac97.c194
-rw-r--r--sound/soc/au1x/psc-i2s.c189
-rw-r--r--sound/soc/au1x/psc.h7
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1836.c11
-rw-r--r--sound/soc/codecs/ad1938.c11
-rw-r--r--sound/soc/codecs/ad1980.c5
-rw-r--r--sound/soc/codecs/ad73311.c8
-rw-r--r--sound/soc/codecs/ak4104.c8
-rw-r--r--sound/soc/codecs/ak4535.c8
-rw-r--r--sound/soc/codecs/ak4642.c9
-rw-r--r--sound/soc/codecs/ak4671.c9
-rw-r--r--sound/soc/codecs/cs4270.c8
-rw-r--r--sound/soc/codecs/cx20442.c11
-rw-r--r--sound/soc/codecs/pcm3008.c9
-rw-r--r--sound/soc/codecs/ssm2602.c8
-rw-r--r--sound/soc/codecs/stac9766.c3
-rw-r--r--sound/soc/codecs/tlv320aic23.c8
-rw-r--r--sound/soc/codecs/tlv320aic26.c11
-rw-r--r--sound/soc/codecs/tlv320aic3x.c10
-rw-r--r--sound/soc/codecs/tlv320dac33.c10
-rw-r--r--sound/soc/codecs/twl4030.c198
-rw-r--r--sound/soc/codecs/uda134x.c9
-rw-r--r--sound/soc/codecs/uda1380.c8
-rw-r--r--sound/soc/codecs/wm8350.c11
-rw-r--r--sound/soc/codecs/wm8400.c11
-rw-r--r--sound/soc/codecs/wm8510.c9
-rw-r--r--sound/soc/codecs/wm8523.c8
-rw-r--r--sound/soc/codecs/wm8580.c8
-rw-r--r--sound/soc/codecs/wm8711.c8
-rw-r--r--sound/soc/codecs/wm8727.c135
-rw-r--r--sound/soc/codecs/wm8727.h21
-rw-r--r--sound/soc/codecs/wm8728.c8
-rw-r--r--sound/soc/codecs/wm8731.c59
-rw-r--r--sound/soc/codecs/wm8750.c8
-rw-r--r--sound/soc/codecs/wm8753.c9
-rw-r--r--sound/soc/codecs/wm8776.c9
-rw-r--r--sound/soc/codecs/wm8900.c11
-rw-r--r--sound/soc/codecs/wm8903.c9
-rw-r--r--sound/soc/codecs/wm8940.c6
-rw-r--r--sound/soc/codecs/wm8960.c8
-rw-r--r--sound/soc/codecs/wm8961.c9
-rw-r--r--sound/soc/codecs/wm8971.c9
-rw-r--r--sound/soc/codecs/wm8974.c8
-rw-r--r--sound/soc/codecs/wm8988.c9
-rw-r--r--sound/soc/codecs/wm8990.c9
-rw-r--r--sound/soc/codecs/wm8993.c9
-rw-r--r--sound/soc/codecs/wm9081.c9
-rw-r--r--sound/soc/codecs/wm9705.c8
-rw-r--r--sound/soc/codecs/wm9712.c8
-rw-r--r--sound/soc/codecs/wm9713.c7
-rw-r--r--sound/soc/fsl/mpc5200_dma.c98
-rw-r--r--sound/soc/fsl/mpc5200_dma.h24
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c39
-rw-r--r--sound/soc/omap/Kconfig22
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/am3517evm.c202
-rw-r--r--sound/soc/omap/omap-mcbsp.c63
-rw-r--r--sound/soc/omap/omap3evm.c7
-rw-r--r--sound/soc/omap/omap3pandora.c24
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c17
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c2
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c15
-rw-r--r--sound/soc/sh/Kconfig1
-rw-r--r--sound/soc/sh/fsi.c234
-rw-r--r--sound/soc/soc-core.c516
69 files changed, 1367 insertions, 1200 deletions
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 594c6c5b7838..fe9f4657c959 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -333,6 +333,30 @@ static int au1xpsc_pcm_new(struct snd_card *card,
333 333
334static int au1xpsc_pcm_probe(struct platform_device *pdev) 334static int au1xpsc_pcm_probe(struct platform_device *pdev)
335{ 335{
336 if (!au1xpsc_audio_pcmdma[PCM_TX] || !au1xpsc_audio_pcmdma[PCM_RX])
337 return -ENODEV;
338
339 return 0;
340}
341
342static int au1xpsc_pcm_remove(struct platform_device *pdev)
343{
344 return 0;
345}
346
347/* au1xpsc audio platform */
348struct snd_soc_platform au1xpsc_soc_platform = {
349 .name = "au1xpsc-pcm-dbdma",
350 .probe = au1xpsc_pcm_probe,
351 .remove = au1xpsc_pcm_remove,
352 .pcm_ops = &au1xpsc_pcm_ops,
353 .pcm_new = au1xpsc_pcm_new,
354 .pcm_free = au1xpsc_pcm_free_dma_buffers,
355};
356EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
357
358static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
359{
336 struct resource *r; 360 struct resource *r;
337 int ret; 361 int ret;
338 362
@@ -365,7 +389,9 @@ static int au1xpsc_pcm_probe(struct platform_device *pdev)
365 } 389 }
366 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start; 390 (au1xpsc_audio_pcmdma[PCM_RX])->ddma_id = r->start;
367 391
368 return 0; 392 ret = snd_soc_register_platform(&au1xpsc_soc_platform);
393 if (!ret)
394 return ret;
369 395
370out2: 396out2:
371 kfree(au1xpsc_audio_pcmdma[PCM_RX]); 397 kfree(au1xpsc_audio_pcmdma[PCM_RX]);
@@ -376,10 +402,12 @@ out1:
376 return ret; 402 return ret;
377} 403}
378 404
379static int au1xpsc_pcm_remove(struct platform_device *pdev) 405static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
380{ 406{
381 int i; 407 int i;
382 408
409 snd_soc_unregister_platform(&au1xpsc_soc_platform);
410
383 for (i = 0; i < 2; i++) { 411 for (i = 0; i < 2; i++) {
384 if (au1xpsc_audio_pcmdma[i]) { 412 if (au1xpsc_audio_pcmdma[i]) {
385 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]); 413 au1x_pcm_dbdma_free(au1xpsc_audio_pcmdma[i]);
@@ -391,32 +419,83 @@ static int au1xpsc_pcm_remove(struct platform_device *pdev)
391 return 0; 419 return 0;
392} 420}
393 421
394/* au1xpsc audio platform */ 422static struct platform_driver au1xpsc_pcm_driver = {
395struct snd_soc_platform au1xpsc_soc_platform = { 423 .driver = {
396 .name = "au1xpsc-pcm-dbdma", 424 .name = "au1xpsc-pcm",
397 .probe = au1xpsc_pcm_probe, 425 .owner = THIS_MODULE,
398 .remove = au1xpsc_pcm_remove, 426 },
399 .pcm_ops = &au1xpsc_pcm_ops, 427 .probe = au1xpsc_pcm_drvprobe,
400 .pcm_new = au1xpsc_pcm_new, 428 .remove = __devexit_p(au1xpsc_pcm_drvremove),
401 .pcm_free = au1xpsc_pcm_free_dma_buffers,
402}; 429};
403EXPORT_SYMBOL_GPL(au1xpsc_soc_platform);
404 430
405static int __init au1xpsc_audio_dbdma_init(void) 431static int __init au1xpsc_audio_dbdma_load(void)
406{ 432{
407 au1xpsc_audio_pcmdma[PCM_TX] = NULL; 433 au1xpsc_audio_pcmdma[PCM_TX] = NULL;
408 au1xpsc_audio_pcmdma[PCM_RX] = NULL; 434 au1xpsc_audio_pcmdma[PCM_RX] = NULL;
409 return snd_soc_register_platform(&au1xpsc_soc_platform); 435 return platform_driver_register(&au1xpsc_pcm_driver);
410} 436}
411 437
412static void __exit au1xpsc_audio_dbdma_exit(void) 438static void __exit au1xpsc_audio_dbdma_unload(void)
413{ 439{
414 snd_soc_unregister_platform(&au1xpsc_soc_platform); 440 platform_driver_unregister(&au1xpsc_pcm_driver);
441}
442
443module_init(au1xpsc_audio_dbdma_load);
444module_exit(au1xpsc_audio_dbdma_unload);
445
446
447struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
448{
449 struct resource *res, *r;
450 struct platform_device *pd;
451 int id[2];
452 int ret;
453
454 r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
455 if (!r)
456 return NULL;
457 id[0] = r->start;
458
459 r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
460 if (!r)
461 return NULL;
462 id[1] = r->start;
463
464 res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
465 if (!res)
466 return NULL;
467
468 res[0].start = res[0].end = id[0];
469 res[1].start = res[1].end = id[1];
470 res[0].flags = res[1].flags = IORESOURCE_DMA;
471
472 pd = platform_device_alloc("au1xpsc-pcm", -1);
473 if (!pd)
474 goto out;
475
476 pd->resource = res;
477 pd->num_resources = 2;
478
479 ret = platform_device_add(pd);
480 if (!ret)
481 return pd;
482
483out:
484 kfree(res);
485 return NULL;
415} 486}
487EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
416 488
417module_init(au1xpsc_audio_dbdma_init); 489void au1xpsc_pcm_destroy(struct platform_device *dmapd)
418module_exit(au1xpsc_audio_dbdma_exit); 490{
491 if (dmapd) {
492 kfree(dmapd->resource);
493 dmapd->resource = NULL;
494 platform_device_unregister(dmapd);
495 }
496}
497EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
419 498
420MODULE_LICENSE("GPL"); 499MODULE_LICENSE("GPL");
421MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); 500MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
422MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 501MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index 2a06a9c548af..340311d7fed5 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -317,19 +317,55 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
317static int au1xpsc_ac97_probe(struct platform_device *pdev, 317static int au1xpsc_ac97_probe(struct platform_device *pdev,
318 struct snd_soc_dai *dai) 318 struct snd_soc_dai *dai)
319{ 319{
320 return au1xpsc_ac97_workdata ? 0 : -ENODEV;
321}
322
323static void au1xpsc_ac97_remove(struct platform_device *pdev,
324 struct snd_soc_dai *dai)
325{
326}
327
328static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
329 .trigger = au1xpsc_ac97_trigger,
330 .hw_params = au1xpsc_ac97_hw_params,
331};
332
333struct snd_soc_dai au1xpsc_ac97_dai = {
334 .name = "au1xpsc_ac97",
335 .ac97_control = 1,
336 .probe = au1xpsc_ac97_probe,
337 .remove = au1xpsc_ac97_remove,
338 .playback = {
339 .rates = AC97_RATES,
340 .formats = AC97_FMTS,
341 .channels_min = 2,
342 .channels_max = 2,
343 },
344 .capture = {
345 .rates = AC97_RATES,
346 .formats = AC97_FMTS,
347 .channels_min = 2,
348 .channels_max = 2,
349 },
350 .ops = &au1xpsc_ac97_dai_ops,
351};
352EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
353
354static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
355{
320 int ret; 356 int ret;
321 struct resource *r; 357 struct resource *r;
322 unsigned long sel; 358 unsigned long sel;
359 struct au1xpsc_audio_data *wd;
323 360
324 if (au1xpsc_ac97_workdata) 361 if (au1xpsc_ac97_workdata)
325 return -EBUSY; 362 return -EBUSY;
326 363
327 au1xpsc_ac97_workdata = 364 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
328 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 365 if (!wd)
329 if (!au1xpsc_ac97_workdata)
330 return -ENOMEM; 366 return -ENOMEM;
331 367
332 mutex_init(&au1xpsc_ac97_workdata->lock); 368 mutex_init(&wd->lock);
333 369
334 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 370 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
335 if (!r) { 371 if (!r) {
@@ -338,81 +374,95 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
338 } 374 }
339 375
340 ret = -EBUSY; 376 ret = -EBUSY;
341 au1xpsc_ac97_workdata->ioarea = 377 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
342 request_mem_region(r->start, r->end - r->start + 1,
343 "au1xpsc_ac97"); 378 "au1xpsc_ac97");
344 if (!au1xpsc_ac97_workdata->ioarea) 379 if (!wd->ioarea)
345 goto out0; 380 goto out0;
346 381
347 au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff); 382 wd->mmio = ioremap(r->start, 0xffff);
348 if (!au1xpsc_ac97_workdata->mmio) 383 if (!wd->mmio)
349 goto out1; 384 goto out1;
350 385
351 /* configuration: max dma trigger threshold, enable ac97 */ 386 /* configuration: max dma trigger threshold, enable ac97 */
352 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | 387 wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
353 PSC_AC97CFG_TT_FIFO8 | 388 PSC_AC97CFG_DE_ENABLE;
354 PSC_AC97CFG_DE_ENABLE;
355 389
356 /* preserve PSC clock source set up by platform (dev.platform_data 390 /* preserve PSC clock source set up by platform */
357 * is already occupied by soc layer) 391 sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
358 */ 392 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
359 sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
360 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
361 au_sync(); 393 au_sync();
362 au_writel(0, PSC_SEL(au1xpsc_ac97_workdata)); 394 au_writel(0, PSC_SEL(wd));
363 au_sync(); 395 au_sync();
364 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata)); 396 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
365 au_sync(); 397 au_sync();
366 /* next up: cold reset. Dont check for PSC-ready now since
367 * there may not be any codec clock yet.
368 */
369 398
370 return 0; 399 ret = snd_soc_register_dai(&au1xpsc_ac97_dai);
400 if (ret)
401 goto out1;
402
403 wd->dmapd = au1xpsc_pcm_add(pdev);
404 if (wd->dmapd) {
405 platform_set_drvdata(pdev, wd);
406 au1xpsc_ac97_workdata = wd; /* MDEV */
407 return 0;
408 }
371 409
410 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
372out1: 411out1:
373 release_resource(au1xpsc_ac97_workdata->ioarea); 412 release_resource(wd->ioarea);
374 kfree(au1xpsc_ac97_workdata->ioarea); 413 kfree(wd->ioarea);
375out0: 414out0:
376 kfree(au1xpsc_ac97_workdata); 415 kfree(wd);
377 au1xpsc_ac97_workdata = NULL;
378 return ret; 416 return ret;
379} 417}
380 418
381static void au1xpsc_ac97_remove(struct platform_device *pdev, 419static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
382 struct snd_soc_dai *dai)
383{ 420{
421 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
422
423 if (wd->dmapd)
424 au1xpsc_pcm_destroy(wd->dmapd);
425
426 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
427
384 /* disable PSC completely */ 428 /* disable PSC completely */
385 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 429 au_writel(0, AC97_CFG(wd));
386 au_sync(); 430 au_sync();
387 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 431 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
388 au_sync(); 432 au_sync();
389 433
390 iounmap(au1xpsc_ac97_workdata->mmio); 434 iounmap(wd->mmio);
391 release_resource(au1xpsc_ac97_workdata->ioarea); 435 release_resource(wd->ioarea);
392 kfree(au1xpsc_ac97_workdata->ioarea); 436 kfree(wd->ioarea);
393 kfree(au1xpsc_ac97_workdata); 437 kfree(wd);
394 au1xpsc_ac97_workdata = NULL; 438
439 au1xpsc_ac97_workdata = NULL; /* MDEV */
440
441 return 0;
395} 442}
396 443
397static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai) 444#ifdef CONFIG_PM
445static int au1xpsc_ac97_drvsuspend(struct device *dev)
398{ 446{
447 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
448
399 /* save interesting registers and disable PSC */ 449 /* save interesting registers and disable PSC */
400 au1xpsc_ac97_workdata->pm[0] = 450 wd->pm[0] = au_readl(PSC_SEL(wd));
401 au_readl(PSC_SEL(au1xpsc_ac97_workdata));
402 451
403 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 452 au_writel(0, AC97_CFG(wd));
404 au_sync(); 453 au_sync();
405 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 454 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
406 au_sync(); 455 au_sync();
407 456
408 return 0; 457 return 0;
409} 458}
410 459
411static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) 460static int au1xpsc_ac97_drvresume(struct device *dev)
412{ 461{
462 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
463
413 /* restore PSC clock config */ 464 /* restore PSC clock config */
414 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, 465 au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
415 PSC_SEL(au1xpsc_ac97_workdata));
416 au_sync(); 466 au_sync();
417 467
418 /* after this point the ac97 core will cold-reset the codec. 468 /* after this point the ac97 core will cold-reset the codec.
@@ -422,48 +472,44 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
422 return 0; 472 return 0;
423} 473}
424 474
425static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { 475static struct dev_pm_ops au1xpscac97_pmops = {
426 .trigger = au1xpsc_ac97_trigger, 476 .suspend = au1xpsc_ac97_drvsuspend,
427 .hw_params = au1xpsc_ac97_hw_params, 477 .resume = au1xpsc_ac97_drvresume,
428}; 478};
429 479
430struct snd_soc_dai au1xpsc_ac97_dai = { 480#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops
431 .name = "au1xpsc_ac97", 481
432 .ac97_control = 1, 482#else
433 .probe = au1xpsc_ac97_probe, 483
434 .remove = au1xpsc_ac97_remove, 484#define AU1XPSCAC97_PMOPS NULL
435 .suspend = au1xpsc_ac97_suspend, 485
436 .resume = au1xpsc_ac97_resume, 486#endif
437 .playback = { 487
438 .rates = AC97_RATES, 488static struct platform_driver au1xpsc_ac97_driver = {
439 .formats = AC97_FMTS, 489 .driver = {
440 .channels_min = 2, 490 .name = "au1xpsc_ac97",
441 .channels_max = 2, 491 .owner = THIS_MODULE,
442 }, 492 .pm = AU1XPSCAC97_PMOPS,
443 .capture = {
444 .rates = AC97_RATES,
445 .formats = AC97_FMTS,
446 .channels_min = 2,
447 .channels_max = 2,
448 }, 493 },
449 .ops = &au1xpsc_ac97_dai_ops, 494 .probe = au1xpsc_ac97_drvprobe,
495 .remove = __devexit_p(au1xpsc_ac97_drvremove),
450}; 496};
451EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
452 497
453static int __init au1xpsc_ac97_init(void) 498static int __init au1xpsc_ac97_load(void)
454{ 499{
455 au1xpsc_ac97_workdata = NULL; 500 au1xpsc_ac97_workdata = NULL;
456 return snd_soc_register_dai(&au1xpsc_ac97_dai); 501 return platform_driver_register(&au1xpsc_ac97_driver);
457} 502}
458 503
459static void __exit au1xpsc_ac97_exit(void) 504static void __exit au1xpsc_ac97_unload(void)
460{ 505{
461 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 506 platform_driver_unregister(&au1xpsc_ac97_driver);
462} 507}
463 508
464module_init(au1xpsc_ac97_init); 509module_init(au1xpsc_ac97_load);
465module_exit(au1xpsc_ac97_exit); 510module_exit(au1xpsc_ac97_unload);
466 511
467MODULE_LICENSE("GPL"); 512MODULE_LICENSE("GPL");
468MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); 513MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
469MODULE_AUTHOR("Manuel Lauss <manuel.lauss@gmail.com>"); 514MODULE_AUTHOR("Manuel Lauss");
515
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index bb589327ee32..0cf2ca61c776 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -265,16 +265,52 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
265static int au1xpsc_i2s_probe(struct platform_device *pdev, 265static int au1xpsc_i2s_probe(struct platform_device *pdev,
266 struct snd_soc_dai *dai) 266 struct snd_soc_dai *dai)
267{ 267{
268 return au1xpsc_i2s_workdata ? 0 : -ENODEV;
269}
270
271static void au1xpsc_i2s_remove(struct platform_device *pdev,
272 struct snd_soc_dai *dai)
273{
274}
275
276static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
277 .trigger = au1xpsc_i2s_trigger,
278 .hw_params = au1xpsc_i2s_hw_params,
279 .set_fmt = au1xpsc_i2s_set_fmt,
280};
281
282struct snd_soc_dai au1xpsc_i2s_dai = {
283 .name = "au1xpsc_i2s",
284 .probe = au1xpsc_i2s_probe,
285 .remove = au1xpsc_i2s_remove,
286 .playback = {
287 .rates = AU1XPSC_I2S_RATES,
288 .formats = AU1XPSC_I2S_FMTS,
289 .channels_min = 2,
290 .channels_max = 8, /* 2 without external help */
291 },
292 .capture = {
293 .rates = AU1XPSC_I2S_RATES,
294 .formats = AU1XPSC_I2S_FMTS,
295 .channels_min = 2,
296 .channels_max = 8, /* 2 without external help */
297 },
298 .ops = &au1xpsc_i2s_dai_ops,
299};
300EXPORT_SYMBOL(au1xpsc_i2s_dai);
301
302static int __init au1xpsc_i2s_drvprobe(struct platform_device *pdev)
303{
268 struct resource *r; 304 struct resource *r;
269 unsigned long sel; 305 unsigned long sel;
270 int ret; 306 int ret;
307 struct au1xpsc_audio_data *wd;
271 308
272 if (au1xpsc_i2s_workdata) 309 if (au1xpsc_i2s_workdata)
273 return -EBUSY; 310 return -EBUSY;
274 311
275 au1xpsc_i2s_workdata = 312 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
276 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 313 if (!wd)
277 if (!au1xpsc_i2s_workdata)
278 return -ENOMEM; 314 return -ENOMEM;
279 315
280 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 316 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -284,131 +320,146 @@ static int au1xpsc_i2s_probe(struct platform_device *pdev,
284 } 320 }
285 321
286 ret = -EBUSY; 322 ret = -EBUSY;
287 au1xpsc_i2s_workdata->ioarea = 323 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
288 request_mem_region(r->start, r->end - r->start + 1,
289 "au1xpsc_i2s"); 324 "au1xpsc_i2s");
290 if (!au1xpsc_i2s_workdata->ioarea) 325 if (!wd->ioarea)
291 goto out0; 326 goto out0;
292 327
293 au1xpsc_i2s_workdata->mmio = ioremap(r->start, 0xffff); 328 wd->mmio = ioremap(r->start, 0xffff);
294 if (!au1xpsc_i2s_workdata->mmio) 329 if (!wd->mmio)
295 goto out1; 330 goto out1;
296 331
297 /* preserve PSC clock source set up by platform (dev.platform_data 332 /* preserve PSC clock source set up by platform (dev.platform_data
298 * is already occupied by soc layer) 333 * is already occupied by soc layer)
299 */ 334 */
300 sel = au_readl(PSC_SEL(au1xpsc_i2s_workdata)) & PSC_SEL_CLK_MASK; 335 sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
301 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 336 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
302 au_sync(); 337 au_sync();
303 au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(au1xpsc_i2s_workdata)); 338 au_writel(PSC_SEL_PS_I2SMODE | sel, PSC_SEL(wd));
304 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 339 au_writel(0, I2S_CFG(wd));
305 au_sync(); 340 au_sync();
306 341
307 /* preconfigure: set max rx/tx fifo depths */ 342 /* preconfigure: set max rx/tx fifo depths */
308 au1xpsc_i2s_workdata->cfg |= 343 wd->cfg |= PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
309 PSC_I2SCFG_RT_FIFO8 | PSC_I2SCFG_TT_FIFO8;
310 344
311 /* don't wait for I2S core to become ready now; clocks may not 345 /* don't wait for I2S core to become ready now; clocks may not
312 * be running yet; depending on clock input for PSC a wait might 346 * be running yet; depending on clock input for PSC a wait might
313 * time out. 347 * time out.
314 */ 348 */
315 349
316 return 0; 350 ret = snd_soc_register_dai(&au1xpsc_i2s_dai);
351 if (ret)
352 goto out1;
317 353
354 /* finally add the DMA device for this PSC */
355 wd->dmapd = au1xpsc_pcm_add(pdev);
356 if (wd->dmapd) {
357 platform_set_drvdata(pdev, wd);
358 au1xpsc_i2s_workdata = wd;
359 return 0;
360 }
361
362 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
318out1: 363out1:
319 release_resource(au1xpsc_i2s_workdata->ioarea); 364 release_resource(wd->ioarea);
320 kfree(au1xpsc_i2s_workdata->ioarea); 365 kfree(wd->ioarea);
321out0: 366out0:
322 kfree(au1xpsc_i2s_workdata); 367 kfree(wd);
323 au1xpsc_i2s_workdata = NULL;
324 return ret; 368 return ret;
325} 369}
326 370
327static void au1xpsc_i2s_remove(struct platform_device *pdev, 371static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
328 struct snd_soc_dai *dai)
329{ 372{
330 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 373 struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
374
375 if (wd->dmapd)
376 au1xpsc_pcm_destroy(wd->dmapd);
377
378 snd_soc_unregister_dai(&au1xpsc_i2s_dai);
379
380 au_writel(0, I2S_CFG(wd));
331 au_sync(); 381 au_sync();
332 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 382 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
333 au_sync(); 383 au_sync();
334 384
335 iounmap(au1xpsc_i2s_workdata->mmio); 385 iounmap(wd->mmio);
336 release_resource(au1xpsc_i2s_workdata->ioarea); 386 release_resource(wd->ioarea);
337 kfree(au1xpsc_i2s_workdata->ioarea); 387 kfree(wd->ioarea);
338 kfree(au1xpsc_i2s_workdata); 388 kfree(wd);
339 au1xpsc_i2s_workdata = NULL; 389
390 au1xpsc_i2s_workdata = NULL; /* MDEV */
391
392 return 0;
340} 393}
341 394
342static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai) 395#ifdef CONFIG_PM
396static int au1xpsc_i2s_drvsuspend(struct device *dev)
343{ 397{
398 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
399
344 /* save interesting register and disable PSC */ 400 /* save interesting register and disable PSC */
345 au1xpsc_i2s_workdata->pm[0] = 401 wd->pm[0] = au_readl(PSC_SEL(wd));
346 au_readl(PSC_SEL(au1xpsc_i2s_workdata));
347 402
348 au_writel(0, I2S_CFG(au1xpsc_i2s_workdata)); 403 au_writel(0, I2S_CFG(wd));
349 au_sync(); 404 au_sync();
350 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 405 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
351 au_sync(); 406 au_sync();
352 407
353 return 0; 408 return 0;
354} 409}
355 410
356static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai) 411static int au1xpsc_i2s_drvresume(struct device *dev)
357{ 412{
413 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
414
358 /* select I2S mode and PSC clock */ 415 /* select I2S mode and PSC clock */
359 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata)); 416 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
360 au_sync(); 417 au_sync();
361 au_writel(0, PSC_SEL(au1xpsc_i2s_workdata)); 418 au_writel(0, PSC_SEL(wd));
362 au_sync(); 419 au_sync();
363 au_writel(au1xpsc_i2s_workdata->pm[0], 420 au_writel(wd->pm[0], PSC_SEL(wd));
364 PSC_SEL(au1xpsc_i2s_workdata));
365 au_sync(); 421 au_sync();
366 422
367 return 0; 423 return 0;
368} 424}
369 425
370static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = { 426static struct dev_pm_ops au1xpsci2s_pmops = {
371 .trigger = au1xpsc_i2s_trigger, 427 .suspend = au1xpsc_i2s_drvsuspend,
372 .hw_params = au1xpsc_i2s_hw_params, 428 .resume = au1xpsc_i2s_drvresume,
373 .set_fmt = au1xpsc_i2s_set_fmt,
374}; 429};
375 430
376struct snd_soc_dai au1xpsc_i2s_dai = { 431#define AU1XPSCI2S_PMOPS &au1xpsci2s_pmops
377 .name = "au1xpsc_i2s", 432
378 .probe = au1xpsc_i2s_probe, 433#else
379 .remove = au1xpsc_i2s_remove, 434
380 .suspend = au1xpsc_i2s_suspend, 435#define AU1XPSCI2S_PMOPS NULL
381 .resume = au1xpsc_i2s_resume, 436
382 .playback = { 437#endif
383 .rates = AU1XPSC_I2S_RATES, 438
384 .formats = AU1XPSC_I2S_FMTS, 439static struct platform_driver au1xpsc_i2s_driver = {
385 .channels_min = 2, 440 .driver = {
386 .channels_max = 8, /* 2 without external help */ 441 .name = "au1xpsc_i2s",
387 }, 442 .owner = THIS_MODULE,
388 .capture = { 443 .pm = AU1XPSCI2S_PMOPS,
389 .rates = AU1XPSC_I2S_RATES,
390 .formats = AU1XPSC_I2S_FMTS,
391 .channels_min = 2,
392 .channels_max = 8, /* 2 without external help */
393 }, 444 },
394 .ops = &au1xpsc_i2s_dai_ops, 445 .probe = au1xpsc_i2s_drvprobe,
446 .remove = __devexit_p(au1xpsc_i2s_drvremove),
395}; 447};
396EXPORT_SYMBOL(au1xpsc_i2s_dai);
397 448
398static int __init au1xpsc_i2s_init(void) 449static int __init au1xpsc_i2s_load(void)
399{ 450{
400 au1xpsc_i2s_workdata = NULL; 451 au1xpsc_i2s_workdata = NULL;
401 return snd_soc_register_dai(&au1xpsc_i2s_dai); 452 return platform_driver_register(&au1xpsc_i2s_driver);
402} 453}
403 454
404static void __exit au1xpsc_i2s_exit(void) 455static void __exit au1xpsc_i2s_unload(void)
405{ 456{
406 snd_soc_unregister_dai(&au1xpsc_i2s_dai); 457 platform_driver_unregister(&au1xpsc_i2s_driver);
407} 458}
408 459
409module_init(au1xpsc_i2s_init); 460module_init(au1xpsc_i2s_load);
410module_exit(au1xpsc_i2s_exit); 461module_exit(au1xpsc_i2s_unload);
411 462
412MODULE_LICENSE("GPL"); 463MODULE_LICENSE("GPL");
413MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver"); 464MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
414MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 465MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index 3f474e8ed4f6..32d3807d3f5a 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -2,7 +2,7 @@
2 * Au12x0/Au1550 PSC ALSA ASoC audio support. 2 * Au12x0/Au1550 PSC ALSA ASoC audio support.
3 * 3 *
4 * (c) 2007-2008 MSC Vertriebsges.m.b.H., 4 * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
5 * Manuel Lauss <mano@roarinelk.homelinux.net> 5 * Manuel Lauss <manuel.lauss@gmail.com>
6 * 6 *
7 * This program is free software; you can redistribute it and/or modify 7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as 8 * it under the terms of the GNU General Public License version 2 as
@@ -21,6 +21,10 @@ extern struct snd_soc_dai au1xpsc_i2s_dai;
21extern struct snd_soc_platform au1xpsc_soc_platform; 21extern struct snd_soc_platform au1xpsc_soc_platform;
22extern struct snd_ac97_bus_ops soc_ac97_ops; 22extern struct snd_ac97_bus_ops soc_ac97_ops;
23 23
24/* DBDMA helpers */
25extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
26extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
27
24struct au1xpsc_audio_data { 28struct au1xpsc_audio_data {
25 void __iomem *mmio; 29 void __iomem *mmio;
26 30
@@ -30,6 +34,7 @@ struct au1xpsc_audio_data {
30 unsigned long pm[2]; 34 unsigned long pm[2];
31 struct resource *ioarea; 35 struct resource *ioarea;
32 struct mutex lock; 36 struct mutex lock;
37 struct platform_device *dmapd;
33}; 38};
34 39
35#define PCM_TX 0 40#define PCM_TX 0
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 3df3497335bf..4a3e8dcf24d9 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS
40 select SND_SOC_WM8523 if I2C 40 select SND_SOC_WM8523 if I2C
41 select SND_SOC_WM8580 if I2C 41 select SND_SOC_WM8580 if I2C
42 select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI 42 select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI
43 select SND_SOC_WM8727
43 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 44 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
44 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 45 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
45 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 46 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
@@ -174,6 +175,9 @@ config SND_SOC_WM8580
174config SND_SOC_WM8711 175config SND_SOC_WM8711
175 tristate 176 tristate
176 177
178config SND_SOC_WM8727
179 tristate
180
177config SND_SOC_WM8728 181config SND_SOC_WM8728
178 tristate 182 tristate
179 183
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 8f519ee9600d..cacfc7692d7f 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -27,6 +27,7 @@ snd-soc-wm8510-objs := wm8510.o
27snd-soc-wm8523-objs := wm8523.o 27snd-soc-wm8523-objs := wm8523.o
28snd-soc-wm8580-objs := wm8580.o 28snd-soc-wm8580-objs := wm8580.o
29snd-soc-wm8711-objs := wm8711.o 29snd-soc-wm8711-objs := wm8711.o
30snd-soc-wm8727-objs := wm8727.o
30snd-soc-wm8728-objs := wm8728.o 31snd-soc-wm8728-objs := wm8728.o
31snd-soc-wm8731-objs := wm8731.o 32snd-soc-wm8731-objs := wm8731.o
32snd-soc-wm8750-objs := wm8750.o 33snd-soc-wm8750-objs := wm8750.o
@@ -81,6 +82,7 @@ obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
81obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o 82obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
82obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 83obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
83obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o 84obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
85obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
84obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 86obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
85obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 87obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
86obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 88obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 932299bb5d1e..69bd0acc81c8 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -117,9 +117,6 @@ static int ac97_soc_probe(struct platform_device *pdev)
117 if (ret < 0) 117 if (ret < 0)
118 goto bus_err; 118 goto bus_err;
119 119
120 ret = snd_soc_init_card(socdev);
121 if (ret < 0)
122 goto bus_err;
123 return 0; 120 return 0;
124 121
125bus_err: 122bus_err:
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index c48485f2c55d..b4be96decf32 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -387,17 +387,6 @@ static int ad1836_probe(struct platform_device *pdev)
387 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 387 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
388 snd_soc_dapm_new_widgets(codec); 388 snd_soc_dapm_new_widgets(codec);
389 389
390 ret = snd_soc_init_card(socdev);
391 if (ret < 0) {
392 dev_err(codec->dev, "failed to register card: %d\n", ret);
393 goto card_err;
394 }
395
396 return ret;
397
398card_err:
399 snd_soc_free_pcms(socdev);
400 snd_soc_dapm_free(socdev);
401pcm_err: 390pcm_err:
402 return ret; 391 return ret;
403} 392}
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index 34b30efc3cb0..3b2222a0c808 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -596,17 +596,6 @@ static int ad1938_probe(struct platform_device *pdev)
596 596
597 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 597 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
598 598
599 ret = snd_soc_init_card(socdev);
600 if (ret < 0) {
601 dev_err(codec->dev, "failed to register card: %d\n", ret);
602 goto card_err;
603 }
604
605 return ret;
606
607card_err:
608 snd_soc_free_pcms(socdev);
609 snd_soc_dapm_free(socdev);
610pcm_err: 599pcm_err:
611 return ret; 600 return ret;
612} 601}
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index d7440a982d22..39c0f7584e65 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -257,11 +257,6 @@ static int ad1980_soc_probe(struct platform_device *pdev)
257 257
258 snd_soc_add_controls(codec, ad1980_snd_ac97_controls, 258 snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
259 ARRAY_SIZE(ad1980_snd_ac97_controls)); 259 ARRAY_SIZE(ad1980_snd_ac97_controls));
260 ret = snd_soc_init_card(socdev);
261 if (ret < 0) {
262 printk(KERN_ERR "ad1980: failed to register card\n");
263 goto reset_err;
264 }
265 260
266 return 0; 261 return 0;
267 262
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index e61dac5e7b8f..d2fcc601722c 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -64,16 +64,8 @@ static int ad73311_soc_probe(struct platform_device *pdev)
64 goto pcm_err; 64 goto pcm_err;
65 } 65 }
66 66
67 ret = snd_soc_init_card(socdev);
68 if (ret < 0) {
69 printk(KERN_ERR "ad73311: failed to register card\n");
70 goto register_err;
71 }
72
73 return ret; 67 return ret;
74 68
75register_err:
76 snd_soc_free_pcms(socdev);
77pcm_err: 69pcm_err:
78 kfree(socdev->card->codec); 70 kfree(socdev->card->codec);
79 socdev->card->codec = NULL; 71 socdev->card->codec = NULL;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index 4d47bc4f7428..3a14c6fc4f5e 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -313,14 +313,6 @@ static int ak4104_probe(struct platform_device *pdev)
313 return ret; 313 return ret;
314 } 314 }
315 315
316 /* Register the socdev */
317 ret = snd_soc_init_card(socdev);
318 if (ret < 0) {
319 dev_err(codec->dev, "failed to register card\n");
320 snd_soc_free_pcms(socdev);
321 return ret;
322 }
323
324 return 0; 316 return 0;
325} 317}
326 318
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 0abec0d29a96..57a6846a9a1f 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -485,17 +485,9 @@ static int ak4535_init(struct snd_soc_device *socdev)
485 snd_soc_add_controls(codec, ak4535_snd_controls, 485 snd_soc_add_controls(codec, ak4535_snd_controls,
486 ARRAY_SIZE(ak4535_snd_controls)); 486 ARRAY_SIZE(ak4535_snd_controls));
487 ak4535_add_widgets(codec); 487 ak4535_add_widgets(codec);
488 ret = snd_soc_init_card(socdev);
489 if (ret < 0) {
490 printk(KERN_ERR "ak4535: failed to register card\n");
491 goto card_err;
492 }
493 488
494 return ret; 489 return ret;
495 490
496card_err:
497 snd_soc_free_pcms(socdev);
498 snd_soc_dapm_free(socdev);
499pcm_err: 491pcm_err:
500 kfree(codec->reg_cache); 492 kfree(codec->reg_cache);
501 493
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index e057c7b578df..b69861d52161 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -442,18 +442,9 @@ static int ak4642_probe(struct platform_device *pdev)
442 goto pcm_err; 442 goto pcm_err;
443 } 443 }
444 444
445 ret = snd_soc_init_card(socdev);
446 if (ret < 0) {
447 printk(KERN_ERR "ak4642: failed to register card\n");
448 goto card_err;
449 }
450
451 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION); 445 dev_info(&pdev->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
452 return ret; 446 return ret;
453 447
454card_err:
455 snd_soc_free_pcms(socdev);
456 snd_soc_dapm_free(socdev);
457pcm_err: 448pcm_err:
458 return ret; 449 return ret;
459 450
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index b61214d1c5de..364832ccd748 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -662,19 +662,10 @@ static int ak4671_probe(struct platform_device *pdev)
662 ARRAY_SIZE(ak4671_snd_controls)); 662 ARRAY_SIZE(ak4671_snd_controls));
663 ak4671_add_widgets(codec); 663 ak4671_add_widgets(codec);
664 664
665 ret = snd_soc_init_card(socdev);
666 if (ret < 0) {
667 dev_err(codec->dev, "failed to register card: %d\n", ret);
668 goto card_err;
669 }
670
671 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 665 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
672 666
673 return ret; 667 return ret;
674 668
675card_err:
676 snd_soc_free_pcms(socdev);
677 snd_soc_dapm_free(socdev);
678pcm_err: 669pcm_err:
679 return ret; 670 return ret;
680} 671}
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 59bb16d033d6..ffe122d1cd76 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -520,6 +520,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
520 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), 520 SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0),
521 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), 521 SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0),
522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), 522 SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0),
523 SOC_SINGLE("De-emphasis filter", CS4270_TRANS, 0, 1, 0),
523 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), 524 SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1),
524 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), 525 SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0),
525 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), 526 SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1),
@@ -598,13 +599,6 @@ static int cs4270_probe(struct platform_device *pdev)
598 goto error_free_pcms; 599 goto error_free_pcms;
599 } 600 }
600 601
601 /* And finally, register the socdev */
602 ret = snd_soc_init_card(socdev);
603 if (ret < 0) {
604 dev_err(codec->dev, "failed to register card\n");
605 goto error_free_pcms;
606 }
607
608 return 0; 602 return 0;
609 603
610error_free_pcms: 604error_free_pcms:
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 38eac9c866e1..dda751c885cb 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -355,17 +355,6 @@ static int cx20442_codec_probe(struct platform_device *pdev)
355 355
356 cx20442_add_widgets(codec); 356 cx20442_add_widgets(codec);
357 357
358 ret = snd_soc_init_card(socdev);
359 if (ret < 0) {
360 dev_err(&pdev->dev, "failed to register card\n");
361 goto card_err;
362 }
363
364 return ret;
365
366card_err:
367 snd_soc_free_pcms(socdev);
368 snd_soc_dapm_free(socdev);
369pcm_err: 358pcm_err:
370 return ret; 359 return ret;
371} 360}
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index 5cda9e6b5a74..2afcd0a8669d 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -90,13 +90,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
90 goto pcm_err; 90 goto pcm_err;
91 } 91 }
92 92
93 /* Register Card. */
94 ret = snd_soc_init_card(socdev);
95 if (ret < 0) {
96 printk(KERN_ERR "pcm3008: failed to register card\n");
97 goto card_err;
98 }
99
100 /* DEM1 DEM0 DE-EMPHASIS_MODE 93 /* DEM1 DEM0 DE-EMPHASIS_MODE
101 * Low Low De-emphasis 44.1 kHz ON 94 * Low Low De-emphasis 44.1 kHz ON
102 * Low High De-emphasis OFF 95 * Low High De-emphasis OFF
@@ -136,8 +129,6 @@ static int pcm3008_soc_probe(struct platform_device *pdev)
136 129
137gpio_err: 130gpio_err:
138 pcm3008_gpio_free(setup); 131 pcm3008_gpio_free(setup);
139card_err:
140 snd_soc_free_pcms(socdev);
141pcm_err: 132pcm_err:
142 kfree(socdev->card->codec); 133 kfree(socdev->card->codec);
143 134
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index c550750c79c0..b3130339d29a 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -613,17 +613,9 @@ static int ssm2602_init(struct snd_soc_device *socdev)
613 snd_soc_add_controls(codec, ssm2602_snd_controls, 613 snd_soc_add_controls(codec, ssm2602_snd_controls,
614 ARRAY_SIZE(ssm2602_snd_controls)); 614 ARRAY_SIZE(ssm2602_snd_controls));
615 ssm2602_add_widgets(codec); 615 ssm2602_add_widgets(codec);
616 ret = snd_soc_init_card(socdev);
617 if (ret < 0) {
618 pr_err("ssm2602: failed to register card\n");
619 goto card_err;
620 }
621 616
622 return ret; 617 return ret;
623 618
624card_err:
625 snd_soc_free_pcms(socdev);
626 snd_soc_dapm_free(socdev);
627pcm_err: 619pcm_err:
628 kfree(codec->reg_cache); 620 kfree(codec->reg_cache);
629 return ret; 621 return ret;
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index befc6488c39a..bbc72c2ddfca 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -418,9 +418,6 @@ static int stac9766_codec_probe(struct platform_device *pdev)
418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls, 418 snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
419 ARRAY_SIZE(stac9766_snd_ac97_controls)); 419 ARRAY_SIZE(stac9766_snd_ac97_controls));
420 420
421 ret = snd_soc_init_card(socdev);
422 if (ret < 0)
423 goto reset_err;
424 return 0; 421 return 0;
425 422
426reset_err: 423reset_err:
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 0b8dcb5cd729..ee8cb2c08b87 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -707,17 +707,9 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
707 snd_soc_add_controls(codec, tlv320aic23_snd_controls, 707 snd_soc_add_controls(codec, tlv320aic23_snd_controls,
708 ARRAY_SIZE(tlv320aic23_snd_controls)); 708 ARRAY_SIZE(tlv320aic23_snd_controls));
709 tlv320aic23_add_widgets(codec); 709 tlv320aic23_add_widgets(codec);
710 ret = snd_soc_init_card(socdev);
711 if (ret < 0) {
712 printk(KERN_ERR "tlv320aic23: failed to register card\n");
713 goto card_err;
714 }
715 710
716 return ret; 711 return ret;
717 712
718card_err:
719 snd_soc_free_pcms(socdev);
720 snd_soc_dapm_free(socdev);
721pcm_err: 713pcm_err:
722 kfree(codec->reg_cache); 714 kfree(codec->reg_cache);
723 return ret; 715 return ret;
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 3387d9e736ea..357b609196e3 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -356,18 +356,7 @@ static int aic26_probe(struct platform_device *pdev)
356 ARRAY_SIZE(aic26_snd_controls)); 356 ARRAY_SIZE(aic26_snd_controls));
357 WARN_ON(err < 0); 357 WARN_ON(err < 0);
358 358
359 /* CODEC is setup, we can register the card now */
360 dev_dbg(&pdev->dev, "Registering card\n");
361 ret = snd_soc_init_card(socdev);
362 if (ret < 0) {
363 dev_err(&pdev->dev, "aic26: failed to register card\n");
364 goto card_err;
365 }
366 return 0; 359 return 0;
367
368 card_err:
369 snd_soc_free_pcms(socdev);
370 return ret;
371} 360}
372 361
373static int aic26_remove(struct platform_device *pdev) 362static int aic26_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 3395cf945d56..03cad250f58d 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1405,18 +1405,8 @@ static int aic3x_probe(struct platform_device *pdev)
1405 1405
1406 aic3x_add_widgets(codec); 1406 aic3x_add_widgets(codec);
1407 1407
1408 ret = snd_soc_init_card(socdev);
1409 if (ret < 0) {
1410 printk(KERN_ERR "aic3x: failed to register card\n");
1411 goto card_err;
1412 }
1413
1414 return ret; 1408 return ret;
1415 1409
1416card_err:
1417 snd_soc_free_pcms(socdev);
1418 snd_soc_dapm_free(socdev);
1419
1420pcm_err: 1410pcm_err:
1421 kfree(codec->reg_cache); 1411 kfree(codec->reg_cache);
1422 return ret; 1412 return ret;
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 3ca8934fc26c..bff476d65d05 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -960,16 +960,8 @@ static int dac33_soc_probe(struct platform_device *pdev)
960 /* power on device */ 960 /* power on device */
961 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 961 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
962 962
963 ret = snd_soc_init_card(socdev);
964 if (ret < 0) {
965 dev_err(codec->dev, "failed to register card\n");
966 goto card_err;
967 }
968
969 return 0; 963 return 0;
970card_err: 964
971 snd_soc_free_pcms(socdev);
972 snd_soc_dapm_free(socdev);
973pcm_err: 965pcm_err:
974 dac33_hard_power(codec, 0); 966 dac33_hard_power(codec, 0);
975 return ret; 967 return ret;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 5c5a4c0a424f..928257b25111 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -122,9 +122,8 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
122struct twl4030_priv { 122struct twl4030_priv {
123 struct snd_soc_codec codec; 123 struct snd_soc_codec codec;
124 124
125 unsigned int bypass_state;
126 unsigned int codec_powered; 125 unsigned int codec_powered;
127 unsigned int codec_muted; 126 unsigned int apll_enabled;
128 127
129 struct snd_pcm_substream *master_substream; 128 struct snd_pcm_substream *master_substream;
130 struct snd_pcm_substream *slave_substream; 129 struct snd_pcm_substream *slave_substream;
@@ -219,25 +218,25 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
219 218
220} 219}
221 220
222static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) 221static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
223{ 222{
224 struct twl4030_priv *twl4030 = codec->private_data; 223 struct twl4030_priv *twl4030 = codec->private_data;
225 int status; 224 int status;
226 225
227 if (mute == twl4030->codec_muted) 226 if (enable == twl4030->apll_enabled)
228 return; 227 return;
229 228
230 if (mute) 229 if (enable)
231 /* Disable PLL */
232 status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
233 else
234 /* Enable PLL */ 230 /* Enable PLL */
235 status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); 231 status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
232 else
233 /* Disable PLL */
234 status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
236 235
237 if (status >= 0) 236 if (status >= 0)
238 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); 237 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status);
239 238
240 twl4030->codec_muted = mute; 239 twl4030->apll_enabled = enable;
241} 240}
242 241
243static void twl4030_power_up(struct snd_soc_codec *codec) 242static void twl4030_power_up(struct snd_soc_codec *codec)
@@ -614,6 +613,27 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
614 return 0; 613 return 0;
615} 614}
616 615
616static int vibramux_event(struct snd_soc_dapm_widget *w,
617 struct snd_kcontrol *kcontrol, int event)
618{
619 twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff);
620 return 0;
621}
622
623static int apll_event(struct snd_soc_dapm_widget *w,
624 struct snd_kcontrol *kcontrol, int event)
625{
626 switch (event) {
627 case SND_SOC_DAPM_PRE_PMU:
628 twl4030_apll_enable(w->codec, 1);
629 break;
630 case SND_SOC_DAPM_POST_PMD:
631 twl4030_apll_enable(w->codec, 0);
632 break;
633 }
634 return 0;
635}
636
617static void headset_ramp(struct snd_soc_codec *codec, int ramp) 637static void headset_ramp(struct snd_soc_codec *codec, int ramp)
618{ 638{
619 struct snd_soc_device *socdev = codec->socdev; 639 struct snd_soc_device *socdev = codec->socdev;
@@ -725,67 +745,6 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
725 return 0; 745 return 0;
726} 746}
727 747
728static int bypass_event(struct snd_soc_dapm_widget *w,
729 struct snd_kcontrol *kcontrol, int event)
730{
731 struct soc_mixer_control *m =
732 (struct soc_mixer_control *)w->kcontrols->private_value;
733 struct twl4030_priv *twl4030 = w->codec->private_data;
734 unsigned char reg, misc;
735
736 reg = twl4030_read_reg_cache(w->codec, m->reg);
737
738 /*
739 * bypass_state[0:3] - analog HiFi bypass
740 * bypass_state[4] - analog voice bypass
741 * bypass_state[5] - digital voice bypass
742 * bypass_state[6:7] - digital HiFi bypass
743 */
744 if (m->reg == TWL4030_REG_VSTPGA) {
745 /* Voice digital bypass */
746 if (reg)
747 twl4030->bypass_state |= (1 << 5);
748 else
749 twl4030->bypass_state &= ~(1 << 5);
750 } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
751 /* Analog bypass */
752 if (reg & (1 << m->shift))
753 twl4030->bypass_state |=
754 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
755 else
756 twl4030->bypass_state &=
757 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
758 } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
759 /* Analog voice bypass */
760 if (reg & (1 << m->shift))
761 twl4030->bypass_state |= (1 << 4);
762 else
763 twl4030->bypass_state &= ~(1 << 4);
764 } else {
765 /* Digital bypass */
766 if (reg & (0x7 << m->shift))
767 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
768 else
769 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
770 }
771
772 /* Enable master analog loopback mode if any analog switch is enabled*/
773 misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
774 if (twl4030->bypass_state & 0x1F)
775 misc |= TWL4030_FMLOOP_EN;
776 else
777 misc &= ~TWL4030_FMLOOP_EN;
778 twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
779
780 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
781 if (twl4030->bypass_state)
782 twl4030_codec_mute(w->codec, 0);
783 else
784 twl4030_codec_mute(w->codec, 1);
785 }
786 return 0;
787}
788
789/* 748/*
790 * Some of the gain controls in TWL (mostly those which are associated with 749 * Some of the gain controls in TWL (mostly those which are associated with
791 * the outputs) are implemented in an interesting way: 750 * the outputs) are implemented in an interesting way:
@@ -1193,32 +1152,28 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1193 SND_SOC_NOPM, 0, 0), 1152 SND_SOC_NOPM, 0, 0),
1194 1153
1195 /* Analog bypasses */ 1154 /* Analog bypasses */
1196 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1155 SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1197 &twl4030_dapm_abypassr1_control, bypass_event, 1156 &twl4030_dapm_abypassr1_control),
1198 SND_SOC_DAPM_POST_REG), 1157 SND_SOC_DAPM_SWITCH("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1199 SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1158 &twl4030_dapm_abypassl1_control),
1200 &twl4030_dapm_abypassl1_control, 1159 SND_SOC_DAPM_SWITCH("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1201 bypass_event, SND_SOC_DAPM_POST_REG), 1160 &twl4030_dapm_abypassr2_control),
1202 SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1161 SND_SOC_DAPM_SWITCH("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1203 &twl4030_dapm_abypassr2_control, 1162 &twl4030_dapm_abypassl2_control),
1204 bypass_event, SND_SOC_DAPM_POST_REG), 1163 SND_SOC_DAPM_SWITCH("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1205 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1164 &twl4030_dapm_abypassv_control),
1206 &twl4030_dapm_abypassl2_control, 1165
1207 bypass_event, SND_SOC_DAPM_POST_REG), 1166 /* Master analog loopback switch */
1208 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, 1167 SND_SOC_DAPM_SUPPLY("FM Loop Enable", TWL4030_REG_MISC_SET_1, 5, 0,
1209 &twl4030_dapm_abypassv_control, 1168 NULL, 0),
1210 bypass_event, SND_SOC_DAPM_POST_REG),
1211 1169
1212 /* Digital bypasses */ 1170 /* Digital bypasses */
1213 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1171 SND_SOC_DAPM_SWITCH("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
1214 &twl4030_dapm_dbypassl_control, bypass_event, 1172 &twl4030_dapm_dbypassl_control),
1215 SND_SOC_DAPM_POST_REG), 1173 SND_SOC_DAPM_SWITCH("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
1216 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1174 &twl4030_dapm_dbypassr_control),
1217 &twl4030_dapm_dbypassr_control, bypass_event, 1175 SND_SOC_DAPM_SWITCH("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1218 SND_SOC_DAPM_POST_REG), 1176 &twl4030_dapm_dbypassv_control),
1219 SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1220 &twl4030_dapm_dbypassv_control, bypass_event,
1221 SND_SOC_DAPM_POST_REG),
1222 1177
1223 /* Digital mixers, power control for the physical DACs */ 1178 /* Digital mixers, power control for the physical DACs */
1224 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", 1179 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
@@ -1244,6 +1199,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1244 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", 1199 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1245 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), 1200 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1246 1201
1202 SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event,
1203 SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD),
1204
1247 /* Output MIXER controls */ 1205 /* Output MIXER controls */
1248 /* Earpiece */ 1206 /* Earpiece */
1249 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, 1207 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
@@ -1309,8 +1267,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1309 0, 0, NULL, 0, handsfreerpga_event, 1267 0, 0, NULL, 0, handsfreerpga_event,
1310 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1268 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1311 /* Vibra */ 1269 /* Vibra */
1312 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, 1270 SND_SOC_DAPM_MUX_E("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1313 &twl4030_dapm_vibra_control), 1271 &twl4030_dapm_vibra_control, vibramux_event,
1272 SND_SOC_DAPM_PRE_PMU),
1314 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, 1273 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1315 &twl4030_dapm_vibrapath_control), 1274 &twl4030_dapm_vibrapath_control),
1316 1275
@@ -1370,6 +1329,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1370 {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, 1329 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1371 {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, 1330 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1372 1331
1332 /* Supply for the digital part (APLL) */
1333 {"Digital R1 Playback Mixer", NULL, "APLL Enable"},
1334 {"Digital L1 Playback Mixer", NULL, "APLL Enable"},
1335 {"Digital R2 Playback Mixer", NULL, "APLL Enable"},
1336 {"Digital L2 Playback Mixer", NULL, "APLL Enable"},
1337 {"Digital Voice Playback Mixer", NULL, "APLL Enable"},
1338
1373 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, 1339 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1374 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, 1340 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1375 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, 1341 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
@@ -1483,6 +1449,11 @@ static const struct snd_soc_dapm_route intercon[] = {
1483 {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, 1449 {"ADC Virtual Left2", NULL, "TX2 Capture Route"},
1484 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1450 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
1485 1451
1452 {"ADC Virtual Left1", NULL, "APLL Enable"},
1453 {"ADC Virtual Right1", NULL, "APLL Enable"},
1454 {"ADC Virtual Left2", NULL, "APLL Enable"},
1455 {"ADC Virtual Right2", NULL, "APLL Enable"},
1456
1486 /* Analog bypass routes */ 1457 /* Analog bypass routes */
1487 {"Right1 Analog Loopback", "Switch", "Analog Right"}, 1458 {"Right1 Analog Loopback", "Switch", "Analog Right"},
1488 {"Left1 Analog Loopback", "Switch", "Analog Left"}, 1459 {"Left1 Analog Loopback", "Switch", "Analog Left"},
@@ -1490,6 +1461,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1490 {"Left2 Analog Loopback", "Switch", "Analog Left"}, 1461 {"Left2 Analog Loopback", "Switch", "Analog Left"},
1491 {"Voice Analog Loopback", "Switch", "Analog Left"}, 1462 {"Voice Analog Loopback", "Switch", "Analog Left"},
1492 1463
1464 /* Supply for the Analog loopbacks */
1465 {"Right1 Analog Loopback", NULL, "FM Loop Enable"},
1466 {"Left1 Analog Loopback", NULL, "FM Loop Enable"},
1467 {"Right2 Analog Loopback", NULL, "FM Loop Enable"},
1468 {"Left2 Analog Loopback", NULL, "FM Loop Enable"},
1469 {"Voice Analog Loopback", NULL, "FM Loop Enable"},
1470
1493 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1471 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1494 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1472 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1495 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1473 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
@@ -1521,25 +1499,14 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec)
1521static int twl4030_set_bias_level(struct snd_soc_codec *codec, 1499static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1522 enum snd_soc_bias_level level) 1500 enum snd_soc_bias_level level)
1523{ 1501{
1524 struct twl4030_priv *twl4030 = codec->private_data;
1525
1526 switch (level) { 1502 switch (level) {
1527 case SND_SOC_BIAS_ON: 1503 case SND_SOC_BIAS_ON:
1528 twl4030_codec_mute(codec, 0);
1529 break; 1504 break;
1530 case SND_SOC_BIAS_PREPARE: 1505 case SND_SOC_BIAS_PREPARE:
1531 twl4030_power_up(codec);
1532 if (twl4030->bypass_state)
1533 twl4030_codec_mute(codec, 0);
1534 else
1535 twl4030_codec_mute(codec, 1);
1536 break; 1506 break;
1537 case SND_SOC_BIAS_STANDBY: 1507 case SND_SOC_BIAS_STANDBY:
1538 twl4030_power_up(codec); 1508 if (codec->bias_level == SND_SOC_BIAS_OFF)
1539 if (twl4030->bypass_state) 1509 twl4030_power_up(codec);
1540 twl4030_codec_mute(codec, 0);
1541 else
1542 twl4030_codec_mute(codec, 1);
1543 break; 1510 break;
1544 case SND_SOC_BIAS_OFF: 1511 case SND_SOC_BIAS_OFF:
1545 twl4030_power_down(codec); 1512 twl4030_power_down(codec);
@@ -2188,19 +2155,7 @@ static int twl4030_soc_probe(struct platform_device *pdev)
2188 ARRAY_SIZE(twl4030_snd_controls)); 2155 ARRAY_SIZE(twl4030_snd_controls));
2189 twl4030_add_widgets(codec); 2156 twl4030_add_widgets(codec);
2190 2157
2191 ret = snd_soc_init_card(socdev);
2192 if (ret < 0) {
2193 dev_err(&pdev->dev, "failed to register card\n");
2194 goto card_err;
2195 }
2196
2197 return 0; 2158 return 0;
2198
2199card_err:
2200 snd_soc_free_pcms(socdev);
2201 snd_soc_dapm_free(socdev);
2202
2203 return ret;
2204} 2159}
2205 2160
2206static int twl4030_soc_remove(struct platform_device *pdev) 2161static int twl4030_soc_remove(struct platform_device *pdev)
@@ -2267,6 +2222,7 @@ static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2267 2222
2268 /* Set the defaults, and power up the codec */ 2223 /* Set the defaults, and power up the codec */
2269 twl4030_init_chip(codec); 2224 twl4030_init_chip(codec);
2225 codec->bias_level = SND_SOC_BIAS_OFF;
2270 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 2226 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2271 2227
2272 ret = snd_soc_register_codec(codec); 2228 ret = snd_soc_register_codec(codec);
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index c33b92edbded..aa40d985138f 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -562,17 +562,8 @@ static int uda134x_soc_probe(struct platform_device *pdev)
562 goto pcm_err; 562 goto pcm_err;
563 } 563 }
564 564
565 ret = snd_soc_init_card(socdev);
566 if (ret < 0) {
567 printk(KERN_ERR "UDA134X: failed to register card\n");
568 goto card_err;
569 }
570
571 return 0; 565 return 0;
572 566
573card_err:
574 snd_soc_free_pcms(socdev);
575 snd_soc_dapm_free(socdev);
576pcm_err: 567pcm_err:
577 kfree(codec->reg_cache); 568 kfree(codec->reg_cache);
578reg_err: 569reg_err:
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 92ec03442154..a42e47d94630 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -713,17 +713,9 @@ static int uda1380_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, uda1380_snd_controls, 713 snd_soc_add_controls(codec, uda1380_snd_controls,
714 ARRAY_SIZE(uda1380_snd_controls)); 714 ARRAY_SIZE(uda1380_snd_controls));
715 uda1380_add_widgets(codec); 715 uda1380_add_widgets(codec);
716 ret = snd_soc_init_card(socdev);
717 if (ret < 0) {
718 dev_err(codec->dev, "failed to register card: %d\n", ret);
719 goto card_err;
720 }
721 716
722 return ret; 717 return ret;
723 718
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 719pcm_err:
728 return ret; 720 return ret;
729} 721}
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 714114b50d18..2e35a354b166 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -1501,18 +1501,7 @@ static int wm8350_probe(struct platform_device *pdev)
1501 1501
1502 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1502 wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1503 1503
1504 ret = snd_soc_init_card(socdev);
1505 if (ret < 0) {
1506 dev_err(&pdev->dev, "failed to register card\n");
1507 goto card_err;
1508 }
1509
1510 return 0; 1504 return 0;
1511
1512card_err:
1513 snd_soc_free_pcms(socdev);
1514 snd_soc_dapm_free(socdev);
1515 return ret;
1516} 1505}
1517 1506
1518static int wm8350_remove(struct platform_device *pdev) 1507static int wm8350_remove(struct platform_device *pdev)
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index bd7eecba20fe..584af68af22a 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -1400,17 +1400,6 @@ static int wm8400_probe(struct platform_device *pdev)
1400 wm8400_add_controls(codec); 1400 wm8400_add_controls(codec);
1401 wm8400_add_widgets(codec); 1401 wm8400_add_widgets(codec);
1402 1402
1403 ret = snd_soc_init_card(socdev);
1404 if (ret < 0) {
1405 dev_err(&pdev->dev, "failed to register card\n");
1406 goto card_err;
1407 }
1408
1409 return ret;
1410
1411card_err:
1412 snd_soc_free_pcms(socdev);
1413 snd_soc_dapm_free(socdev);
1414pcm_err: 1403pcm_err:
1415 return ret; 1404 return ret;
1416} 1405}
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 5702435af81b..e3c21ebcc08e 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -604,16 +604,9 @@ static int wm8510_init(struct snd_soc_device *socdev,
604 snd_soc_add_controls(codec, wm8510_snd_controls, 604 snd_soc_add_controls(codec, wm8510_snd_controls,
605 ARRAY_SIZE(wm8510_snd_controls)); 605 ARRAY_SIZE(wm8510_snd_controls));
606 wm8510_add_widgets(codec); 606 wm8510_add_widgets(codec);
607 ret = snd_soc_init_card(socdev); 607
608 if (ret < 0) {
609 printk(KERN_ERR "wm8510: failed to register card\n");
610 goto card_err;
611 }
612 return ret; 608 return ret;
613 609
614card_err:
615 snd_soc_free_pcms(socdev);
616 snd_soc_dapm_free(socdev);
617err: 610err:
618 kfree(codec->reg_cache); 611 kfree(codec->reg_cache);
619 return ret; 612 return ret;
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 268cab21c2cc..2e2b01d6c82b 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -448,17 +448,9 @@ static int wm8523_probe(struct platform_device *pdev)
448 snd_soc_add_controls(codec, wm8523_snd_controls, 448 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls)); 449 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec); 450 wm8523_add_widgets(codec);
451 ret = snd_soc_init_card(socdev);
452 if (ret < 0) {
453 dev_err(codec->dev, "failed to register card: %d\n", ret);
454 goto card_err;
455 }
456 451
457 return ret; 452 return ret;
458 453
459card_err:
460 snd_soc_free_pcms(socdev);
461 snd_soc_dapm_free(socdev);
462pcm_err: 454pcm_err:
463 return ret; 455 return ret;
464} 456}
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index a09b23e03664..dde50d118181 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -800,17 +800,9 @@ static int wm8580_probe(struct platform_device *pdev)
800 snd_soc_add_controls(codec, wm8580_snd_controls, 800 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls)); 801 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec); 802 wm8580_add_widgets(codec);
803 ret = snd_soc_init_card(socdev);
804 if (ret < 0) {
805 dev_err(codec->dev, "failed to register card: %d\n", ret);
806 goto card_err;
807 }
808 803
809 return ret; 804 return ret;
810 805
811card_err:
812 snd_soc_free_pcms(socdev);
813 snd_soc_dapm_free(socdev);
814pcm_err: 806pcm_err:
815 return ret; 807 return ret;
816} 808}
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 54189fbf9e93..70e0675b5d4a 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -404,17 +404,9 @@ static int wm8711_probe(struct platform_device *pdev)
404 snd_soc_add_controls(codec, wm8711_snd_controls, 404 snd_soc_add_controls(codec, wm8711_snd_controls,
405 ARRAY_SIZE(wm8711_snd_controls)); 405 ARRAY_SIZE(wm8711_snd_controls));
406 wm8711_add_widgets(codec); 406 wm8711_add_widgets(codec);
407 ret = snd_soc_init_card(socdev);
408 if (ret < 0) {
409 dev_err(codec->dev, "failed to register card: %d\n", ret);
410 goto card_err;
411 }
412 407
413 return ret; 408 return ret;
414 409
415card_err:
416 snd_soc_free_pcms(socdev);
417 snd_soc_dapm_free(socdev);
418pcm_err: 410pcm_err:
419 return ret; 411 return ret;
420} 412}
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
new file mode 100644
index 000000000000..d8ffbd641d71
--- /dev/null
+++ b/sound/soc/codecs/wm8727.c
@@ -0,0 +1,135 @@
1/*
2 * wm8727.c
3 *
4 * Created on: 15-Oct-2009
5 * Author: neil.jones@imgtec.com
6 *
7 * Copyright (C) 2009 Imagination Technologies Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/kernel.h>
18#include <linux/device.h>
19#include <sound/core.h>
20#include <sound/pcm.h>
21#include <sound/ac97_codec.h>
22#include <sound/initval.h>
23#include <sound/soc.h>
24
25#include "wm8727.h"
26/*
27 * Note this is a simple chip with no configuration interface, sample rate is
28 * determined automatically by examining the Master clock and Bit clock ratios
29 */
30#define WM8727_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
31 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 |\
32 SNDRV_PCM_RATE_192000)
33
34
35struct snd_soc_dai wm8727_dai = {
36 .name = "WM8727",
37 .playback = {
38 .stream_name = "Playback",
39 .channels_min = 2,
40 .channels_max = 2,
41 .rates = WM8727_RATES,
42 .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE,
43 },
44};
45EXPORT_SYMBOL_GPL(wm8727_dai);
46
47static int wm8727_soc_probe(struct platform_device *pdev)
48{
49 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
50 struct snd_soc_codec *codec;
51 int ret = 0;
52
53 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
54 if (codec == NULL)
55 return -ENOMEM;
56 mutex_init(&codec->mutex);
57 codec->name = "WM8727";
58 codec->owner = THIS_MODULE;
59 codec->dai = &wm8727_dai;
60 codec->num_dai = 1;
61 socdev->card->codec = codec;
62 INIT_LIST_HEAD(&codec->dapm_widgets);
63 INIT_LIST_HEAD(&codec->dapm_paths);
64
65 /* register pcms */
66 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
67 if (ret < 0) {
68 printk(KERN_ERR "wm8727: failed to create pcms\n");
69 goto pcm_err;
70 }
71
72 return ret;
73
74pcm_err:
75 kfree(socdev->card->codec);
76 socdev->card->codec = NULL;
77 return ret;
78}
79
80static int wm8727_soc_remove(struct platform_device *pdev)
81{
82 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
83 struct snd_soc_codec *codec = socdev->card->codec;
84
85 if (codec == NULL)
86 return 0;
87 snd_soc_free_pcms(socdev);
88 kfree(codec);
89 return 0;
90}
91
92struct snd_soc_codec_device soc_codec_dev_wm8727 = {
93 .probe = wm8727_soc_probe,
94 .remove = wm8727_soc_remove,
95};
96EXPORT_SYMBOL_GPL(soc_codec_dev_wm8727);
97
98
99static __devinit int wm8727_platform_probe(struct platform_device *pdev)
100{
101 wm8727_dai.dev = &pdev->dev;
102 return snd_soc_register_dai(&wm8727_dai);
103}
104
105static int __devexit wm8727_platform_remove(struct platform_device *pdev)
106{
107 snd_soc_unregister_dai(&wm8727_dai);
108 return 0;
109}
110
111static struct platform_driver wm8727_codec_driver = {
112 .driver = {
113 .name = "wm8727-codec",
114 .owner = THIS_MODULE,
115 },
116
117 .probe = wm8727_platform_probe,
118 .remove = __devexit_p(wm8727_platform_remove),
119};
120
121static int __init wm8727_init(void)
122{
123 return platform_driver_register(&wm8727_codec_driver);
124}
125module_init(wm8727_init);
126
127static void __exit wm8727_exit(void)
128{
129 platform_driver_unregister(&wm8727_codec_driver);
130}
131module_exit(wm8727_exit);
132
133MODULE_DESCRIPTION("ASoC wm8727 driver");
134MODULE_AUTHOR("Neil Jones");
135MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8727.h b/sound/soc/codecs/wm8727.h
new file mode 100644
index 000000000000..ee19aa71bcdc
--- /dev/null
+++ b/sound/soc/codecs/wm8727.h
@@ -0,0 +1,21 @@
1/*
2 * wm8727.h
3 *
4 * Created on: 15-Oct-2009
5 * Author: neil.jones@imgtec.com
6 *
7 * Copyright (C) 2009 Imagination Technologies Ltd.
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by the
11 * Free Software Foundation; either version 2 of the License, or (at your
12 * option) any later version.
13 */
14
15#ifndef WM8727_H_
16#define WM8727_H_
17
18extern struct snd_soc_dai wm8727_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8727;
20
21#endif /* WM8727_H_ */
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 16e969a762c3..1252a8a486a6 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -287,17 +287,9 @@ static int wm8728_init(struct snd_soc_device *socdev,
287 snd_soc_add_controls(codec, wm8728_snd_controls, 287 snd_soc_add_controls(codec, wm8728_snd_controls,
288 ARRAY_SIZE(wm8728_snd_controls)); 288 ARRAY_SIZE(wm8728_snd_controls));
289 wm8728_add_widgets(codec); 289 wm8728_add_widgets(codec);
290 ret = snd_soc_init_card(socdev);
291 if (ret < 0) {
292 printk(KERN_ERR "wm8728: failed to register card\n");
293 goto card_err;
294 }
295 290
296 return ret; 291 return ret;
297 292
298card_err:
299 snd_soc_free_pcms(socdev);
300 snd_soc_dapm_free(socdev);
301err: 293err:
302 kfree(codec->reg_cache); 294 kfree(codec->reg_cache);
303 return ret; 295 return ret;
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 0e59219a59f4..e3675e7a9813 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,6 +19,7 @@
19#include <linux/pm.h> 19#include <linux/pm.h>
20#include <linux/i2c.h> 20#include <linux/i2c.h>
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/regulator/consumer.h>
22#include <linux/spi/spi.h> 23#include <linux/spi/spi.h>
23#include <sound/core.h> 24#include <sound/core.h>
24#include <sound/pcm.h> 25#include <sound/pcm.h>
@@ -33,9 +34,18 @@
33static struct snd_soc_codec *wm8731_codec; 34static struct snd_soc_codec *wm8731_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8731; 35struct snd_soc_codec_device soc_codec_dev_wm8731;
35 36
37#define WM8731_NUM_SUPPLIES 4
38static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
39 "AVDD",
40 "HPVDD",
41 "DCVDD",
42 "DBVDD",
43};
44
36/* codec private data */ 45/* codec private data */
37struct wm8731_priv { 46struct wm8731_priv {
38 struct snd_soc_codec codec; 47 struct snd_soc_codec codec;
48 struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
39 u16 reg_cache[WM8731_CACHEREGNUM]; 49 u16 reg_cache[WM8731_CACHEREGNUM];
40 unsigned int sysclk; 50 unsigned int sysclk;
41}; 51};
@@ -422,9 +432,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
422{ 432{
423 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 433 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
424 struct snd_soc_codec *codec = socdev->card->codec; 434 struct snd_soc_codec *codec = socdev->card->codec;
435 struct wm8731_priv *wm8731 = codec->private_data;
425 436
426 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 437 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 438 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
439 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
440 wm8731->supplies);
428 return 0; 441 return 0;
429} 442}
430 443
@@ -432,10 +445,16 @@ static int wm8731_resume(struct platform_device *pdev)
432{ 445{
433 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 446 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
434 struct snd_soc_codec *codec = socdev->card->codec; 447 struct snd_soc_codec *codec = socdev->card->codec;
435 int i; 448 struct wm8731_priv *wm8731 = codec->private_data;
449 int i, ret;
436 u8 data[2]; 450 u8 data[2];
437 u16 *cache = codec->reg_cache; 451 u16 *cache = codec->reg_cache;
438 452
453 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
454 wm8731->supplies);
455 if (ret != 0)
456 return ret;
457
439 /* Sync reg_cache with the hardware */ 458 /* Sync reg_cache with the hardware */
440 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { 459 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
441 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 460 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
@@ -444,6 +463,7 @@ static int wm8731_resume(struct platform_device *pdev)
444 } 463 }
445 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 464 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
446 wm8731_set_bias_level(codec, codec->suspend_bias_level); 465 wm8731_set_bias_level(codec, codec->suspend_bias_level);
466
447 return 0; 467 return 0;
448} 468}
449#else 469#else
@@ -475,17 +495,9 @@ static int wm8731_probe(struct platform_device *pdev)
475 snd_soc_add_controls(codec, wm8731_snd_controls, 495 snd_soc_add_controls(codec, wm8731_snd_controls,
476 ARRAY_SIZE(wm8731_snd_controls)); 496 ARRAY_SIZE(wm8731_snd_controls));
477 wm8731_add_widgets(codec); 497 wm8731_add_widgets(codec);
478 ret = snd_soc_init_card(socdev);
479 if (ret < 0) {
480 dev_err(codec->dev, "failed to register card: %d\n", ret);
481 goto card_err;
482 }
483 498
484 return ret; 499 return ret;
485 500
486card_err:
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489pcm_err: 501pcm_err:
490 return ret; 502 return ret;
491} 503}
@@ -512,7 +524,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
512static int wm8731_register(struct wm8731_priv *wm8731, 524static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control) 525 enum snd_soc_control_type control)
514{ 526{
515 int ret; 527 int ret, i;
516 struct snd_soc_codec *codec = &wm8731->codec; 528 struct snd_soc_codec *codec = &wm8731->codec;
517 529
518 if (wm8731_codec) { 530 if (wm8731_codec) {
@@ -543,10 +555,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
543 goto err; 555 goto err;
544 } 556 }
545 557
558 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
559 wm8731->supplies[i].supply = wm8731_supply_names[i];
560
561 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
562 wm8731->supplies);
563 if (ret != 0) {
564 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
565 goto err;
566 }
567
568 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
569 wm8731->supplies);
570 if (ret != 0) {
571 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
572 goto err_regulator_get;
573 }
574
546 ret = wm8731_reset(codec); 575 ret = wm8731_reset(codec);
547 if (ret < 0) { 576 if (ret < 0) {
548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 577 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
549 goto err; 578 goto err_regulator_enable;
550 } 579 }
551 580
552 wm8731_dai.dev = codec->dev; 581 wm8731_dai.dev = codec->dev;
@@ -567,7 +596,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
567 ret = snd_soc_register_codec(codec); 596 ret = snd_soc_register_codec(codec);
568 if (ret != 0) { 597 if (ret != 0) {
569 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 598 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
570 goto err; 599 goto err_regulator_enable;
571 } 600 }
572 601
573 ret = snd_soc_register_dai(&wm8731_dai); 602 ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +610,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
581 610
582err_codec: 611err_codec:
583 snd_soc_unregister_codec(codec); 612 snd_soc_unregister_codec(codec);
613err_regulator_enable:
614 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
615err_regulator_get:
616 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
584err: 617err:
585 kfree(wm8731); 618 kfree(wm8731);
586 return ret; 619 return ret;
@@ -591,6 +624,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
591 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 624 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
592 snd_soc_unregister_dai(&wm8731_dai); 625 snd_soc_unregister_dai(&wm8731_dai);
593 snd_soc_unregister_codec(&wm8731->codec); 626 snd_soc_unregister_codec(&wm8731->codec);
627 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
628 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
594 kfree(wm8731); 629 kfree(wm8731);
595 wm8731_codec = NULL; 630 wm8731_codec = NULL;
596} 631}
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 4ba1e7e93fb4..50a3d6590588 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -772,16 +772,8 @@ static int wm8750_init(struct snd_soc_device *socdev,
772 snd_soc_add_controls(codec, wm8750_snd_controls, 772 snd_soc_add_controls(codec, wm8750_snd_controls,
773 ARRAY_SIZE(wm8750_snd_controls)); 773 ARRAY_SIZE(wm8750_snd_controls));
774 wm8750_add_widgets(codec); 774 wm8750_add_widgets(codec);
775 ret = snd_soc_init_card(socdev);
776 if (ret < 0) {
777 printk(KERN_ERR "wm8750: failed to register card\n");
778 goto card_err;
779 }
780 return ret; 775 return ret;
781 776
782card_err:
783 snd_soc_free_pcms(socdev);
784 snd_soc_dapm_free(socdev);
785err: 777err:
786 kfree(codec->reg_cache); 778 kfree(codec->reg_cache);
787 return ret; 779 return ret;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 8f7305257d29..c652bc04cc81 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -1583,18 +1583,9 @@ static int wm8753_probe(struct platform_device *pdev)
1583 snd_soc_add_controls(codec, wm8753_snd_controls, 1583 snd_soc_add_controls(codec, wm8753_snd_controls,
1584 ARRAY_SIZE(wm8753_snd_controls)); 1584 ARRAY_SIZE(wm8753_snd_controls));
1585 wm8753_add_widgets(codec); 1585 wm8753_add_widgets(codec);
1586 ret = snd_soc_init_card(socdev);
1587 if (ret < 0) {
1588 printk(KERN_ERR "wm8753: failed to register card\n");
1589 goto card_err;
1590 }
1591 1586
1592 return 0; 1587 return 0;
1593 1588
1594card_err:
1595 snd_soc_free_pcms(socdev);
1596 snd_soc_dapm_free(socdev);
1597
1598pcm_err: 1589pcm_err:
1599 return ret; 1590 return ret;
1600} 1591}
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index a0bbb28eed75..ab2c0da18091 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -447,17 +447,8 @@ static int wm8776_probe(struct platform_device *pdev)
447 ARRAY_SIZE(wm8776_dapm_widgets)); 447 ARRAY_SIZE(wm8776_dapm_widgets));
448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); 448 snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes));
449 449
450 ret = snd_soc_init_card(socdev);
451 if (ret < 0) {
452 dev_err(codec->dev, "failed to register card: %d\n", ret);
453 goto card_err;
454 }
455
456 return ret; 450 return ret;
457 451
458card_err:
459 snd_soc_free_pcms(socdev);
460 snd_soc_dapm_free(socdev);
461pcm_err: 452pcm_err:
462 return ret; 453 return ret;
463} 454}
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index b48804b5cacd..85f67dbe211d 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1353,17 +1353,6 @@ static int wm8900_probe(struct platform_device *pdev)
1353 ARRAY_SIZE(wm8900_snd_controls)); 1353 ARRAY_SIZE(wm8900_snd_controls));
1354 wm8900_add_widgets(codec); 1354 wm8900_add_widgets(codec);
1355 1355
1356 ret = snd_soc_init_card(socdev);
1357 if (ret < 0) {
1358 dev_err(&pdev->dev, "Failed to register card\n");
1359 goto card_err;
1360 }
1361
1362 return ret;
1363
1364card_err:
1365 snd_soc_free_pcms(socdev);
1366 snd_soc_dapm_free(socdev);
1367pcm_err: 1356pcm_err:
1368 return ret; 1357 return ret;
1369} 1358}
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 94cdb8130415..bfeff4ee5de9 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -1695,17 +1695,8 @@ static int wm8903_probe(struct platform_device *pdev)
1695 ARRAY_SIZE(wm8903_snd_controls)); 1695 ARRAY_SIZE(wm8903_snd_controls));
1696 wm8903_add_widgets(socdev->card->codec); 1696 wm8903_add_widgets(socdev->card->codec);
1697 1697
1698 ret = snd_soc_init_card(socdev);
1699 if (ret < 0) {
1700 dev_err(&pdev->dev, "wm8903: failed to register card\n");
1701 goto card_err;
1702 }
1703
1704 return ret; 1698 return ret;
1705 1699
1706card_err:
1707 snd_soc_free_pcms(socdev);
1708 snd_soc_dapm_free(socdev);
1709err: 1700err:
1710 return ret; 1701 return ret;
1711} 1702}
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 8d4fd3c08c09..fc80aa6c913c 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -731,12 +731,6 @@ static int wm8940_probe(struct platform_device *pdev)
731 if (ret) 731 if (ret)
732 goto error_free_pcms; 732 goto error_free_pcms;
733 733
734 ret = snd_soc_init_card(socdev);
735 if (ret < 0) {
736 dev_err(codec->dev, "failed to register card: %d\n", ret);
737 goto error_free_pcms;
738 }
739
740 return ret; 734 return ret;
741 735
742error_free_pcms: 736error_free_pcms:
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index b9b096a85396..40390afa75f3 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -713,17 +713,9 @@ static int wm8960_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, wm8960_snd_controls, 713 snd_soc_add_controls(codec, wm8960_snd_controls,
714 ARRAY_SIZE(wm8960_snd_controls)); 714 ARRAY_SIZE(wm8960_snd_controls));
715 wm8960_add_widgets(codec); 715 wm8960_add_widgets(codec);
716 ret = snd_soc_init_card(socdev);
717 if (ret < 0) {
718 dev_err(codec->dev, "failed to register card: %d\n", ret);
719 goto card_err;
720 }
721 716
722 return ret; 717 return ret;
723 718
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 719pcm_err:
728 return ret; 720 return ret;
729} 721}
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index b5c6f2cd5ae2..07e389574db1 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -988,17 +988,8 @@ static int wm8961_probe(struct platform_device *pdev)
988 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 988 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
989 snd_soc_dapm_new_widgets(codec); 989 snd_soc_dapm_new_widgets(codec);
990 990
991 ret = snd_soc_init_card(socdev);
992 if (ret < 0) {
993 dev_err(codec->dev, "failed to register card: %d\n", ret);
994 goto card_err;
995 }
996
997 return ret; 991 return ret;
998 992
999card_err:
1000 snd_soc_free_pcms(socdev);
1001 snd_soc_dapm_free(socdev);
1002pcm_err: 993pcm_err:
1003 return ret; 994 return ret;
1004} 995}
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index d66efb0546ea..56a66e89ab91 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -703,16 +703,9 @@ static int wm8971_init(struct snd_soc_device *socdev,
703 snd_soc_add_controls(codec, wm8971_snd_controls, 703 snd_soc_add_controls(codec, wm8971_snd_controls,
704 ARRAY_SIZE(wm8971_snd_controls)); 704 ARRAY_SIZE(wm8971_snd_controls));
705 wm8971_add_widgets(codec); 705 wm8971_add_widgets(codec);
706 ret = snd_soc_init_card(socdev); 706
707 if (ret < 0) {
708 printk(KERN_ERR "wm8971: failed to register card\n");
709 goto card_err;
710 }
711 return ret; 707 return ret;
712 708
713card_err:
714 snd_soc_free_pcms(socdev);
715 snd_soc_dapm_free(socdev);
716err: 709err:
717 kfree(codec->reg_cache); 710 kfree(codec->reg_cache);
718 return ret; 711 return ret;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index eff29331235b..c245f0ee0ec2 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -641,17 +641,9 @@ static int wm8974_probe(struct platform_device *pdev)
641 snd_soc_add_controls(codec, wm8974_snd_controls, 641 snd_soc_add_controls(codec, wm8974_snd_controls,
642 ARRAY_SIZE(wm8974_snd_controls)); 642 ARRAY_SIZE(wm8974_snd_controls));
643 wm8974_add_widgets(codec); 643 wm8974_add_widgets(codec);
644 ret = snd_soc_init_card(socdev);
645 if (ret < 0) {
646 dev_err(codec->dev, "failed to register card: %d\n", ret);
647 goto card_err;
648 }
649 644
650 return ret; 645 return ret;
651 646
652card_err:
653 snd_soc_free_pcms(socdev);
654 snd_soc_dapm_free(socdev);
655pcm_err: 647pcm_err:
656 return ret; 648 return ret;
657} 649}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d8d8f68b81ea..bee292e37d1b 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -792,17 +792,8 @@ static int wm8988_probe(struct platform_device *pdev)
792 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 792 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
793 snd_soc_dapm_new_widgets(codec); 793 snd_soc_dapm_new_widgets(codec);
794 794
795 ret = snd_soc_init_card(socdev);
796 if (ret < 0) {
797 dev_err(codec->dev, "failed to register card: %d\n", ret);
798 goto card_err;
799 }
800
801 return ret; 795 return ret;
802 796
803card_err:
804 snd_soc_free_pcms(socdev);
805 snd_soc_dapm_free(socdev);
806pcm_err: 797pcm_err:
807 return ret; 798 return ret;
808} 799}
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index f657e9a5fe26..e43cb2c8b915 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1409,16 +1409,9 @@ static int wm8990_init(struct snd_soc_device *socdev)
1409 snd_soc_add_controls(codec, wm8990_snd_controls, 1409 snd_soc_add_controls(codec, wm8990_snd_controls,
1410 ARRAY_SIZE(wm8990_snd_controls)); 1410 ARRAY_SIZE(wm8990_snd_controls));
1411 wm8990_add_widgets(codec); 1411 wm8990_add_widgets(codec);
1412 ret = snd_soc_init_card(socdev); 1412
1413 if (ret < 0) {
1414 printk(KERN_ERR "wm8990: failed to register card\n");
1415 goto card_err;
1416 }
1417 return ret; 1413 return ret;
1418 1414
1419card_err:
1420 snd_soc_free_pcms(socdev);
1421 snd_soc_dapm_free(socdev);
1422pcm_err: 1415pcm_err:
1423 kfree(codec->reg_cache); 1416 kfree(codec->reg_cache);
1424 return ret; 1417 return ret;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index dac397712147..0d4d2be92b64 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1466,17 +1466,8 @@ static int wm8993_probe(struct platform_device *pdev)
1466 1466
1467 snd_soc_dapm_new_widgets(codec); 1467 snd_soc_dapm_new_widgets(codec);
1468 1468
1469 ret = snd_soc_init_card(socdev);
1470 if (ret < 0) {
1471 dev_err(codec->dev, "failed to register card\n");
1472 goto card_err;
1473 }
1474
1475 return ret; 1469 return ret;
1476 1470
1477card_err:
1478 snd_soc_free_pcms(socdev);
1479 snd_soc_dapm_free(socdev);
1480err: 1471err:
1481 return ret; 1472 return ret;
1482} 1473}
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 4cb6b104b729..3f1f84421312 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1264,17 +1264,8 @@ static int wm9081_probe(struct platform_device *pdev)
1264 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 1264 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
1265 snd_soc_dapm_new_widgets(codec); 1265 snd_soc_dapm_new_widgets(codec);
1266 1266
1267 ret = snd_soc_init_card(socdev);
1268 if (ret < 0) {
1269 dev_err(codec->dev, "failed to register card: %d\n", ret);
1270 goto card_err;
1271 }
1272
1273 return ret; 1267 return ret;
1274 1268
1275card_err:
1276 snd_soc_free_pcms(socdev);
1277 snd_soc_dapm_free(socdev);
1278pcm_err: 1269pcm_err:
1279 return ret; 1270 return ret;
1280} 1271}
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index e7d2840d9e59..0e817b8705cd 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -403,16 +403,8 @@ static int wm9705_soc_probe(struct platform_device *pdev)
403 ARRAY_SIZE(wm9705_snd_ac97_controls)); 403 ARRAY_SIZE(wm9705_snd_ac97_controls));
404 wm9705_add_widgets(codec); 404 wm9705_add_widgets(codec);
405 405
406 ret = snd_soc_init_card(socdev);
407 if (ret < 0) {
408 printk(KERN_ERR "wm9705: failed to register card\n");
409 goto reset_err;
410 }
411
412 return 0; 406 return 0;
413 407
414reset_err:
415 snd_soc_free_pcms(socdev);
416pcm_err: 408pcm_err:
417 snd_soc_free_ac97_codec(codec); 409 snd_soc_free_ac97_codec(codec);
418codec_err: 410codec_err:
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 1fd4e88f50cf..155cacf124ea 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -695,17 +695,9 @@ static int wm9712_soc_probe(struct platform_device *pdev)
695 snd_soc_add_controls(codec, wm9712_snd_ac97_controls, 695 snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
696 ARRAY_SIZE(wm9712_snd_ac97_controls)); 696 ARRAY_SIZE(wm9712_snd_ac97_controls));
697 wm9712_add_widgets(codec); 697 wm9712_add_widgets(codec);
698 ret = snd_soc_init_card(socdev);
699 if (ret < 0) {
700 printk(KERN_ERR "wm9712: failed to register card\n");
701 goto reset_err;
702 }
703 698
704 return 0; 699 return 0;
705 700
706reset_err:
707 snd_soc_free_pcms(socdev);
708
709pcm_err: 701pcm_err:
710 snd_soc_free_ac97_codec(codec); 702 snd_soc_free_ac97_codec(codec);
711 703
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index ca3d449ed89e..5f81ecd20a81 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1247,13 +1247,8 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1247 snd_soc_add_controls(codec, wm9713_snd_ac97_controls, 1247 snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
1248 ARRAY_SIZE(wm9713_snd_ac97_controls)); 1248 ARRAY_SIZE(wm9713_snd_ac97_controls));
1249 wm9713_add_widgets(codec); 1249 wm9713_add_widgets(codec);
1250 ret = snd_soc_init_card(socdev);
1251 if (ret < 0)
1252 goto reset_err;
1253 return 0;
1254 1250
1255reset_err: 1251 return 0;
1256 snd_soc_free_pcms(socdev);
1257 1252
1258pcm_err: 1253pcm_err:
1259 snd_soc_free_ac97_codec(codec); 1254 snd_soc_free_ac97_codec(codec);
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 6096d22283e6..9c88e15ce693 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -58,43 +58,11 @@ static void psc_dma_bcom_enqueue_next_buffer(struct psc_dma_stream *s)
58 /* Prepare and enqueue the next buffer descriptor */ 58 /* Prepare and enqueue the next buffer descriptor */
59 bd = bcom_prepare_next_buffer(s->bcom_task); 59 bd = bcom_prepare_next_buffer(s->bcom_task);
60 bd->status = s->period_bytes; 60 bd->status = s->period_bytes;
61 bd->data[0] = s->period_next_pt; 61 bd->data[0] = s->runtime->dma_addr + (s->period_next * s->period_bytes);
62 bcom_submit_next_buffer(s->bcom_task, NULL); 62 bcom_submit_next_buffer(s->bcom_task, NULL);
63 63
64 /* Update for next period */ 64 /* Update for next period */
65 s->period_next_pt += s->period_bytes; 65 s->period_next = (s->period_next + 1) % s->runtime->periods;
66 if (s->period_next_pt >= s->period_end)
67 s->period_next_pt = s->period_start;
68}
69
70static void psc_dma_bcom_enqueue_tx(struct psc_dma_stream *s)
71{
72 if (s->appl_ptr > s->runtime->control->appl_ptr) {
73 /*
74 * In this case s->runtime->control->appl_ptr has wrapped around.
75 * Play the data to the end of the boundary, then wrap our own
76 * appl_ptr back around.
77 */
78 while (s->appl_ptr < s->runtime->boundary) {
79 if (bcom_queue_full(s->bcom_task))
80 return;
81
82 s->appl_ptr += s->period_size;
83
84 psc_dma_bcom_enqueue_next_buffer(s);
85 }
86 s->appl_ptr -= s->runtime->boundary;
87 }
88
89 while (s->appl_ptr < s->runtime->control->appl_ptr) {
90
91 if (bcom_queue_full(s->bcom_task))
92 return;
93
94 s->appl_ptr += s->period_size;
95
96 psc_dma_bcom_enqueue_next_buffer(s);
97 }
98} 66}
99 67
100/* Bestcomm DMA irq handler */ 68/* Bestcomm DMA irq handler */
@@ -108,11 +76,11 @@ static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream)
108 while (bcom_buffer_done(s->bcom_task)) { 76 while (bcom_buffer_done(s->bcom_task)) {
109 bcom_retrieve_buffer(s->bcom_task, NULL, NULL); 77 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
110 78
111 s->period_current_pt += s->period_bytes; 79 s->period_current = (s->period_current+1) % s->runtime->periods;
112 if (s->period_current_pt >= s->period_end) 80 s->period_count++;
113 s->period_current_pt = s->period_start; 81
82 psc_dma_bcom_enqueue_next_buffer(s);
114 } 83 }
115 psc_dma_bcom_enqueue_tx(s);
116 spin_unlock(&s->psc_dma->lock); 84 spin_unlock(&s->psc_dma->lock);
117 85
118 /* If the stream is active, then also inform the PCM middle layer 86 /* If the stream is active, then also inform the PCM middle layer
@@ -133,9 +101,8 @@ static irqreturn_t psc_dma_bcom_irq_rx(int irq, void *_psc_dma_stream)
133 while (bcom_buffer_done(s->bcom_task)) { 101 while (bcom_buffer_done(s->bcom_task)) {
134 bcom_retrieve_buffer(s->bcom_task, NULL, NULL); 102 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
135 103
136 s->period_current_pt += s->period_bytes; 104 s->period_current = (s->period_current+1) % s->runtime->periods;
137 if (s->period_current_pt >= s->period_end) 105 s->period_count++;
138 s->period_current_pt = s->period_start;
139 106
140 psc_dma_bcom_enqueue_next_buffer(s); 107 psc_dma_bcom_enqueue_next_buffer(s);
141 } 108 }
@@ -166,54 +133,38 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
166 struct snd_soc_pcm_runtime *rtd = substream->private_data; 133 struct snd_soc_pcm_runtime *rtd = substream->private_data;
167 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 134 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
168 struct snd_pcm_runtime *runtime = substream->runtime; 135 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct psc_dma_stream *s; 136 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
170 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 137 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
171 u16 imr; 138 u16 imr;
172 unsigned long flags; 139 unsigned long flags;
173 int i; 140 int i;
174 141
175 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
176 s = &psc_dma->capture;
177 else
178 s = &psc_dma->playback;
179
180 dev_dbg(psc_dma->dev, "psc_dma_trigger(substream=%p, cmd=%i)"
181 " stream_id=%i\n",
182 substream, cmd, substream->pstr->stream);
183
184 switch (cmd) { 142 switch (cmd) {
185 case SNDRV_PCM_TRIGGER_START: 143 case SNDRV_PCM_TRIGGER_START:
144 dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n",
145 substream->pstr->stream, runtime->frame_bits,
146 (int)runtime->period_size, runtime->periods);
186 s->period_bytes = frames_to_bytes(runtime, 147 s->period_bytes = frames_to_bytes(runtime,
187 runtime->period_size); 148 runtime->period_size);
188 s->period_start = virt_to_phys(runtime->dma_area); 149 s->period_next = 0;
189 s->period_end = s->period_start + 150 s->period_current = 0;
190 (s->period_bytes * runtime->periods);
191 s->period_next_pt = s->period_start;
192 s->period_current_pt = s->period_start;
193 s->period_size = runtime->period_size;
194 s->active = 1; 151 s->active = 1;
195 152 s->period_count = 0;
196 /* track appl_ptr so that we have a better chance of detecting
197 * end of stream and not over running it.
198 */
199 s->runtime = runtime; 153 s->runtime = runtime;
200 s->appl_ptr = s->runtime->control->appl_ptr -
201 (runtime->period_size * runtime->periods);
202 154
203 /* Fill up the bestcomm bd queue and enable DMA. 155 /* Fill up the bestcomm bd queue and enable DMA.
204 * This will begin filling the PSC's fifo. 156 * This will begin filling the PSC's fifo.
205 */ 157 */
206 spin_lock_irqsave(&psc_dma->lock, flags); 158 spin_lock_irqsave(&psc_dma->lock, flags);
207 159
208 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 160 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
209 bcom_gen_bd_rx_reset(s->bcom_task); 161 bcom_gen_bd_rx_reset(s->bcom_task);
210 for (i = 0; i < runtime->periods; i++) 162 else
211 if (!bcom_queue_full(s->bcom_task))
212 psc_dma_bcom_enqueue_next_buffer(s);
213 } else {
214 bcom_gen_bd_tx_reset(s->bcom_task); 163 bcom_gen_bd_tx_reset(s->bcom_task);
215 psc_dma_bcom_enqueue_tx(s); 164
216 } 165 for (i = 0; i < runtime->periods; i++)
166 if (!bcom_queue_full(s->bcom_task))
167 psc_dma_bcom_enqueue_next_buffer(s);
217 168
218 bcom_enable(s->bcom_task); 169 bcom_enable(s->bcom_task);
219 spin_unlock_irqrestore(&psc_dma->lock, flags); 170 spin_unlock_irqrestore(&psc_dma->lock, flags);
@@ -223,6 +174,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
223 break; 174 break;
224 175
225 case SNDRV_PCM_TRIGGER_STOP: 176 case SNDRV_PCM_TRIGGER_STOP:
177 dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n",
178 substream->pstr->stream, s->period_count);
226 s->active = 0; 179 s->active = 0;
227 180
228 spin_lock_irqsave(&psc_dma->lock, flags); 181 spin_lock_irqsave(&psc_dma->lock, flags);
@@ -236,7 +189,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
236 break; 189 break;
237 190
238 default: 191 default:
239 dev_dbg(psc_dma->dev, "invalid command\n"); 192 dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n",
193 substream->pstr->stream, cmd);
240 return -EINVAL; 194 return -EINVAL;
241 } 195 }
242 196
@@ -343,7 +297,7 @@ psc_dma_pointer(struct snd_pcm_substream *substream)
343 else 297 else
344 s = &psc_dma->playback; 298 s = &psc_dma->playback;
345 299
346 count = s->period_current_pt - s->period_start; 300 count = s->period_current * s->period_bytes;
347 301
348 return bytes_to_frames(substream->runtime, count); 302 return bytes_to_frames(substream->runtime, count);
349} 303}
diff --git a/sound/soc/fsl/mpc5200_dma.h b/sound/soc/fsl/mpc5200_dma.h
index 8d396bb9d9fe..22208b373fb9 100644
--- a/sound/soc/fsl/mpc5200_dma.h
+++ b/sound/soc/fsl/mpc5200_dma.h
@@ -13,26 +13,25 @@
13 * @psc_dma: pointer back to parent psc_dma data structure 13 * @psc_dma: pointer back to parent psc_dma data structure
14 * @bcom_task: bestcomm task structure 14 * @bcom_task: bestcomm task structure
15 * @irq: irq number for bestcomm task 15 * @irq: irq number for bestcomm task
16 * @period_start: physical address of start of DMA region
17 * @period_end: physical address of end of DMA region 16 * @period_end: physical address of end of DMA region
18 * @period_next_pt: physical address of next DMA buffer to enqueue 17 * @period_next_pt: physical address of next DMA buffer to enqueue
19 * @period_bytes: size of DMA period in bytes 18 * @period_bytes: size of DMA period in bytes
19 * @ac97_slot_bits: Enable bits for turning on the correct AC97 slot
20 */ 20 */
21struct psc_dma_stream { 21struct psc_dma_stream {
22 struct snd_pcm_runtime *runtime; 22 struct snd_pcm_runtime *runtime;
23 snd_pcm_uframes_t appl_ptr;
24
25 int active; 23 int active;
26 struct psc_dma *psc_dma; 24 struct psc_dma *psc_dma;
27 struct bcom_task *bcom_task; 25 struct bcom_task *bcom_task;
28 int irq; 26 int irq;
29 struct snd_pcm_substream *stream; 27 struct snd_pcm_substream *stream;
30 dma_addr_t period_start; 28 int period_next;
31 dma_addr_t period_end; 29 int period_current;
32 dma_addr_t period_next_pt;
33 dma_addr_t period_current_pt;
34 int period_bytes; 30 int period_bytes;
35 int period_size; 31 int period_count;
32
33 /* AC97 state */
34 u32 ac97_slot_bits;
36}; 35};
37 36
38/** 37/**
@@ -73,6 +72,15 @@ struct psc_dma {
73 } stats; 72 } stats;
74}; 73};
75 74
75/* Utility for retrieving psc_dma_stream structure from a substream */
76inline struct psc_dma_stream *
77to_psc_dma_stream(struct snd_pcm_substream *substream, struct psc_dma *psc_dma)
78{
79 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
80 return &psc_dma->capture;
81 return &psc_dma->playback;
82}
83
76int mpc5200_audio_dma_create(struct of_device *op); 84int mpc5200_audio_dma_create(struct of_device *op);
77int mpc5200_audio_dma_destroy(struct of_device *op); 85int mpc5200_audio_dma_destroy(struct of_device *op);
78 86
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index c4ae3e096bb9..3dbc7f7cd7b9 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -130,6 +130,7 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
130 struct snd_soc_dai *cpu_dai) 130 struct snd_soc_dai *cpu_dai)
131{ 131{
132 struct psc_dma *psc_dma = cpu_dai->private_data; 132 struct psc_dma *psc_dma = cpu_dai->private_data;
133 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
133 134
134 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i" 135 dev_dbg(psc_dma->dev, "%s(substream=%p) p_size=%i p_bytes=%i"
135 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i" 136 " periods=%i buffer_size=%i buffer_bytes=%i channels=%i"
@@ -140,20 +141,10 @@ static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream,
140 params_channels(params), params_rate(params), 141 params_channels(params), params_rate(params),
141 params_format(params)); 142 params_format(params));
142 143
143 144 /* Determine the set of enable bits to turn on */
144 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 145 s->ac97_slot_bits = (params_channels(params) == 1) ? 0x100 : 0x300;
145 if (params_channels(params) == 1) 146 if (substream->pstr->stream != SNDRV_PCM_STREAM_CAPTURE)
146 psc_dma->slots |= 0x00000100; 147 s->ac97_slot_bits <<= 16;
147 else
148 psc_dma->slots |= 0x00000300;
149 } else {
150 if (params_channels(params) == 1)
151 psc_dma->slots |= 0x01000000;
152 else
153 psc_dma->slots |= 0x03000000;
154 }
155 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
156
157 return 0; 148 return 0;
158} 149}
159 150
@@ -163,6 +154,8 @@ static int psc_ac97_hw_digital_params(struct snd_pcm_substream *substream,
163{ 154{
164 struct psc_dma *psc_dma = cpu_dai->private_data; 155 struct psc_dma *psc_dma = cpu_dai->private_data;
165 156
157 dev_dbg(psc_dma->dev, "%s(substream=%p)\n", __func__, substream);
158
166 if (params_channels(params) == 1) 159 if (params_channels(params) == 1)
167 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000); 160 out_be32(&psc_dma->psc_regs->ac97_slots, 0x01000000);
168 else 161 else
@@ -176,14 +169,24 @@ static int psc_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
176{ 169{
177 struct snd_soc_pcm_runtime *rtd = substream->private_data; 170 struct snd_soc_pcm_runtime *rtd = substream->private_data;
178 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 171 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
172 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
179 173
180 switch (cmd) { 174 switch (cmd) {
175 case SNDRV_PCM_TRIGGER_START:
176 dev_dbg(psc_dma->dev, "AC97 START: stream=%i\n",
177 substream->pstr->stream);
178
179 /* Set the slot enable bits */
180 psc_dma->slots |= s->ac97_slot_bits;
181 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
182 break;
183
181 case SNDRV_PCM_TRIGGER_STOP: 184 case SNDRV_PCM_TRIGGER_STOP:
182 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) 185 dev_dbg(psc_dma->dev, "AC97 STOP: stream=%i\n",
183 psc_dma->slots &= 0xFFFF0000; 186 substream->pstr->stream);
184 else
185 psc_dma->slots &= 0x0000FFFF;
186 187
188 /* Clear the slot enable bits */
189 psc_dma->slots &= ~(s->ac97_slot_bits);
187 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots); 190 out_be32(&psc_dma->psc_regs->ac97_slots, psc_dma->slots);
188 break; 191 break;
189 } 192 }
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 2dee9839be86..bb5731a22bed 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -21,7 +21,18 @@ config SND_OMAP_SOC_AMS_DELTA
21 select SND_OMAP_SOC_MCBSP 21 select SND_OMAP_SOC_MCBSP
22 select SND_SOC_CX20442 22 select SND_SOC_CX20442
23 help 23 help
24 Say Y if you want to add support for SoC audio on Amstrad Delta. 24 Say Y if you want to add support for SoC audio device connected to
25 a handset and a speakerphone found on Amstrad E3 (Delta) videophone.
26
27 Note that in order to get those devices fully supported, you have to
28 build the kernel with standard serial port driver included and
29 configured for at least 4 ports. Then, from userspace, you must load
30 a line discipline #19 on the modem (ttyS3) serial line. The simplest
31 way to achieve this is to install util-linux-ng and use the included
32 ldattach utility. This can be started automatically from udev,
33 a simple rule like this one should do the trick (it does for me):
34 ACTION=="add", KERNEL=="controlC0", \
35 RUN+="/usr/sbin/ldattach 19 /dev/ttyS3"
25 36
26config SND_OMAP_SOC_OSK5912 37config SND_OMAP_SOC_OSK5912
27 tristate "SoC Audio support for omap osk5912" 38 tristate "SoC Audio support for omap osk5912"
@@ -55,6 +66,15 @@ config SND_OMAP_SOC_OMAP3EVM
55 help 66 help
56 Say Y if you want to add support for SoC audio on the omap3evm board. 67 Say Y if you want to add support for SoC audio on the omap3evm board.
57 68
69config SND_OMAP_SOC_AM3517EVM
70 tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
71 depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
72 select SND_OMAP_SOC_MCBSP
73 select SND_SOC_TLV320AIC23
74 help
75 Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
76 EVM.
77
58config SND_OMAP_SOC_SDP3430 78config SND_OMAP_SOC_SDP3430
59 tristate "SoC Audio support for Texas Instruments SDP3430" 79 tristate "SoC Audio support for Texas Instruments SDP3430"
60 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP 80 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 02d69471dcb5..0c78ae4e6b97 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -12,6 +12,7 @@ snd-soc-osk5912-objs := osk5912.o
12snd-soc-overo-objs := overo.o 12snd-soc-overo-objs := overo.o
13snd-soc-omap2evm-objs := omap2evm.o 13snd-soc-omap2evm-objs := omap2evm.o
14snd-soc-omap3evm-objs := omap3evm.o 14snd-soc-omap3evm-objs := omap3evm.o
15snd-soc-am3517evm-objs := am3517evm.o
15snd-soc-sdp3430-objs := sdp3430.o 16snd-soc-sdp3430-objs := sdp3430.o
16snd-soc-omap3pandora-objs := omap3pandora.o 17snd-soc-omap3pandora-objs := omap3pandora.o
17snd-soc-omap3beagle-objs := omap3beagle.o 18snd-soc-omap3beagle-objs := omap3beagle.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
23obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 24obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
24obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 25obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
25obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o 26obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o
27obj-$(CONFIG_MACH_OMAP3517EVM) += snd-soc-am3517evm.o
26obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 28obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
27obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 29obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
28obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 30obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
new file mode 100644
index 000000000000..135901b2ea11
--- /dev/null
+++ b/sound/soc/omap/am3517evm.c
@@ -0,0 +1,202 @@
1/*
2 * am3517evm.c -- ALSA SoC support for OMAP3517 / AM3517 EVM
3 *
4 * Author: Anuj Aggarwal <anuj.aggarwal@ti.com>
5 *
6 * Based on sound/soc/omap/beagle.c by Steve Sakoman
7 *
8 * Copyright (C) 2009 Texas Instruments Incorporated
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation version 2.
13 *
14 * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
15 * whether express or implied; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 */
19
20#include <linux/clk.h>
21#include <linux/platform_device.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/soc.h>
25#include <sound/soc-dapm.h>
26
27#include <asm/mach-types.h>
28#include <mach/hardware.h>
29#include <mach/gpio.h>
30#include <plat/mcbsp.h>
31
32#include "omap-mcbsp.h"
33#include "omap-pcm.h"
34
35#include "../codecs/tlv320aic23.h"
36
37#define CODEC_CLOCK 12000000
38
39static int am3517evm_hw_params(struct snd_pcm_substream *substream,
40 struct snd_pcm_hw_params *params)
41{
42 struct snd_soc_pcm_runtime *rtd = substream->private_data;
43 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
44 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
45 int ret;
46
47 /* Set codec DAI configuration */
48 ret = snd_soc_dai_set_fmt(codec_dai,
49 SND_SOC_DAIFMT_DSP_B |
50 SND_SOC_DAIFMT_NB_NF |
51 SND_SOC_DAIFMT_CBM_CFM);
52 if (ret < 0) {
53 printk(KERN_ERR "can't set codec DAI configuration\n");
54 return ret;
55 }
56
57 /* Set cpu DAI configuration */
58 ret = snd_soc_dai_set_fmt(cpu_dai,
59 SND_SOC_DAIFMT_DSP_B |
60 SND_SOC_DAIFMT_NB_NF |
61 SND_SOC_DAIFMT_CBM_CFM);
62 if (ret < 0) {
63 printk(KERN_ERR "can't set cpu DAI configuration\n");
64 return ret;
65 }
66
67 /* Set the codec system clock for DAC and ADC */
68 ret = snd_soc_dai_set_sysclk(codec_dai, 0,
69 CODEC_CLOCK, SND_SOC_CLOCK_IN);
70 if (ret < 0) {
71 printk(KERN_ERR "can't set codec system clock\n");
72 return ret;
73 }
74
75 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_CLKR_SRC_CLKX, 0,
76 SND_SOC_CLOCK_IN);
77 if (ret < 0) {
78 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_CLKR_SRC_CLKX\n");
79 return ret;
80 }
81
82 snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
83 SND_SOC_CLOCK_IN);
84 if (ret < 0) {
85 printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
86 return ret;
87 }
88
89 return 0;
90}
91
92static struct snd_soc_ops am3517evm_ops = {
93 .hw_params = am3517evm_hw_params,
94};
95
96/* am3517evm machine dapm widgets */
97static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
98 SND_SOC_DAPM_HP("Line Out", NULL),
99 SND_SOC_DAPM_LINE("Line In", NULL),
100 SND_SOC_DAPM_MIC("Mic In", NULL),
101};
102
103static const struct snd_soc_dapm_route audio_map[] = {
104 /* Line Out connected to LLOUT, RLOUT */
105 {"Line Out", NULL, "LOUT"},
106 {"Line Out", NULL, "ROUT"},
107
108 {"LLINEIN", NULL, "Line In"},
109 {"RLINEIN", NULL, "Line In"},
110
111 {"MICIN", NULL, "Mic In"},
112};
113
114static int am3517evm_aic23_init(struct snd_soc_codec *codec)
115{
116 /* Add am3517-evm specific widgets */
117 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
118 ARRAY_SIZE(tlv320aic23_dapm_widgets));
119
120 /* Set up davinci-evm specific audio path audio_map */
121 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
122
123 /* always connected */
124 snd_soc_dapm_enable_pin(codec, "Line Out");
125 snd_soc_dapm_enable_pin(codec, "Line In");
126 snd_soc_dapm_enable_pin(codec, "Mic In");
127
128 snd_soc_dapm_sync(codec);
129
130 return 0;
131}
132
133/* Digital audio interface glue - connects codec <--> CPU */
134static struct snd_soc_dai_link am3517evm_dai = {
135 .name = "TLV320AIC23",
136 .stream_name = "AIC23",
137 .cpu_dai = &omap_mcbsp_dai[0],
138 .codec_dai = &tlv320aic23_dai,
139 .init = am3517evm_aic23_init,
140 .ops = &am3517evm_ops,
141};
142
143/* Audio machine driver */
144static struct snd_soc_card snd_soc_am3517evm = {
145 .name = "am3517evm",
146 .platform = &omap_soc_platform,
147 .dai_link = &am3517evm_dai,
148 .num_links = 1,
149};
150
151/* Audio subsystem */
152static struct snd_soc_device am3517evm_snd_devdata = {
153 .card = &snd_soc_am3517evm,
154 .codec_dev = &soc_codec_dev_tlv320aic23,
155};
156
157static struct platform_device *am3517evm_snd_device;
158
159static int __init am3517evm_soc_init(void)
160{
161 int ret;
162
163 if (!machine_is_omap3517evm()) {
164 pr_err("Not OMAP3517 / AM3517 EVM!\n");
165 return -ENODEV;
166 }
167 pr_info("OMAP3517 / AM3517 EVM SoC init\n");
168
169 am3517evm_snd_device = platform_device_alloc("soc-audio", -1);
170 if (!am3517evm_snd_device) {
171 printk(KERN_ERR "Platform device allocation failed\n");
172 return -ENOMEM;
173 }
174
175 platform_set_drvdata(am3517evm_snd_device, &am3517evm_snd_devdata);
176 am3517evm_snd_devdata.dev = &am3517evm_snd_device->dev;
177 *(unsigned int *)am3517evm_dai.cpu_dai->private_data = 0; /* McBSP1 */
178
179 ret = platform_device_add(am3517evm_snd_device);
180 if (ret)
181 goto err1;
182
183 return 0;
184
185err1:
186 printk(KERN_ERR "Unable to add platform device\n");
187 platform_device_put(am3517evm_snd_device);
188
189 return ret;
190}
191
192static void __exit am3517evm_soc_exit(void)
193{
194 platform_device_unregister(am3517evm_snd_device);
195}
196
197module_init(am3517evm_soc_init);
198module_exit(am3517evm_soc_exit);
199
200MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
201MODULE_DESCRIPTION("ALSA SoC OMAP3517 / AM3517 EVM");
202MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 3341f49402ca..45be94201c89 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -49,6 +49,8 @@ struct omap_mcbsp_data {
49 */ 49 */
50 int active; 50 int active;
51 int configured; 51 int configured;
52 unsigned int in_freq;
53 int clk_div;
52}; 54};
53 55
54#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id) 56#define to_mcbsp(priv) container_of((priv), struct omap_mcbsp_data, bus_id)
@@ -257,7 +259,7 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
257 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id; 259 int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
258 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT; 260 int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
259 unsigned long port; 261 unsigned long port;
260 unsigned int format; 262 unsigned int format, div, framesize, master;
261 263
262 if (cpu_class_is_omap1()) { 264 if (cpu_class_is_omap1()) {
263 dma = omap1_dma_reqs[bus_id][substream->stream]; 265 dma = omap1_dma_reqs[bus_id][substream->stream];
@@ -294,28 +296,19 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
294 296
295 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK; 297 format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
296 wpf = channels = params_channels(params); 298 wpf = channels = params_channels(params);
297 switch (channels) { 299 if (channels == 2 && format == SND_SOC_DAIFMT_I2S) {
298 case 2: 300 /* Use dual-phase frames */
299 if (format == SND_SOC_DAIFMT_I2S) { 301 regs->rcr2 |= RPHASE;
300 /* Use dual-phase frames */ 302 regs->xcr2 |= XPHASE;
301 regs->rcr2 |= RPHASE; 303 /* Set 1 word per (McBSP) frame for phase1 and phase2 */
302 regs->xcr2 |= XPHASE; 304 wpf--;
303 /* Set 1 word per (McBSP) frame for phase1 and phase2 */ 305 regs->rcr2 |= RFRLEN2(wpf - 1);
304 wpf--; 306 regs->xcr2 |= XFRLEN2(wpf - 1);
305 regs->rcr2 |= RFRLEN2(wpf - 1);
306 regs->xcr2 |= XFRLEN2(wpf - 1);
307 }
308 case 1:
309 case 4:
310 /* Set word per (McBSP) frame for phase1 */
311 regs->rcr1 |= RFRLEN1(wpf - 1);
312 regs->xcr1 |= XFRLEN1(wpf - 1);
313 break;
314 default:
315 /* Unsupported number of channels */
316 return -EINVAL;
317 } 307 }
318 308
309 regs->rcr1 |= RFRLEN1(wpf - 1);
310 regs->xcr1 |= XFRLEN1(wpf - 1);
311
319 switch (params_format(params)) { 312 switch (params_format(params)) {
320 case SNDRV_PCM_FORMAT_S16_LE: 313 case SNDRV_PCM_FORMAT_S16_LE:
321 /* Set word lengths */ 314 /* Set word lengths */
@@ -330,15 +323,30 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
330 return -EINVAL; 323 return -EINVAL;
331 } 324 }
332 325
326 /* In McBSP master modes, FRAME (i.e. sample rate) is generated
327 * by _counting_ BCLKs. Calculate frame size in BCLKs */
328 master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
329 if (master == SND_SOC_DAIFMT_CBS_CFS) {
330 div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
331 framesize = (mcbsp_data->in_freq / div) / params_rate(params);
332
333 if (framesize < wlen * channels) {
334 printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
335 "channels\n", __func__);
336 return -EINVAL;
337 }
338 } else
339 framesize = wlen * channels;
340
333 /* Set FS period and length in terms of bit clock periods */ 341 /* Set FS period and length in terms of bit clock periods */
334 switch (format) { 342 switch (format) {
335 case SND_SOC_DAIFMT_I2S: 343 case SND_SOC_DAIFMT_I2S:
336 regs->srgr2 |= FPER(wlen * channels - 1); 344 regs->srgr2 |= FPER(framesize - 1);
337 regs->srgr1 |= FWID(wlen - 1); 345 regs->srgr1 |= FWID((framesize >> 1) - 1);
338 break; 346 break;
339 case SND_SOC_DAIFMT_DSP_A: 347 case SND_SOC_DAIFMT_DSP_A:
340 case SND_SOC_DAIFMT_DSP_B: 348 case SND_SOC_DAIFMT_DSP_B:
341 regs->srgr2 |= FPER(wlen * channels - 1); 349 regs->srgr2 |= FPER(framesize - 1);
342 regs->srgr1 |= FWID(0); 350 regs->srgr1 |= FWID(0);
343 break; 351 break;
344 } 352 }
@@ -454,6 +462,7 @@ static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
454 if (div_id != OMAP_MCBSP_CLKGDV) 462 if (div_id != OMAP_MCBSP_CLKGDV)
455 return -ENODEV; 463 return -ENODEV;
456 464
465 mcbsp_data->clk_div = div;
457 regs->srgr1 |= CLKGDV(div - 1); 466 regs->srgr1 |= CLKGDV(div - 1);
458 467
459 return 0; 468 return 0;
@@ -554,6 +563,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
554 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs; 563 struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
555 int err = 0; 564 int err = 0;
556 565
566 mcbsp_data->in_freq = freq;
567
557 switch (clk_id) { 568 switch (clk_id) {
558 case OMAP_MCBSP_SYSCLK_CLK: 569 case OMAP_MCBSP_SYSCLK_CLK:
559 regs->srgr2 |= CLKSM; 570 regs->srgr2 |= CLKSM;
@@ -598,13 +609,13 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
598 .id = (link_id), \ 609 .id = (link_id), \
599 .playback = { \ 610 .playback = { \
600 .channels_min = 1, \ 611 .channels_min = 1, \
601 .channels_max = 4, \ 612 .channels_max = 16, \
602 .rates = OMAP_MCBSP_RATES, \ 613 .rates = OMAP_MCBSP_RATES, \
603 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 614 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
604 }, \ 615 }, \
605 .capture = { \ 616 .capture = { \
606 .channels_min = 1, \ 617 .channels_min = 1, \
607 .channels_max = 4, \ 618 .channels_max = 16, \
608 .rates = OMAP_MCBSP_RATES, \ 619 .rates = OMAP_MCBSP_RATES, \
609 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 620 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
610 }, \ 621 }, \
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 9114c263077b..8deb59bb10b1 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -93,10 +93,17 @@ static struct snd_soc_card snd_soc_omap3evm = {
93 .num_links = 1, 93 .num_links = 1,
94}; 94};
95 95
96/* twl4030 setup */
97static struct twl4030_setup_data twl4030_setup = {
98 .ramp_delay_value = 4,
99 .sysclk = 26000,
100};
101
96/* Audio subsystem */ 102/* Audio subsystem */
97static struct snd_soc_device omap3evm_snd_devdata = { 103static struct snd_soc_device omap3evm_snd_devdata = {
98 .card = &snd_soc_omap3evm, 104 .card = &snd_soc_omap3evm,
99 .codec_dev = &soc_codec_dev_twl4030, 105 .codec_dev = &soc_codec_dev_twl4030,
106 .codec_data = &twl4030_setup,
100}; 107};
101 108
102static struct platform_device *omap3evm_snd_device; 109static struct platform_device *omap3evm_snd_device;
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index ad219aaf7cb8..cace5f13792d 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -40,9 +40,12 @@
40 40
41#define PREFIX "ASoC omap3pandora: " 41#define PREFIX "ASoC omap3pandora: "
42 42
43static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai, 43static int omap3pandora_cmn_hw_params(struct snd_pcm_substream *substream,
44 struct snd_soc_dai *cpu_dai, unsigned int fmt) 44 struct snd_pcm_hw_params *params, unsigned int fmt)
45{ 45{
46 struct snd_soc_pcm_runtime *rtd = substream->private_data;
47 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
48 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
46 int ret; 49 int ret;
47 50
48 /* Set codec DAI configuration */ 51 /* Set codec DAI configuration */
@@ -68,8 +71,9 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
68 } 71 }
69 72
70 /* Set McBSP clock to external */ 73 /* Set McBSP clock to external */
71 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0, 74 ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT,
72 SND_SOC_CLOCK_IN); 75 256 * params_rate(params),
76 SND_SOC_CLOCK_IN);
73 if (ret < 0) { 77 if (ret < 0) {
74 pr_err(PREFIX "can't set cpu system clock\n"); 78 pr_err(PREFIX "can't set cpu system clock\n");
75 return ret; 79 return ret;
@@ -87,11 +91,7 @@ static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
87static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream, 91static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
88 struct snd_pcm_hw_params *params) 92 struct snd_pcm_hw_params *params)
89{ 93{
90 struct snd_soc_pcm_runtime *rtd = substream->private_data; 94 return omap3pandora_cmn_hw_params(substream, params,
91 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
93
94 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
95 SND_SOC_DAIFMT_I2S | 95 SND_SOC_DAIFMT_I2S |
96 SND_SOC_DAIFMT_IB_NF | 96 SND_SOC_DAIFMT_IB_NF |
97 SND_SOC_DAIFMT_CBS_CFS); 97 SND_SOC_DAIFMT_CBS_CFS);
@@ -100,11 +100,7 @@ static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
100static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream, 100static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
101 struct snd_pcm_hw_params *params) 101 struct snd_pcm_hw_params *params)
102{ 102{
103 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 return omap3pandora_cmn_hw_params(substream, params,
104 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
105 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
106
107 return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
108 SND_SOC_DAIFMT_I2S | 104 SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF | 105 SND_SOC_DAIFMT_NB_NF |
110 SND_SOC_DAIFMT_CBS_CFS); 106 SND_SOC_DAIFMT_CBS_CFS);
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index 27cf097c2b1d..151a69463269 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -74,11 +74,19 @@ static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream)
74{ 74{
75 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 75 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
76 dma_addr_t pos = prtd->dma_pos; 76 dma_addr_t pos = prtd->dma_pos;
77 unsigned int limit;
77 int ret; 78 int ret;
78 79
79 pr_debug("Entered %s\n", __func__); 80 pr_debug("Entered %s\n", __func__);
80 81
81 while (prtd->dma_loaded < prtd->dma_limit) { 82 if (s3c_dma_has_circular()) {
83 limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
84 } else
85 limit = prtd->dma_limit;
86
87 pr_debug("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
88
89 while (prtd->dma_loaded < limit) {
82 unsigned long len = prtd->dma_period; 90 unsigned long len = prtd->dma_period;
83 91
84 pr_debug("dma_loaded: %d\n", prtd->dma_loaded); 92 pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
@@ -122,7 +130,7 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
122 snd_pcm_period_elapsed(substream); 130 snd_pcm_period_elapsed(substream);
123 131
124 spin_lock(&prtd->lock); 132 spin_lock(&prtd->lock);
125 if (prtd->state & ST_RUNNING) { 133 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
126 prtd->dma_loaded--; 134 prtd->dma_loaded--;
127 s3c24xx_pcm_enqueue(substream); 135 s3c24xx_pcm_enqueue(substream);
128 } 136 }
@@ -163,6 +171,11 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
163 printk(KERN_ERR "failed to get dma channel\n"); 171 printk(KERN_ERR "failed to get dma channel\n");
164 return ret; 172 return ret;
165 } 173 }
174
175 /* use the circular buffering if we have it available. */
176 if (s3c_dma_has_circular())
177 s3c2410_dma_setflags(prtd->params->channel,
178 S3C2410_DMAF_CIRCULAR);
166 } 179 }
167 180
168 s3c2410_dma_set_buffdone_fn(prtd->params->channel, 181 s3c2410_dma_set_buffdone_fn(prtd->params->channel,
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index b67eed59666a..d68cae15561c 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -236,6 +236,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
236 goto err; 236 goto err;
237 } 237 }
238 238
239 clk_enable(i2s->iis_cclk);
240
239 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); 241 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
240 if (ret) 242 if (ret)
241 goto err_clk; 243 goto err_clk;
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
index 482aaf10eff6..cb8a9161b643 100644
--- a/sound/soc/s3c24xx/smdk64xx_wm8580.c
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -103,7 +103,7 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
103 if (ret < 0) 103 if (ret < 0)
104 return ret; 104 return ret;
105 105
106 /* Set WM8580 to drive MCLK from it's PLLA */ 106 /* Set WM8580 to drive MCLK from its PLLA */
107 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK, 107 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
108 WM8580_CLKSRC_PLLA); 108 WM8580_CLKSRC_PLLA);
109 if (ret < 0) 109 if (ret < 0)
@@ -115,7 +115,6 @@ static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
115 if (ret < 0) 115 if (ret < 0)
116 return ret; 116 return ret;
117 117
118 /* Assuming the CODEC driver evaluates it's rfs too from this call */
119 ret = snd_soc_dai_set_pll(codec_dai, 0, WM8580_PLLA, 118 ret = snd_soc_dai_set_pll(codec_dai, 0, WM8580_PLLA,
120 SMDK64XX_WM8580_FREQ, pll_out); 119 SMDK64XX_WM8580_FREQ, pll_out);
121 if (ret < 0) 120 if (ret < 0)
@@ -186,9 +185,10 @@ static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
186 /* Set up PAIFTX audio path */ 185 /* Set up PAIFTX audio path */
187 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx)); 186 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx));
188 187
189 /* All enabled by default */ 188 /* Enabling the microphone requires the fitting of a 0R
190 snd_soc_dapm_enable_pin(codec, "MicIn"); 189 * resistor to connect the line from the microphone jack.
191 snd_soc_dapm_enable_pin(codec, "LineIn"); 190 */
191 snd_soc_dapm_disable_pin(codec, "MicIn");
192 192
193 /* signal a DAPM event */ 193 /* signal a DAPM event */
194 snd_soc_dapm_sync(codec); 194 snd_soc_dapm_sync(codec);
@@ -205,11 +205,6 @@ static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec)
205 /* Set up PAIFRX audio path */ 205 /* Set up PAIFRX audio path */
206 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx)); 206 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx));
207 207
208 /* All enabled by default */
209 snd_soc_dapm_enable_pin(codec, "Front-L/R");
210 snd_soc_dapm_enable_pin(codec, "Center/Sub");
211 snd_soc_dapm_enable_pin(codec, "Rear-L/R");
212
213 /* signal a DAPM event */ 208 /* signal a DAPM event */
214 snd_soc_dapm_sync(codec); 209 snd_soc_dapm_sync(codec);
215 210
diff --git a/sound/soc/sh/Kconfig b/sound/soc/sh/Kconfig
index 9154b4363db3..9e6976586554 100644
--- a/sound/soc/sh/Kconfig
+++ b/sound/soc/sh/Kconfig
@@ -23,7 +23,6 @@ config SND_SOC_SH4_SSI
23config SND_SOC_SH4_FSI 23config SND_SOC_SH4_FSI
24 tristate "SH4 FSI support" 24 tristate "SH4 FSI support"
25 depends on CPU_SUBTYPE_SH7724 25 depends on CPU_SUBTYPE_SH7724
26 select SH_DMA
27 help 26 help
28 This option enables FSI sound support 27 This option enables FSI sound support
29 28
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 44123248b630..e1a3d1a2b4c8 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -26,8 +26,6 @@
26#include <sound/pcm_params.h> 26#include <sound/pcm_params.h>
27#include <sound/sh_fsi.h> 27#include <sound/sh_fsi.h>
28#include <asm/atomic.h> 28#include <asm/atomic.h>
29#include <asm/dma.h>
30#include <asm/dma-sh.h>
31 29
32#define DO_FMT 0x0000 30#define DO_FMT 0x0000
33#define DOFF_CTL 0x0004 31#define DOFF_CTL 0x0004
@@ -97,7 +95,6 @@ struct fsi_priv {
97 95
98 int fifo_max; 96 int fifo_max;
99 int chan; 97 int chan;
100 int dma_chan;
101 98
102 int byte_offset; 99 int byte_offset;
103 int period_len; 100 int period_len;
@@ -308,62 +305,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
308 return residue; 305 return residue;
309} 306}
310 307
311static int fsi_get_residue(struct fsi_priv *fsi, int is_play)
312{
313 int residue;
314 int width;
315 struct snd_pcm_runtime *runtime;
316
317 runtime = fsi->substream->runtime;
318
319 /* get 1 channel data width */
320 width = frames_to_bytes(runtime, 1) / fsi->chan;
321
322 if (2 == width)
323 residue = fsi_get_fifo_residue(fsi, is_play);
324 else
325 residue = get_dma_residue(fsi->dma_chan);
326
327 return residue;
328}
329
330/************************************************************************
331
332
333 basic dma function
334
335
336************************************************************************/
337#define PORTA_DMA 0
338#define PORTB_DMA 1
339
340static int fsi_get_dma_chan(void)
341{
342 if (0 != request_dma(PORTA_DMA, "fsia"))
343 return -EIO;
344
345 if (0 != request_dma(PORTB_DMA, "fsib")) {
346 free_dma(PORTA_DMA);
347 return -EIO;
348 }
349
350 master->fsia.dma_chan = PORTA_DMA;
351 master->fsib.dma_chan = PORTB_DMA;
352
353 return 0;
354}
355
356static void fsi_free_dma_chan(void)
357{
358 dma_wait_for_completion(PORTA_DMA);
359 dma_wait_for_completion(PORTB_DMA);
360 free_dma(PORTA_DMA);
361 free_dma(PORTB_DMA);
362
363 master->fsia.dma_chan = -1;
364 master->fsib.dma_chan = -1;
365}
366
367/************************************************************************ 308/************************************************************************
368 309
369 310
@@ -435,44 +376,6 @@ static void fsi_soft_all_reset(void)
435 mdelay(10); 376 mdelay(10);
436} 377}
437 378
438static void fsi_16data_push(struct fsi_priv *fsi,
439 struct snd_pcm_runtime *runtime,
440 int send)
441{
442 u16 *dma_start;
443 u32 snd;
444 int i;
445
446 /* get dma start position for FSI */
447 dma_start = (u16 *)runtime->dma_area;
448 dma_start += fsi->byte_offset / 2;
449
450 /*
451 * soft dma
452 * FSI can not use DMA when 16bpp
453 */
454 for (i = 0; i < send; i++) {
455 snd = (u32)dma_start[i];
456 fsi_reg_write(fsi, DODT, snd << 8);
457 }
458}
459
460static void fsi_32data_push(struct fsi_priv *fsi,
461 struct snd_pcm_runtime *runtime,
462 int send)
463{
464 u32 *dma_start;
465
466 /* get dma start position for FSI */
467 dma_start = (u32 *)runtime->dma_area;
468 dma_start += fsi->byte_offset / 4;
469
470 dma_wait_for_completion(fsi->dma_chan);
471 dma_configure_channel(fsi->dma_chan, (SM_INC|0x400|TS_32|TM_BUR));
472 dma_write(fsi->dma_chan, (u32)dma_start,
473 (u32)(fsi->base + DODT), send * 4);
474}
475
476/* playback interrupt */ 379/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi) 380static int fsi_data_push(struct fsi_priv *fsi)
478{ 381{
@@ -481,6 +384,8 @@ static int fsi_data_push(struct fsi_priv *fsi)
481 int send; 384 int send;
482 int fifo_free; 385 int fifo_free;
483 int width; 386 int width;
387 u8 *start;
388 int i;
484 389
485 if (!fsi || 390 if (!fsi ||
486 !fsi->substream || 391 !fsi->substream ||
@@ -515,12 +420,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
515 if (fifo_free < send) 420 if (fifo_free < send)
516 send = fifo_free; 421 send = fifo_free;
517 422
518 if (2 == width) 423 start = runtime->dma_area;
519 fsi_16data_push(fsi, runtime, send); 424 start += fsi->byte_offset;
520 else if (4 == width) 425
521 fsi_32data_push(fsi, runtime, send); 426 switch (width) {
522 else 427 case 2:
428 for (i = 0; i < send; i++)
429 fsi_reg_write(fsi, DODT,
430 ((u32)*((u16 *)start + i) << 8));
431 break;
432 case 4:
433 for (i = 0; i < send; i++)
434 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
435 break;
436 default:
523 return -EINVAL; 437 return -EINVAL;
438 }
524 439
525 fsi->byte_offset += send * width; 440 fsi->byte_offset += send * width;
526 441
@@ -532,6 +447,75 @@ static int fsi_data_push(struct fsi_priv *fsi)
532 return 0; 447 return 0;
533} 448}
534 449
450static int fsi_data_pop(struct fsi_priv *fsi)
451{
452 struct snd_pcm_runtime *runtime;
453 struct snd_pcm_substream *substream = NULL;
454 int free;
455 int fifo_fill;
456 int width;
457 u8 *start;
458 int i;
459
460 if (!fsi ||
461 !fsi->substream ||
462 !fsi->substream->runtime)
463 return -EINVAL;
464
465 runtime = fsi->substream->runtime;
466
467 /* FSI FIFO has limit.
468 * So, this driver can not send periods data at a time
469 */
470 if (fsi->byte_offset >=
471 fsi->period_len * (fsi->periods + 1)) {
472
473 substream = fsi->substream;
474 fsi->periods = (fsi->periods + 1) % runtime->periods;
475
476 if (0 == fsi->periods)
477 fsi->byte_offset = 0;
478 }
479
480 /* get 1 channel data width */
481 width = frames_to_bytes(runtime, 1) / fsi->chan;
482
483 /* get free space for alsa */
484 free = (fsi->buffer_len - fsi->byte_offset) / width;
485
486 /* get recv size */
487 fifo_fill = fsi_get_fifo_residue(fsi, 0);
488
489 if (free < fifo_fill)
490 fifo_fill = free;
491
492 start = runtime->dma_area;
493 start += fsi->byte_offset;
494
495 switch (width) {
496 case 2:
497 for (i = 0; i < fifo_fill; i++)
498 *((u16 *)start + i) =
499 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
500 break;
501 case 4:
502 for (i = 0; i < fifo_fill; i++)
503 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
504 break;
505 default:
506 return -EINVAL;
507 }
508
509 fsi->byte_offset += fifo_fill * width;
510
511 fsi_irq_enable(fsi, 0);
512
513 if (substream)
514 snd_pcm_period_elapsed(substream);
515
516 return 0;
517}
518
535static irqreturn_t fsi_interrupt(int irq, void *data) 519static irqreturn_t fsi_interrupt(int irq, void *data)
536{ 520{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; 521 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
@@ -545,6 +529,10 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
545 fsi_data_push(&master->fsia); 529 fsi_data_push(&master->fsia);
546 if (int_st & INT_B_OUT) 530 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib); 531 fsi_data_push(&master->fsib);
532 if (int_st & INT_A_IN)
533 fsi_data_pop(&master->fsia);
534 if (int_st & INT_B_IN)
535 fsi_data_pop(&master->fsib);
548 536
549 fsi_master_write(INT_ST, 0x0000000); 537 fsi_master_write(INT_ST, 0x0000000);
550 538
@@ -664,8 +652,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
664 } 652 }
665 653
666 fsi_reg_write(fsi, reg, data); 654 fsi_reg_write(fsi, reg, data);
667 dev_dbg(dai->dev, "use %s format (%d channel) use %d DMAC\n",
668 msg, fsi->chan, fsi->dma_chan);
669 655
670 /* 656 /*
671 * clear clk reset if master mode 657 * clear clk reset if master mode
@@ -699,16 +685,12 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 685 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0; 686 int ret = 0;
701 687
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) { 688 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START: 689 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream, 690 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size), 691 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size)); 692 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi); 693 ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
712 break; 694 break;
713 case SNDRV_PCM_TRIGGER_STOP: 695 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play); 696 fsi_irq_disable(fsi, is_play);
@@ -780,10 +762,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{ 762{
781 struct snd_pcm_runtime *runtime = substream->runtime; 763 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream); 764 struct fsi_priv *fsi = fsi_get(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location; 765 long location;
785 766
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); 767 location = (fsi->byte_offset - 1);
787 if (location < 0) 768 if (location < 0)
788 location = 0; 769 location = 0;
789 770
@@ -845,7 +826,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
845 .channels_min = 1, 826 .channels_min = 1,
846 .channels_max = 8, 827 .channels_max = 8,
847 }, 828 },
848 /* capture not supported */ 829 .capture = {
830 .rates = FSI_RATES,
831 .formats = FSI_FMTS,
832 .channels_min = 1,
833 .channels_max = 8,
834 },
849 .ops = &fsi_dai_ops, 835 .ops = &fsi_dai_ops,
850 }, 836 },
851 { 837 {
@@ -857,7 +843,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
857 .channels_min = 1, 843 .channels_min = 1,
858 .channels_max = 8, 844 .channels_max = 8,
859 }, 845 },
860 /* capture not supported */ 846 .capture = {
847 .rates = FSI_RATES,
848 .formats = FSI_FMTS,
849 .channels_min = 1,
850 .channels_max = 8,
851 },
861 .ops = &fsi_dai_ops, 852 .ops = &fsi_dai_ops,
862 }, 853 },
863}; 854};
@@ -912,22 +903,13 @@ static int fsi_probe(struct platform_device *pdev)
912 master->fsia.base = master->base; 903 master->fsia.base = master->base;
913 master->fsib.base = master->base + 0x40; 904 master->fsib.base = master->base + 0x40;
914 905
915 master->fsia.dma_chan = -1;
916 master->fsib.dma_chan = -1;
917
918 ret = fsi_get_dma_chan();
919 if (ret < 0) {
920 dev_err(&pdev->dev, "cannot get dma api\n");
921 goto exit_iounmap;
922 }
923
924 /* FSI is based on SPU mstp */ 906 /* FSI is based on SPU mstp */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id); 907 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name); 908 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) { 909 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name); 910 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO; 911 ret = -EIO;
930 goto exit_free_dma; 912 goto exit_iounmap;
931 } 913 }
932 914
933 fsi_soc_dai[0].dev = &pdev->dev; 915 fsi_soc_dai[0].dev = &pdev->dev;
@@ -938,7 +920,7 @@ static int fsi_probe(struct platform_device *pdev)
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 920 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) { 921 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n"); 922 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma; 923 goto exit_iounmap;
942 } 924 }
943 925
944 ret = snd_soc_register_platform(&fsi_soc_platform); 926 ret = snd_soc_register_platform(&fsi_soc_platform);
@@ -951,8 +933,6 @@ static int fsi_probe(struct platform_device *pdev)
951 933
952exit_free_irq: 934exit_free_irq:
953 free_irq(irq, master); 935 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap: 936exit_iounmap:
957 iounmap(master->base); 937 iounmap(master->base);
958exit_kfree: 938exit_kfree:
@@ -969,8 +949,6 @@ static int fsi_remove(struct platform_device *pdev)
969 949
970 clk_put(master->clk); 950 clk_put(master->clk);
971 951
972 fsi_free_dma_chan();
973
974 free_irq(master->irq, master); 952 free_irq(master->irq, master);
975 953
976 iounmap(master->base); 954 iounmap(master->base);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 2d190df9fccc..e2b6d75f16e3 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -37,7 +37,6 @@
37#include <sound/initval.h> 37#include <sound/initval.h>
38 38
39static DEFINE_MUTEX(pcm_mutex); 39static DEFINE_MUTEX(pcm_mutex);
40static DEFINE_MUTEX(io_mutex);
41static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); 40static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
42 41
43#ifdef CONFIG_DEBUG_FS 42#ifdef CONFIG_DEBUG_FS
@@ -81,6 +80,173 @@ static int run_delayed_work(struct delayed_work *dwork)
81 return ret; 80 return ret;
82} 81}
83 82
83/* codec register dump */
84static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
85{
86 int i, step = 1, count = 0;
87
88 if (!codec->reg_cache_size)
89 return 0;
90
91 if (codec->reg_cache_step)
92 step = codec->reg_cache_step;
93
94 count += sprintf(buf, "%s registers\n", codec->name);
95 for (i = 0; i < codec->reg_cache_size; i += step) {
96 if (codec->readable_register && !codec->readable_register(i))
97 continue;
98
99 count += sprintf(buf + count, "%2x: ", i);
100 if (count >= PAGE_SIZE - 1)
101 break;
102
103 if (codec->display_register)
104 count += codec->display_register(codec, buf + count,
105 PAGE_SIZE - count, i);
106 else
107 count += snprintf(buf + count, PAGE_SIZE - count,
108 "%4x", codec->read(codec, i));
109
110 if (count >= PAGE_SIZE - 1)
111 break;
112
113 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
114 if (count >= PAGE_SIZE - 1)
115 break;
116 }
117
118 /* Truncate count; min() would cause a warning */
119 if (count >= PAGE_SIZE)
120 count = PAGE_SIZE - 1;
121
122 return count;
123}
124static ssize_t codec_reg_show(struct device *dev,
125 struct device_attribute *attr, char *buf)
126{
127 struct snd_soc_device *devdata = dev_get_drvdata(dev);
128 return soc_codec_reg_show(devdata->card->codec, buf);
129}
130
131static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
132
133#ifdef CONFIG_DEBUG_FS
134static int codec_reg_open_file(struct inode *inode, struct file *file)
135{
136 file->private_data = inode->i_private;
137 return 0;
138}
139
140static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
141 size_t count, loff_t *ppos)
142{
143 ssize_t ret;
144 struct snd_soc_codec *codec = file->private_data;
145 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
146 if (!buf)
147 return -ENOMEM;
148 ret = soc_codec_reg_show(codec, buf);
149 if (ret >= 0)
150 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
151 kfree(buf);
152 return ret;
153}
154
155static ssize_t codec_reg_write_file(struct file *file,
156 const char __user *user_buf, size_t count, loff_t *ppos)
157{
158 char buf[32];
159 int buf_size;
160 char *start = buf;
161 unsigned long reg, value;
162 int step = 1;
163 struct snd_soc_codec *codec = file->private_data;
164
165 buf_size = min(count, (sizeof(buf)-1));
166 if (copy_from_user(buf, user_buf, buf_size))
167 return -EFAULT;
168 buf[buf_size] = 0;
169
170 if (codec->reg_cache_step)
171 step = codec->reg_cache_step;
172
173 while (*start == ' ')
174 start++;
175 reg = simple_strtoul(start, &start, 16);
176 if ((reg >= codec->reg_cache_size) || (reg % step))
177 return -EINVAL;
178 while (*start == ' ')
179 start++;
180 if (strict_strtoul(start, 16, &value))
181 return -EINVAL;
182 codec->write(codec, reg, value);
183 return buf_size;
184}
185
186static const struct file_operations codec_reg_fops = {
187 .open = codec_reg_open_file,
188 .read = codec_reg_read_file,
189 .write = codec_reg_write_file,
190};
191
192static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
193{
194 char codec_root[128];
195
196 if (codec->dev)
197 snprintf(codec_root, sizeof(codec_root),
198 "%s.%s", codec->name, dev_name(codec->dev));
199 else
200 snprintf(codec_root, sizeof(codec_root),
201 "%s", codec->name);
202
203 codec->debugfs_codec_root = debugfs_create_dir(codec_root,
204 debugfs_root);
205 if (!codec->debugfs_codec_root) {
206 printk(KERN_WARNING
207 "ASoC: Failed to create codec debugfs directory\n");
208 return;
209 }
210
211 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
212 codec->debugfs_codec_root,
213 codec, &codec_reg_fops);
214 if (!codec->debugfs_reg)
215 printk(KERN_WARNING
216 "ASoC: Failed to create codec register debugfs file\n");
217
218 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
219 codec->debugfs_codec_root,
220 &codec->pop_time);
221 if (!codec->debugfs_pop_time)
222 printk(KERN_WARNING
223 "Failed to create pop time debugfs file\n");
224
225 codec->debugfs_dapm = debugfs_create_dir("dapm",
226 codec->debugfs_codec_root);
227 if (!codec->debugfs_dapm)
228 printk(KERN_WARNING
229 "Failed to create DAPM debugfs directory\n");
230
231 snd_soc_dapm_debugfs_init(codec);
232}
233
234static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
235{
236 debugfs_remove_recursive(codec->debugfs_codec_root);
237}
238
239#else
240
241static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
242{
243}
244
245static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
246{
247}
248#endif
249
84#ifdef CONFIG_SND_SOC_AC97_BUS 250#ifdef CONFIG_SND_SOC_AC97_BUS
85/* unregister ac97 codec */ 251/* unregister ac97 codec */
86static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) 252static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
@@ -804,6 +970,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
804 struct platform_device, 970 struct platform_device,
805 dev); 971 dev);
806 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; 972 struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
973 struct snd_soc_codec *codec;
807 struct snd_soc_platform *platform; 974 struct snd_soc_platform *platform;
808 struct snd_soc_dai *dai; 975 struct snd_soc_dai *dai;
809 int i, found, ret, ac97; 976 int i, found, ret, ac97;
@@ -892,6 +1059,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
892 if (ret < 0) 1059 if (ret < 0)
893 goto cpu_dai_err; 1060 goto cpu_dai_err;
894 } 1061 }
1062 codec = card->codec;
895 1063
896 if (platform->probe) { 1064 if (platform->probe) {
897 ret = platform->probe(pdev); 1065 ret = platform->probe(pdev);
@@ -906,10 +1074,72 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
906 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); 1074 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
907#endif 1075#endif
908 1076
1077 for (i = 0; i < card->num_links; i++) {
1078 if (card->dai_link[i].init) {
1079 ret = card->dai_link[i].init(codec);
1080 if (ret < 0) {
1081 printk(KERN_ERR "asoc: failed to init %s\n",
1082 card->dai_link[i].stream_name);
1083 continue;
1084 }
1085 }
1086 if (card->dai_link[i].codec_dai->ac97_control) {
1087 ac97 = 1;
1088 snd_ac97_dev_add_pdata(codec->ac97,
1089 card->dai_link[i].cpu_dai->ac97_pdata);
1090 }
1091 }
1092
1093 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1094 "%s", card->name);
1095 snprintf(codec->card->longname, sizeof(codec->card->longname),
1096 "%s (%s)", card->name, codec->name);
1097
1098 /* Make sure all DAPM widgets are instantiated */
1099 snd_soc_dapm_new_widgets(codec);
1100
1101 ret = snd_card_register(codec->card);
1102 if (ret < 0) {
1103 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1104 codec->name);
1105 goto card_err;
1106 }
1107
1108 mutex_lock(&codec->mutex);
1109#ifdef CONFIG_SND_SOC_AC97_BUS
1110 /* Only instantiate AC97 if not already done by the adaptor
1111 * for the generic AC97 subsystem.
1112 */
1113 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1114 ret = soc_ac97_dev_register(codec);
1115 if (ret < 0) {
1116 printk(KERN_ERR "asoc: AC97 device register failed\n");
1117 snd_card_free(codec->card);
1118 mutex_unlock(&codec->mutex);
1119 goto card_err;
1120 }
1121 }
1122#endif
1123
1124 ret = snd_soc_dapm_sys_add(card->socdev->dev);
1125 if (ret < 0)
1126 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1127
1128 ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg);
1129 if (ret < 0)
1130 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1131
1132 soc_init_codec_debugfs(codec);
1133 mutex_unlock(&codec->mutex);
1134
909 card->instantiated = 1; 1135 card->instantiated = 1;
910 1136
911 return; 1137 return;
912 1138
1139card_err:
1140 if (platform->remove)
1141 platform->remove(pdev);
1142
913platform_err: 1143platform_err:
914 if (codec_dev->remove) 1144 if (codec_dev->remove)
915 codec_dev->remove(pdev); 1145 codec_dev->remove(pdev);
@@ -1112,173 +1342,6 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1112} 1342}
1113EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); 1343EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1114 1344
1115/* codec register dump */
1116static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1117{
1118 int i, step = 1, count = 0;
1119
1120 if (!codec->reg_cache_size)
1121 return 0;
1122
1123 if (codec->reg_cache_step)
1124 step = codec->reg_cache_step;
1125
1126 count += sprintf(buf, "%s registers\n", codec->name);
1127 for (i = 0; i < codec->reg_cache_size; i += step) {
1128 if (codec->readable_register && !codec->readable_register(i))
1129 continue;
1130
1131 count += sprintf(buf + count, "%2x: ", i);
1132 if (count >= PAGE_SIZE - 1)
1133 break;
1134
1135 if (codec->display_register)
1136 count += codec->display_register(codec, buf + count,
1137 PAGE_SIZE - count, i);
1138 else
1139 count += snprintf(buf + count, PAGE_SIZE - count,
1140 "%4x", codec->read(codec, i));
1141
1142 if (count >= PAGE_SIZE - 1)
1143 break;
1144
1145 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1146 if (count >= PAGE_SIZE - 1)
1147 break;
1148 }
1149
1150 /* Truncate count; min() would cause a warning */
1151 if (count >= PAGE_SIZE)
1152 count = PAGE_SIZE - 1;
1153
1154 return count;
1155}
1156static ssize_t codec_reg_show(struct device *dev,
1157 struct device_attribute *attr, char *buf)
1158{
1159 struct snd_soc_device *devdata = dev_get_drvdata(dev);
1160 return soc_codec_reg_show(devdata->card->codec, buf);
1161}
1162
1163static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
1164
1165#ifdef CONFIG_DEBUG_FS
1166static int codec_reg_open_file(struct inode *inode, struct file *file)
1167{
1168 file->private_data = inode->i_private;
1169 return 0;
1170}
1171
1172static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
1173 size_t count, loff_t *ppos)
1174{
1175 ssize_t ret;
1176 struct snd_soc_codec *codec = file->private_data;
1177 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1178 if (!buf)
1179 return -ENOMEM;
1180 ret = soc_codec_reg_show(codec, buf);
1181 if (ret >= 0)
1182 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1183 kfree(buf);
1184 return ret;
1185}
1186
1187static ssize_t codec_reg_write_file(struct file *file,
1188 const char __user *user_buf, size_t count, loff_t *ppos)
1189{
1190 char buf[32];
1191 int buf_size;
1192 char *start = buf;
1193 unsigned long reg, value;
1194 int step = 1;
1195 struct snd_soc_codec *codec = file->private_data;
1196
1197 buf_size = min(count, (sizeof(buf)-1));
1198 if (copy_from_user(buf, user_buf, buf_size))
1199 return -EFAULT;
1200 buf[buf_size] = 0;
1201
1202 if (codec->reg_cache_step)
1203 step = codec->reg_cache_step;
1204
1205 while (*start == ' ')
1206 start++;
1207 reg = simple_strtoul(start, &start, 16);
1208 if ((reg >= codec->reg_cache_size) || (reg % step))
1209 return -EINVAL;
1210 while (*start == ' ')
1211 start++;
1212 if (strict_strtoul(start, 16, &value))
1213 return -EINVAL;
1214 codec->write(codec, reg, value);
1215 return buf_size;
1216}
1217
1218static const struct file_operations codec_reg_fops = {
1219 .open = codec_reg_open_file,
1220 .read = codec_reg_read_file,
1221 .write = codec_reg_write_file,
1222};
1223
1224static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1225{
1226 char codec_root[128];
1227
1228 if (codec->dev)
1229 snprintf(codec_root, sizeof(codec_root),
1230 "%s.%s", codec->name, dev_name(codec->dev));
1231 else
1232 snprintf(codec_root, sizeof(codec_root),
1233 "%s", codec->name);
1234
1235 codec->debugfs_codec_root = debugfs_create_dir(codec_root,
1236 debugfs_root);
1237 if (!codec->debugfs_codec_root) {
1238 printk(KERN_WARNING
1239 "ASoC: Failed to create codec debugfs directory\n");
1240 return;
1241 }
1242
1243 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
1244 codec->debugfs_codec_root,
1245 codec, &codec_reg_fops);
1246 if (!codec->debugfs_reg)
1247 printk(KERN_WARNING
1248 "ASoC: Failed to create codec register debugfs file\n");
1249
1250 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
1251 codec->debugfs_codec_root,
1252 &codec->pop_time);
1253 if (!codec->debugfs_pop_time)
1254 printk(KERN_WARNING
1255 "Failed to create pop time debugfs file\n");
1256
1257 codec->debugfs_dapm = debugfs_create_dir("dapm",
1258 codec->debugfs_codec_root);
1259 if (!codec->debugfs_dapm)
1260 printk(KERN_WARNING
1261 "Failed to create DAPM debugfs directory\n");
1262
1263 snd_soc_dapm_debugfs_init(codec);
1264}
1265
1266static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1267{
1268 debugfs_remove_recursive(codec->debugfs_codec_root);
1269}
1270
1271#else
1272
1273static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1274{
1275}
1276
1277static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1278{
1279}
1280#endif
1281
1282/** 1345/**
1283 * snd_soc_new_ac97_codec - initailise AC97 device 1346 * snd_soc_new_ac97_codec - initailise AC97 device
1284 * @codec: audio codec 1347 * @codec: audio codec
@@ -1346,19 +1409,41 @@ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
1346 int change; 1409 int change;
1347 unsigned int old, new; 1410 unsigned int old, new;
1348 1411
1349 mutex_lock(&io_mutex);
1350 old = snd_soc_read(codec, reg); 1412 old = snd_soc_read(codec, reg);
1351 new = (old & ~mask) | value; 1413 new = (old & ~mask) | value;
1352 change = old != new; 1414 change = old != new;
1353 if (change) 1415 if (change)
1354 snd_soc_write(codec, reg, new); 1416 snd_soc_write(codec, reg, new);
1355 1417
1356 mutex_unlock(&io_mutex);
1357 return change; 1418 return change;
1358} 1419}
1359EXPORT_SYMBOL_GPL(snd_soc_update_bits); 1420EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1360 1421
1361/** 1422/**
1423 * snd_soc_update_bits_locked - update codec register bits
1424 * @codec: audio codec
1425 * @reg: codec register
1426 * @mask: register mask
1427 * @value: new value
1428 *
1429 * Writes new register value, and takes the codec mutex.
1430 *
1431 * Returns 1 for change else 0.
1432 */
1433static int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
1434 unsigned short reg, unsigned int mask,
1435 unsigned int value)
1436{
1437 int change;
1438
1439 mutex_lock(&codec->mutex);
1440 change = snd_soc_update_bits(codec, reg, mask, value);
1441 mutex_unlock(&codec->mutex);
1442
1443 return change;
1444}
1445
1446/**
1362 * snd_soc_test_bits - test register for change 1447 * snd_soc_test_bits - test register for change
1363 * @codec: audio codec 1448 * @codec: audio codec
1364 * @reg: codec register 1449 * @reg: codec register
@@ -1376,11 +1461,9 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1376 int change; 1461 int change;
1377 unsigned int old, new; 1462 unsigned int old, new;
1378 1463
1379 mutex_lock(&io_mutex);
1380 old = snd_soc_read(codec, reg); 1464 old = snd_soc_read(codec, reg);
1381 new = (old & ~mask) | value; 1465 new = (old & ~mask) | value;
1382 change = old != new; 1466 change = old != new;
1383 mutex_unlock(&io_mutex);
1384 1467
1385 return change; 1468 return change;
1386} 1469}
@@ -1435,83 +1518,6 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1435EXPORT_SYMBOL_GPL(snd_soc_new_pcms); 1518EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1436 1519
1437/** 1520/**
1438 * snd_soc_init_card - register sound card
1439 * @socdev: the SoC audio device
1440 *
1441 * Register a SoC sound card. Also registers an AC97 device if the
1442 * codec is AC97 for ad hoc devices.
1443 *
1444 * Returns 0 for success, else error.
1445 */
1446int snd_soc_init_card(struct snd_soc_device *socdev)
1447{
1448 struct snd_soc_card *card = socdev->card;
1449 struct snd_soc_codec *codec = card->codec;
1450 int ret = 0, i, ac97 = 0, err = 0;
1451
1452 for (i = 0; i < card->num_links; i++) {
1453 if (card->dai_link[i].init) {
1454 err = card->dai_link[i].init(codec);
1455 if (err < 0) {
1456 printk(KERN_ERR "asoc: failed to init %s\n",
1457 card->dai_link[i].stream_name);
1458 continue;
1459 }
1460 }
1461 if (card->dai_link[i].codec_dai->ac97_control) {
1462 ac97 = 1;
1463 snd_ac97_dev_add_pdata(codec->ac97,
1464 card->dai_link[i].cpu_dai->ac97_pdata);
1465 }
1466 }
1467 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1468 "%s", card->name);
1469 snprintf(codec->card->longname, sizeof(codec->card->longname),
1470 "%s (%s)", card->name, codec->name);
1471
1472 /* Make sure all DAPM widgets are instantiated */
1473 snd_soc_dapm_new_widgets(codec);
1474
1475 ret = snd_card_register(codec->card);
1476 if (ret < 0) {
1477 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1478 codec->name);
1479 goto out;
1480 }
1481
1482 mutex_lock(&codec->mutex);
1483#ifdef CONFIG_SND_SOC_AC97_BUS
1484 /* Only instantiate AC97 if not already done by the adaptor
1485 * for the generic AC97 subsystem.
1486 */
1487 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1488 ret = soc_ac97_dev_register(codec);
1489 if (ret < 0) {
1490 printk(KERN_ERR "asoc: AC97 device register failed\n");
1491 snd_card_free(codec->card);
1492 mutex_unlock(&codec->mutex);
1493 goto out;
1494 }
1495 }
1496#endif
1497
1498 err = snd_soc_dapm_sys_add(socdev->dev);
1499 if (err < 0)
1500 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1501
1502 err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1503 if (err < 0)
1504 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1505
1506 soc_init_codec_debugfs(codec);
1507 mutex_unlock(&codec->mutex);
1508
1509out:
1510 return ret;
1511}
1512EXPORT_SYMBOL_GPL(snd_soc_init_card);
1513
1514/**
1515 * snd_soc_free_pcms - free sound card and pcms 1521 * snd_soc_free_pcms - free sound card and pcms
1516 * @socdev: the SoC audio device 1522 * @socdev: the SoC audio device
1517 * 1523 *
@@ -1711,7 +1717,7 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1711 mask |= (bitmask - 1) << e->shift_r; 1717 mask |= (bitmask - 1) << e->shift_r;
1712 } 1718 }
1713 1719
1714 return snd_soc_update_bits(codec, e->reg, mask, val); 1720 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1715} 1721}
1716EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 1722EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1717 1723
@@ -1785,7 +1791,7 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
1785 mask |= e->mask << e->shift_r; 1791 mask |= e->mask << e->shift_r;
1786 } 1792 }
1787 1793
1788 return snd_soc_update_bits(codec, e->reg, mask, val); 1794 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1789} 1795}
1790EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); 1796EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
1791 1797
@@ -1946,7 +1952,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1946 val_mask |= mask << rshift; 1952 val_mask |= mask << rshift;
1947 val |= val2 << rshift; 1953 val |= val2 << rshift;
1948 } 1954 }
1949 return snd_soc_update_bits(codec, reg, val_mask, val); 1955 return snd_soc_update_bits_locked(codec, reg, val_mask, val);
1950} 1956}
1951EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 1957EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1952 1958
@@ -2052,11 +2058,11 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
2052 val = val << shift; 2058 val = val << shift;
2053 val2 = val2 << shift; 2059 val2 = val2 << shift;
2054 2060
2055 err = snd_soc_update_bits(codec, reg, val_mask, val); 2061 err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
2056 if (err < 0) 2062 if (err < 0)
2057 return err; 2063 return err;
2058 2064
2059 err = snd_soc_update_bits(codec, reg2, val_mask, val2); 2065 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
2060 return err; 2066 return err;
2061} 2067}
2062EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); 2068EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
@@ -2135,7 +2141,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2135 val = (ucontrol->value.integer.value[0]+min) & 0xff; 2141 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2136 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; 2142 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
2137 2143
2138 return snd_soc_update_bits(codec, reg, 0xffff, val); 2144 return snd_soc_update_bits_locked(codec, reg, 0xffff, val);
2139} 2145}
2140EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); 2146EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2141 2147