aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c2
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c2
-rw-r--r--sound/soc/au1x/dbdma2.c115
-rw-r--r--sound/soc/au1x/psc-ac97.c243
-rw-r--r--sound/soc/au1x/psc-i2s.c189
-rw-r--r--sound/soc/au1x/psc.h7
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c7
-rw-r--r--sound/soc/blackfin/bf5xx-ad1938.c9
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c15
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c9
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c45
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.h11
-rw-r--r--sound/soc/codecs/Kconfig25
-rw-r--r--sound/soc/codecs/Makefile12
-rw-r--r--sound/soc/codecs/ac97.c3
-rw-r--r--sound/soc/codecs/ad1836.c12
-rw-r--r--sound/soc/codecs/ad1938.c12
-rw-r--r--sound/soc/codecs/ad1980.c5
-rw-r--r--sound/soc/codecs/ad73311.c8
-rw-r--r--sound/soc/codecs/ads117x.c123
-rw-r--r--sound/soc/codecs/ads117x.h13
-rw-r--r--sound/soc/codecs/ak4104.c8
-rw-r--r--sound/soc/codecs/ak4535.c9
-rw-r--r--sound/soc/codecs/ak4642.c9
-rw-r--r--sound/soc/codecs/ak4671.c815
-rw-r--r--sound/soc/codecs/ak4671.h156
-rw-r--r--sound/soc/codecs/cs4270.c28
-rw-r--r--sound/soc/codecs/cx20442.c12
-rw-r--r--sound/soc/codecs/pcm3008.c9
-rw-r--r--sound/soc/codecs/ssm2602.c9
-rw-r--r--sound/soc/codecs/stac9766.c3
-rw-r--r--sound/soc/codecs/tlv320aic23.c14
-rw-r--r--sound/soc/codecs/tlv320aic26.c11
-rw-r--r--sound/soc/codecs/tlv320aic3x.c11
-rw-r--r--sound/soc/codecs/tlv320dac33.c1229
-rw-r--r--sound/soc/codecs/tlv320dac33.h267
-rw-r--r--sound/soc/codecs/tpa6130a2.c463
-rw-r--r--sound/soc/codecs/tpa6130a2.h61
-rw-r--r--sound/soc/codecs/twl4030.c452
-rw-r--r--sound/soc/codecs/twl4030.h242
-rw-r--r--sound/soc/codecs/uda134x.c9
-rw-r--r--sound/soc/codecs/uda1380.c9
-rw-r--r--sound/soc/codecs/wm8350.c32
-rw-r--r--sound/soc/codecs/wm8400.c32
-rw-r--r--sound/soc/codecs/wm8510.c14
-rw-r--r--sound/soc/codecs/wm8523.c26
-rw-r--r--sound/soc/codecs/wm8580.c30
-rw-r--r--sound/soc/codecs/wm8711.c633
-rw-r--r--sound/soc/codecs/wm8711.h42
-rw-r--r--sound/soc/codecs/wm8727.c135
-rw-r--r--sound/soc/codecs/wm8727.h21
-rw-r--r--sound/soc/codecs/wm8728.c10
-rw-r--r--sound/soc/codecs/wm8731.c94
-rw-r--r--sound/soc/codecs/wm8750.c9
-rw-r--r--sound/soc/codecs/wm8753.c49
-rw-r--r--sound/soc/codecs/wm8776.c43
-rw-r--r--sound/soc/codecs/wm8900.c34
-rw-r--r--sound/soc/codecs/wm8903.c28
-rw-r--r--sound/soc/codecs/wm8940.c28
-rw-r--r--sound/soc/codecs/wm8960.c30
-rw-r--r--sound/soc/codecs/wm8961.c27
-rw-r--r--sound/soc/codecs/wm8971.c11
-rw-r--r--sound/soc/codecs/wm8974.c36
-rw-r--r--sound/soc/codecs/wm8988.c44
-rw-r--r--sound/soc/codecs/wm8990.c14
-rw-r--r--sound/soc/codecs/wm8993.c49
-rw-r--r--sound/soc/codecs/wm9081.c27
-rw-r--r--sound/soc/codecs/wm9705.c7
-rw-r--r--sound/soc/codecs/wm9712.c7
-rw-r--r--sound/soc/codecs/wm9713.c10
-rw-r--r--sound/soc/codecs/wm_hubs.c51
-rw-r--r--sound/soc/codecs/wm_hubs.h5
-rw-r--r--sound/soc/davinci/Kconfig4
-rw-r--r--sound/soc/davinci/davinci-evm.c7
-rw-r--r--sound/soc/davinci/davinci-i2s.c85
-rw-r--r--sound/soc/davinci/davinci-mcasp.c18
-rw-r--r--sound/soc/davinci/davinci-mcasp.h5
-rw-r--r--sound/soc/davinci/davinci-pcm.c571
-rw-r--r--sound/soc/davinci/davinci-pcm.h2
-rw-r--r--sound/soc/fsl/mpc5200_dma.c123
-rw-r--r--sound/soc/fsl/mpc5200_dma.h24
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c39
-rw-r--r--sound/soc/imx/mx1_mx2-pcm.c6
-rw-r--r--sound/soc/imx/mx27vis_wm8974.c2
-rw-r--r--sound/soc/omap/Kconfig36
-rw-r--r--sound/soc/omap/Makefile8
-rw-r--r--sound/soc/omap/am3517evm.c202
-rw-r--r--sound/soc/omap/ams-delta.c4
-rw-r--r--sound/soc/omap/igep0020.c148
-rw-r--r--sound/soc/omap/omap-mcbsp.c63
-rw-r--r--sound/soc/omap/omap-pcm.c8
-rw-r--r--sound/soc/omap/omap3evm.c9
-rw-r--r--sound/soc/omap/omap3pandora.c27
-rw-r--r--sound/soc/omap/overo.c4
-rw-r--r--sound/soc/pxa/Kconfig12
-rw-r--r--sound/soc/pxa/Makefile2
-rw-r--r--sound/soc/pxa/magician.c2
-rw-r--r--sound/soc/pxa/pxa-ssp.c20
-rw-r--r--sound/soc/pxa/raumfeld.c335
-rw-r--r--sound/soc/pxa/zylonite.c5
-rw-r--r--sound/soc/s3c24xx/Kconfig12
-rw-r--r--sound/soc/s3c24xx/Makefile6
-rw-r--r--sound/soc/s3c24xx/jive_wm8750.c2
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c2
-rw-r--r--sound/soc/s3c24xx/neo1973_gta02_wm8753.c10
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c11
-rw-r--r--sound/soc/s3c24xx/s3c-dma.c (renamed from sound/soc/s3c24xx/s3c24xx-pcm.c)99
-rw-r--r--sound/soc/s3c24xx/s3c-dma.h (renamed from sound/soc/s3c24xx/s3c24xx-pcm.h)8
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.c35
-rw-r--r--sound/soc/s3c24xx/s3c-i2s-v2.h4
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.c552
-rw-r--r--sound/soc/s3c24xx/s3c-pcm.h123
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c7
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c13
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c14
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_hermes.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c2
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c2
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.c28
-rw-r--r--sound/soc/s3c24xx/s3c64xx-i2s.h1
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c2
-rw-r--r--sound/soc/s3c24xx/smdk64xx_wm8580.c268
-rw-r--r--sound/soc/s6000/s6000-pcm.c4
-rw-r--r--sound/soc/sh/Kconfig1
-rw-r--r--sound/soc/sh/fsi.c271
-rw-r--r--sound/soc/soc-cache.c46
-rw-r--r--sound/soc/soc-core.c577
-rw-r--r--sound/soc/soc-dapm.c157
-rw-r--r--sound/soc/soc-jack.c6
-rw-r--r--sound/soc/soc-utils.c74
132 files changed, 8065 insertions, 2320 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 0c5eac01bf2e..1470141d4167 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ 4obj-$(CONFIG_SND_SOC) += codecs/
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
index 9eb610c2ba91..9df4c68ef000 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/atmel/playpaq_wm8510.c
@@ -268,7 +268,7 @@ static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */ 268#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
269 269
270 270
271 ret = snd_soc_dai_set_pll(codec_dai, 0, 271 ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
272 clk_get_rate(CODEC_CLK), pll_out); 272 clk_get_rate(CODEC_CLK), pll_out);
273 if (ret < 0) { 273 if (ret < 0) {
274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n", 274 pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index 885ba012557e..e028744c32ce 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -207,7 +207,7 @@ static int __init at91sam9g20ek_init(void)
207 struct clk *pllb; 207 struct clk *pllb;
208 int ret; 208 int ret;
209 209
210 if (!machine_is_at91sam9g20ek()) 210 if (!(machine_is_at91sam9g20ek() || machine_is_at91sam9g20ek_2mmc()))
211 return -ENODEV; 211 return -ENODEV;
212 212
213 /* 213 /*
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 594c6c5b7838..19e4d37eba1c 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,81 @@ 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);
415} 441}
416 442
417module_init(au1xpsc_audio_dbdma_init); 443module_init(au1xpsc_audio_dbdma_load);
418module_exit(au1xpsc_audio_dbdma_exit); 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
483 platform_device_put(pd);
484out:
485 kfree(res);
486 return NULL;
487}
488EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
489
490void au1xpsc_pcm_destroy(struct platform_device *dmapd)
491{
492 if (dmapd)
493 platform_device_unregister(dmapd);
494}
495EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
419 496
420MODULE_LICENSE("GPL"); 497MODULE_LICENSE("GPL");
421MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver"); 498MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
422MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>"); 499MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index a521aa90ddee..340311d7fed5 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -61,7 +61,8 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
61{ 61{
62 /* FIXME */ 62 /* FIXME */
63 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 63 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
64 unsigned short data, retry, tmo; 64 unsigned short retry, tmo;
65 unsigned long data;
65 66
66 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 67 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
67 au_sync(); 68 au_sync();
@@ -74,20 +75,26 @@ static unsigned short au1xpsc_ac97_read(struct snd_ac97 *ac97,
74 AC97_CDC(pscdata)); 75 AC97_CDC(pscdata));
75 au_sync(); 76 au_sync();
76 77
77 tmo = 2000; 78 tmo = 20;
78 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) 79 do {
79 && --tmo) 80 udelay(21);
80 udelay(2); 81 if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
82 break;
83 } while (--tmo);
81 84
82 data = au_readl(AC97_CDC(pscdata)) & 0xffff; 85 data = au_readl(AC97_CDC(pscdata));
83 86
84 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 87 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
85 au_sync(); 88 au_sync();
86 89
87 mutex_unlock(&pscdata->lock); 90 mutex_unlock(&pscdata->lock);
91
92 if (reg != ((data >> 16) & 0x7f))
93 tmo = 1; /* wrong register, try again */
94
88 } while (--retry && !tmo); 95 } while (--retry && !tmo);
89 96
90 return retry ? data : 0xffff; 97 return retry ? data & 0xffff : 0xffff;
91} 98}
92 99
93/* AC97 controller writes to codec register */ 100/* AC97 controller writes to codec register */
@@ -109,10 +116,12 @@ static void au1xpsc_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
109 AC97_CDC(pscdata)); 116 AC97_CDC(pscdata));
110 au_sync(); 117 au_sync();
111 118
112 tmo = 2000; 119 tmo = 20;
113 while ((!(au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)) 120 do {
114 && --tmo) 121 udelay(21);
115 udelay(2); 122 if (au_readl(AC97_EVNT(pscdata)) & PSC_AC97EVNT_CD)
123 break;
124 } while (--tmo);
116 125
117 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata)); 126 au_writel(PSC_AC97EVNT_CD, AC97_EVNT(pscdata));
118 au_sync(); 127 au_sync();
@@ -195,7 +204,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
195 /* FIXME */ 204 /* FIXME */
196 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata; 205 struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
197 unsigned long r, ro, stat; 206 unsigned long r, ro, stat;
198 int chans, stype = SUBSTREAM_TYPE(substream); 207 int chans, t, stype = SUBSTREAM_TYPE(substream);
199 208
200 chans = params_channels(params); 209 chans = params_channels(params);
201 210
@@ -237,8 +246,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
237 au_sync(); 246 au_sync();
238 247
239 /* ...wait for it... */ 248 /* ...wait for it... */
240 while (au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) 249 t = 100;
241 asm volatile ("nop"); 250 while ((au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR) && --t)
251 msleep(1);
252
253 if (!t)
254 printk(KERN_ERR "PSC-AC97: can't disable!\n");
242 255
243 /* ...write config... */ 256 /* ...write config... */
244 au_writel(r, AC97_CFG(pscdata)); 257 au_writel(r, AC97_CFG(pscdata));
@@ -249,8 +262,12 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
249 au_sync(); 262 au_sync();
250 263
251 /* ...and wait for ready bit */ 264 /* ...and wait for ready bit */
252 while (!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) 265 t = 100;
253 asm volatile ("nop"); 266 while ((!(au_readl(AC97_STAT(pscdata)) & PSC_AC97STAT_DR)) && --t)
267 msleep(1);
268
269 if (!t)
270 printk(KERN_ERR "PSC-AC97: can't enable!\n");
254 271
255 mutex_unlock(&pscdata->lock); 272 mutex_unlock(&pscdata->lock);
256 273
@@ -300,19 +317,55 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
300static int au1xpsc_ac97_probe(struct platform_device *pdev, 317static int au1xpsc_ac97_probe(struct platform_device *pdev,
301 struct snd_soc_dai *dai) 318 struct snd_soc_dai *dai)
302{ 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{
303 int ret; 356 int ret;
304 struct resource *r; 357 struct resource *r;
305 unsigned long sel; 358 unsigned long sel;
359 struct au1xpsc_audio_data *wd;
306 360
307 if (au1xpsc_ac97_workdata) 361 if (au1xpsc_ac97_workdata)
308 return -EBUSY; 362 return -EBUSY;
309 363
310 au1xpsc_ac97_workdata = 364 wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
311 kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL); 365 if (!wd)
312 if (!au1xpsc_ac97_workdata)
313 return -ENOMEM; 366 return -ENOMEM;
314 367
315 mutex_init(&au1xpsc_ac97_workdata->lock); 368 mutex_init(&wd->lock);
316 369
317 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 370 r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
318 if (!r) { 371 if (!r) {
@@ -321,81 +374,95 @@ static int au1xpsc_ac97_probe(struct platform_device *pdev,
321 } 374 }
322 375
323 ret = -EBUSY; 376 ret = -EBUSY;
324 au1xpsc_ac97_workdata->ioarea = 377 wd->ioarea = request_mem_region(r->start, r->end - r->start + 1,
325 request_mem_region(r->start, r->end - r->start + 1,
326 "au1xpsc_ac97"); 378 "au1xpsc_ac97");
327 if (!au1xpsc_ac97_workdata->ioarea) 379 if (!wd->ioarea)
328 goto out0; 380 goto out0;
329 381
330 au1xpsc_ac97_workdata->mmio = ioremap(r->start, 0xffff); 382 wd->mmio = ioremap(r->start, 0xffff);
331 if (!au1xpsc_ac97_workdata->mmio) 383 if (!wd->mmio)
332 goto out1; 384 goto out1;
333 385
334 /* configuration: max dma trigger threshold, enable ac97 */ 386 /* configuration: max dma trigger threshold, enable ac97 */
335 au1xpsc_ac97_workdata->cfg = PSC_AC97CFG_RT_FIFO8 | 387 wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
336 PSC_AC97CFG_TT_FIFO8 | 388 PSC_AC97CFG_DE_ENABLE;
337 PSC_AC97CFG_DE_ENABLE;
338 389
339 /* preserve PSC clock source set up by platform (dev.platform_data 390 /* preserve PSC clock source set up by platform */
340 * is already occupied by soc layer) 391 sel = au_readl(PSC_SEL(wd)) & PSC_SEL_CLK_MASK;
341 */ 392 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
342 sel = au_readl(PSC_SEL(au1xpsc_ac97_workdata)) & PSC_SEL_CLK_MASK;
343 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata));
344 au_sync(); 393 au_sync();
345 au_writel(0, PSC_SEL(au1xpsc_ac97_workdata)); 394 au_writel(0, PSC_SEL(wd));
346 au_sync(); 395 au_sync();
347 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(au1xpsc_ac97_workdata)); 396 au_writel(PSC_SEL_PS_AC97MODE | sel, PSC_SEL(wd));
348 au_sync(); 397 au_sync();
349 /* next up: cold reset. Dont check for PSC-ready now since
350 * there may not be any codec clock yet.
351 */
352 398
353 return 0; 399 ret = snd_soc_register_dai(&au1xpsc_ac97_dai);
400 if (ret)
401 goto out1;
354 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 }
409
410 snd_soc_unregister_dai(&au1xpsc_ac97_dai);
355out1: 411out1:
356 release_resource(au1xpsc_ac97_workdata->ioarea); 412 release_resource(wd->ioarea);
357 kfree(au1xpsc_ac97_workdata->ioarea); 413 kfree(wd->ioarea);
358out0: 414out0:
359 kfree(au1xpsc_ac97_workdata); 415 kfree(wd);
360 au1xpsc_ac97_workdata = NULL;
361 return ret; 416 return ret;
362} 417}
363 418
364static void au1xpsc_ac97_remove(struct platform_device *pdev, 419static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
365 struct snd_soc_dai *dai)
366{ 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
367 /* disable PSC completely */ 428 /* disable PSC completely */
368 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 429 au_writel(0, AC97_CFG(wd));
369 au_sync(); 430 au_sync();
370 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 431 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
371 au_sync(); 432 au_sync();
372 433
373 iounmap(au1xpsc_ac97_workdata->mmio); 434 iounmap(wd->mmio);
374 release_resource(au1xpsc_ac97_workdata->ioarea); 435 release_resource(wd->ioarea);
375 kfree(au1xpsc_ac97_workdata->ioarea); 436 kfree(wd->ioarea);
376 kfree(au1xpsc_ac97_workdata); 437 kfree(wd);
377 au1xpsc_ac97_workdata = NULL; 438
439 au1xpsc_ac97_workdata = NULL; /* MDEV */
440
441 return 0;
378} 442}
379 443
380static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai) 444#ifdef CONFIG_PM
445static int au1xpsc_ac97_drvsuspend(struct device *dev)
381{ 446{
447 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
448
382 /* save interesting registers and disable PSC */ 449 /* save interesting registers and disable PSC */
383 au1xpsc_ac97_workdata->pm[0] = 450 wd->pm[0] = au_readl(PSC_SEL(wd));
384 au_readl(PSC_SEL(au1xpsc_ac97_workdata));
385 451
386 au_writel(0, AC97_CFG(au1xpsc_ac97_workdata)); 452 au_writel(0, AC97_CFG(wd));
387 au_sync(); 453 au_sync();
388 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_ac97_workdata)); 454 au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
389 au_sync(); 455 au_sync();
390 456
391 return 0; 457 return 0;
392} 458}
393 459
394static int au1xpsc_ac97_resume(struct snd_soc_dai *dai) 460static int au1xpsc_ac97_drvresume(struct device *dev)
395{ 461{
462 struct au1xpsc_audio_data *wd = dev_get_drvdata(dev);
463
396 /* restore PSC clock config */ 464 /* restore PSC clock config */
397 au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE, 465 au_writel(wd->pm[0] | PSC_SEL_PS_AC97MODE, PSC_SEL(wd));
398 PSC_SEL(au1xpsc_ac97_workdata));
399 au_sync(); 466 au_sync();
400 467
401 /* after this point the ac97 core will cold-reset the codec. 468 /* after this point the ac97 core will cold-reset the codec.
@@ -405,48 +472,44 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
405 return 0; 472 return 0;
406} 473}
407 474
408static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { 475static struct dev_pm_ops au1xpscac97_pmops = {
409 .trigger = au1xpsc_ac97_trigger, 476 .suspend = au1xpsc_ac97_drvsuspend,
410 .hw_params = au1xpsc_ac97_hw_params, 477 .resume = au1xpsc_ac97_drvresume,
411}; 478};
412 479
413struct snd_soc_dai au1xpsc_ac97_dai = { 480#define AU1XPSCAC97_PMOPS &au1xpscac97_pmops
414 .name = "au1xpsc_ac97", 481
415 .ac97_control = 1, 482#else
416 .probe = au1xpsc_ac97_probe, 483
417 .remove = au1xpsc_ac97_remove, 484#define AU1XPSCAC97_PMOPS NULL
418 .suspend = au1xpsc_ac97_suspend, 485
419 .resume = au1xpsc_ac97_resume, 486#endif
420 .playback = { 487
421 .rates = AC97_RATES, 488static struct platform_driver au1xpsc_ac97_driver = {
422 .formats = AC97_FMTS, 489 .driver = {
423 .channels_min = 2, 490 .name = "au1xpsc_ac97",
424 .channels_max = 2, 491 .owner = THIS_MODULE,
425 }, 492 .pm = AU1XPSCAC97_PMOPS,
426 .capture = {
427 .rates = AC97_RATES,
428 .formats = AC97_FMTS,
429 .channels_min = 2,
430 .channels_max = 2,
431 }, 493 },
432 .ops = &au1xpsc_ac97_dai_ops, 494 .probe = au1xpsc_ac97_drvprobe,
495 .remove = __devexit_p(au1xpsc_ac97_drvremove),
433}; 496};
434EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
435 497
436static int __init au1xpsc_ac97_init(void) 498static int __init au1xpsc_ac97_load(void)
437{ 499{
438 au1xpsc_ac97_workdata = NULL; 500 au1xpsc_ac97_workdata = NULL;
439 return snd_soc_register_dai(&au1xpsc_ac97_dai); 501 return platform_driver_register(&au1xpsc_ac97_driver);
440} 502}
441 503
442static void __exit au1xpsc_ac97_exit(void) 504static void __exit au1xpsc_ac97_unload(void)
443{ 505{
444 snd_soc_unregister_dai(&au1xpsc_ac97_dai); 506 platform_driver_unregister(&au1xpsc_ac97_driver);
445} 507}
446 508
447module_init(au1xpsc_ac97_init); 509module_init(au1xpsc_ac97_load);
448module_exit(au1xpsc_ac97_exit); 510module_exit(au1xpsc_ac97_unload);
449 511
450MODULE_LICENSE("GPL"); 512MODULE_LICENSE("GPL");
451MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); 513MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver");
452MODULE_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/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index cd361e304b0f..0f45a3f56be8 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -52,6 +52,7 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
52 struct snd_soc_pcm_runtime *rtd = substream->private_data; 52 struct snd_soc_pcm_runtime *rtd = substream->private_data;
53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 53 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
55 unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
55 int ret = 0; 56 int ret = 0;
56 /* set cpu DAI configuration */ 57 /* set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 58 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
@@ -65,6 +66,12 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
65 if (ret < 0) 66 if (ret < 0)
66 return ret; 67 return ret;
67 68
69 /* set cpu DAI channel mapping */
70 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
71 channel_map, ARRAY_SIZE(channel_map), channel_map);
72 if (ret < 0)
73 return ret;
74
68 return 0; 75 return 0;
69} 76}
70 77
diff --git a/sound/soc/blackfin/bf5xx-ad1938.c b/sound/soc/blackfin/bf5xx-ad1938.c
index 08269e91810c..2ef1e5013b8c 100644
--- a/sound/soc/blackfin/bf5xx-ad1938.c
+++ b/sound/soc/blackfin/bf5xx-ad1938.c
@@ -61,6 +61,7 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
61 struct snd_soc_pcm_runtime *rtd = substream->private_data; 61 struct snd_soc_pcm_runtime *rtd = substream->private_data;
62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 62 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 63 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
64 unsigned int channel_map[] = {0, 1, 2, 3, 4, 5, 6, 7};
64 int ret = 0; 65 int ret = 0;
65 /* set cpu DAI configuration */ 66 /* set cpu DAI configuration */
66 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A | 67 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
@@ -75,7 +76,13 @@ static int bf5xx_ad1938_hw_params(struct snd_pcm_substream *substream,
75 return ret; 76 return ret;
76 77
77 /* set codec DAI slots, 8 channels, all channels are enabled */ 78 /* set codec DAI slots, 8 channels, all channels are enabled */
78 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 8); 79 ret = snd_soc_dai_set_tdm_slot(codec_dai, 0xFF, 0xFF, 8, 32);
80 if (ret < 0)
81 return ret;
82
83 /* set cpu DAI channel mapping */
84 ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
85 channel_map, ARRAY_SIZE(channel_map), channel_map);
79 if (ret < 0) 86 if (ret < 0)
80 return ret; 87 return ret;
81 88
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 084b68884ada..3e6ada0dd1c4 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -49,7 +49,6 @@ struct bf5xx_i2s_port {
49 u16 rcr1; 49 u16 rcr1;
50 u16 tcr2; 50 u16 tcr2;
51 u16 rcr2; 51 u16 rcr2;
52 int counter;
53 int configured; 52 int configured;
54}; 53};
55 54
@@ -133,16 +132,6 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
133 return ret; 132 return ret;
134} 133}
135 134
136static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
137 struct snd_soc_dai *dai)
138{
139 pr_debug("%s enter\n", __func__);
140
141 /*this counter is used for counting how many pcm streams are opened*/
142 bf5xx_i2s.counter++;
143 return 0;
144}
145
146static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream, 135static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
147 struct snd_pcm_hw_params *params, 136 struct snd_pcm_hw_params *params,
148 struct snd_soc_dai *dai) 137 struct snd_soc_dai *dai)
@@ -201,9 +190,8 @@ static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
201 struct snd_soc_dai *dai) 190 struct snd_soc_dai *dai)
202{ 191{
203 pr_debug("%s enter\n", __func__); 192 pr_debug("%s enter\n", __func__);
204 bf5xx_i2s.counter--;
205 /* No active stream, SPORT is allowed to be configured again. */ 193 /* No active stream, SPORT is allowed to be configured again. */
206 if (!bf5xx_i2s.counter) 194 if (!dai->active)
207 bf5xx_i2s.configured = 0; 195 bf5xx_i2s.configured = 0;
208} 196}
209 197
@@ -284,7 +272,6 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
284 SNDRV_PCM_FMTBIT_S32_LE) 272 SNDRV_PCM_FMTBIT_S32_LE)
285 273
286static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = { 274static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
287 .startup = bf5xx_i2s_startup,
288 .shutdown = bf5xx_i2s_shutdown, 275 .shutdown = bf5xx_i2s_shutdown,
289 .hw_params = bf5xx_i2s_hw_params, 276 .hw_params = bf5xx_i2s_hw_params,
290 .set_fmt = bf5xx_i2s_set_dai_fmt, 277 .set_fmt = bf5xx_i2s_set_dai_fmt,
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index ccb5e823bd18..a8c73cbbd685 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -43,7 +43,7 @@
43#include "bf5xx-tdm.h" 43#include "bf5xx-tdm.h"
44#include "bf5xx-sport.h" 44#include "bf5xx-sport.h"
45 45
46#define PCM_BUFFER_MAX 0x10000 46#define PCM_BUFFER_MAX 0x8000
47#define FRAGMENT_SIZE_MIN (4*1024) 47#define FRAGMENT_SIZE_MIN (4*1024)
48#define FRAGMENTS_MIN 2 48#define FRAGMENTS_MIN 2
49#define FRAGMENTS_MAX 32 49#define FRAGMENTS_MAX 32
@@ -177,6 +177,9 @@ out:
177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel, 177static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count) 178 snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
179{ 179{
180 struct snd_pcm_runtime *runtime = substream->runtime;
181 struct sport_device *sport = runtime->private_data;
182 struct bf5xx_tdm_port *tdm_port = sport->private_data;
180 unsigned int *src; 183 unsigned int *src;
181 unsigned int *dst; 184 unsigned int *dst;
182 int i; 185 int i;
@@ -188,7 +191,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
188 dst += pos * 8; 191 dst += pos * 8;
189 while (count--) { 192 while (count--) {
190 for (i = 0; i < substream->runtime->channels; i++) 193 for (i = 0; i < substream->runtime->channels; i++)
191 *(dst + i) = *src++; 194 *(dst + tdm_port->tx_map[i]) = *src++;
192 dst += 8; 195 dst += 8;
193 } 196 }
194 } else { 197 } else {
@@ -198,7 +201,7 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
198 src += pos * 8; 201 src += pos * 8;
199 while (count--) { 202 while (count--) {
200 for (i = 0; i < substream->runtime->channels; i++) 203 for (i = 0; i < substream->runtime->channels; i++)
201 *dst++ = *(src+i); 204 *dst++ = *(src + tdm_port->rx_map[i]);
202 src += 8; 205 src += 8;
203 } 206 }
204 } 207 }
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index ff546e91a22e..4b360124083e 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -46,14 +46,6 @@
46#include "bf5xx-sport.h" 46#include "bf5xx-sport.h"
47#include "bf5xx-tdm.h" 47#include "bf5xx-tdm.h"
48 48
49struct bf5xx_tdm_port {
50 u16 tcr1;
51 u16 rcr1;
52 u16 tcr2;
53 u16 rcr2;
54 int configured;
55};
56
57static struct bf5xx_tdm_port bf5xx_tdm; 49static struct bf5xx_tdm_port bf5xx_tdm;
58static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM; 50static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
59 51
@@ -181,6 +173,40 @@ static void bf5xx_tdm_shutdown(struct snd_pcm_substream *substream,
181 bf5xx_tdm.configured = 0; 173 bf5xx_tdm.configured = 0;
182} 174}
183 175
176static int bf5xx_tdm_set_channel_map(struct snd_soc_dai *dai,
177 unsigned int tx_num, unsigned int *tx_slot,
178 unsigned int rx_num, unsigned int *rx_slot)
179{
180 int i;
181 unsigned int slot;
182 unsigned int tx_mapped = 0, rx_mapped = 0;
183
184 if ((tx_num > BFIN_TDM_DAI_MAX_SLOTS) ||
185 (rx_num > BFIN_TDM_DAI_MAX_SLOTS))
186 return -EINVAL;
187
188 for (i = 0; i < tx_num; i++) {
189 slot = tx_slot[i];
190 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
191 (!(tx_mapped & (1 << slot)))) {
192 bf5xx_tdm.tx_map[i] = slot;
193 tx_mapped |= 1 << slot;
194 } else
195 return -EINVAL;
196 }
197 for (i = 0; i < rx_num; i++) {
198 slot = rx_slot[i];
199 if ((slot < BFIN_TDM_DAI_MAX_SLOTS) &&
200 (!(rx_mapped & (1 << slot)))) {
201 bf5xx_tdm.rx_map[i] = slot;
202 rx_mapped |= 1 << slot;
203 } else
204 return -EINVAL;
205 }
206
207 return 0;
208}
209
184#ifdef CONFIG_PM 210#ifdef CONFIG_PM
185static int bf5xx_tdm_suspend(struct snd_soc_dai *dai) 211static int bf5xx_tdm_suspend(struct snd_soc_dai *dai)
186{ 212{
@@ -235,6 +261,7 @@ static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
235 .hw_params = bf5xx_tdm_hw_params, 261 .hw_params = bf5xx_tdm_hw_params,
236 .set_fmt = bf5xx_tdm_set_dai_fmt, 262 .set_fmt = bf5xx_tdm_set_dai_fmt,
237 .shutdown = bf5xx_tdm_shutdown, 263 .shutdown = bf5xx_tdm_shutdown,
264 .set_channel_map = bf5xx_tdm_set_channel_map,
238}; 265};
239 266
240struct snd_soc_dai bf5xx_tdm_dai = { 267struct snd_soc_dai bf5xx_tdm_dai = {
@@ -300,6 +327,8 @@ static int __devinit bfin_tdm_probe(struct platform_device *pdev)
300 pr_err("Failed to register DAI: %d\n", ret); 327 pr_err("Failed to register DAI: %d\n", ret);
301 goto sport_config_err; 328 goto sport_config_err;
302 } 329 }
330
331 sport_handle->private_data = &bf5xx_tdm;
303 return 0; 332 return 0;
304 333
305sport_config_err: 334sport_config_err:
diff --git a/sound/soc/blackfin/bf5xx-tdm.h b/sound/soc/blackfin/bf5xx-tdm.h
index 618ec3d90cd4..04189a18c1ba 100644
--- a/sound/soc/blackfin/bf5xx-tdm.h
+++ b/sound/soc/blackfin/bf5xx-tdm.h
@@ -9,6 +9,17 @@
9#ifndef _BF5XX_TDM_H 9#ifndef _BF5XX_TDM_H
10#define _BF5XX_TDM_H 10#define _BF5XX_TDM_H
11 11
12#define BFIN_TDM_DAI_MAX_SLOTS 8
13struct bf5xx_tdm_port {
14 u16 tcr1;
15 u16 rcr1;
16 u16 tcr2;
17 u16 rcr2;
18 unsigned int tx_map[BFIN_TDM_DAI_MAX_SLOTS];
19 unsigned int rx_map[BFIN_TDM_DAI_MAX_SLOTS];
20 int configured;
21};
22
12extern struct snd_soc_dai bf5xx_tdm_dai; 23extern struct snd_soc_dai bf5xx_tdm_dai;
13 24
14#endif 25#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 0edca93af3b0..52b005f8fed4 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -15,10 +15,12 @@ config SND_SOC_ALL_CODECS
15 select SND_SOC_AD1836 if SPI_MASTER 15 select SND_SOC_AD1836 if SPI_MASTER
16 select SND_SOC_AD1938 if SPI_MASTER 16 select SND_SOC_AD1938 if SPI_MASTER
17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS 17 select SND_SOC_AD1980 if SND_SOC_AC97_BUS
18 select SND_SOC_ADS117X
18 select SND_SOC_AD73311 if I2C 19 select SND_SOC_AD73311 if I2C
19 select SND_SOC_AK4104 if SPI_MASTER 20 select SND_SOC_AK4104 if SPI_MASTER
20 select SND_SOC_AK4535 if I2C 21 select SND_SOC_AK4535 if I2C
21 select SND_SOC_AK4642 if I2C 22 select SND_SOC_AK4642 if I2C
23 select SND_SOC_AK4671 if I2C
22 select SND_SOC_CS4270 if I2C 24 select SND_SOC_CS4270 if I2C
23 select SND_SOC_MAX9877 if I2C 25 select SND_SOC_MAX9877 if I2C
24 select SND_SOC_PCM3008 26 select SND_SOC_PCM3008
@@ -28,6 +30,8 @@ config SND_SOC_ALL_CODECS
28 select SND_SOC_TLV320AIC23 if I2C 30 select SND_SOC_TLV320AIC23 if I2C
29 select SND_SOC_TLV320AIC26 if SPI_MASTER 31 select SND_SOC_TLV320AIC26 if SPI_MASTER
30 select SND_SOC_TLV320AIC3X if I2C 32 select SND_SOC_TLV320AIC3X if I2C
33 select SND_SOC_TPA6130A2 if I2C
34 select SND_SOC_TLV320DAC33 if I2C
31 select SND_SOC_TWL4030 if TWL4030_CORE 35 select SND_SOC_TWL4030 if TWL4030_CORE
32 select SND_SOC_UDA134X 36 select SND_SOC_UDA134X
33 select SND_SOC_UDA1380 if I2C 37 select SND_SOC_UDA1380 if I2C
@@ -36,6 +40,8 @@ config SND_SOC_ALL_CODECS
36 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI 40 select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
37 select SND_SOC_WM8523 if I2C 41 select SND_SOC_WM8523 if I2C
38 select SND_SOC_WM8580 if I2C 42 select SND_SOC_WM8580 if I2C
43 select SND_SOC_WM8711 if SND_SOC_I2C_AND_SPI
44 select SND_SOC_WM8727
39 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI 45 select SND_SOC_WM8728 if SND_SOC_I2C_AND_SPI
40 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI 46 select SND_SOC_WM8731 if SND_SOC_I2C_AND_SPI
41 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI 47 select SND_SOC_WM8750 if SND_SOC_I2C_AND_SPI
@@ -86,6 +92,9 @@ config SND_SOC_AD1980
86 92
87config SND_SOC_AD73311 93config SND_SOC_AD73311
88 tristate 94 tristate
95
96config SND_SOC_ADS117X
97 tristate
89 98
90config SND_SOC_AK4104 99config SND_SOC_AK4104
91 tristate 100 tristate
@@ -96,6 +105,9 @@ config SND_SOC_AK4535
96config SND_SOC_AK4642 105config SND_SOC_AK4642
97 tristate 106 tristate
98 107
108config SND_SOC_AK4671
109 tristate
110
99# Cirrus Logic CS4270 Codec 111# Cirrus Logic CS4270 Codec
100config SND_SOC_CS4270 112config SND_SOC_CS4270
101 tristate 113 tristate
@@ -136,7 +148,11 @@ config SND_SOC_TLV320AIC26
136config SND_SOC_TLV320AIC3X 148config SND_SOC_TLV320AIC3X
137 tristate 149 tristate
138 150
151config SND_SOC_TLV320DAC33
152 tristate
153
139config SND_SOC_TWL4030 154config SND_SOC_TWL4030
155 select TWL4030_CODEC
140 tristate 156 tristate
141 157
142config SND_SOC_UDA134X 158config SND_SOC_UDA134X
@@ -160,6 +176,12 @@ config SND_SOC_WM8523
160config SND_SOC_WM8580 176config SND_SOC_WM8580
161 tristate 177 tristate
162 178
179config SND_SOC_WM8711
180 tristate
181
182config SND_SOC_WM8727
183 tristate
184
163config SND_SOC_WM8728 185config SND_SOC_WM8728
164 tristate 186 tristate
165 187
@@ -220,3 +242,6 @@ config SND_SOC_WM9713
220# Amp 242# Amp
221config SND_SOC_MAX9877 243config SND_SOC_MAX9877
222 tristate 244 tristate
245
246config SND_SOC_TPA6130A2
247 tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index fb4af28486ba..dbaecb133ac7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,9 +3,11 @@ snd-soc-ad1836-objs := ad1836.o
3snd-soc-ad1938-objs := ad1938.o 3snd-soc-ad1938-objs := ad1938.o
4snd-soc-ad1980-objs := ad1980.o 4snd-soc-ad1980-objs := ad1980.o
5snd-soc-ad73311-objs := ad73311.o 5snd-soc-ad73311-objs := ad73311.o
6snd-soc-ads117x-objs := ads117x.o
6snd-soc-ak4104-objs := ak4104.o 7snd-soc-ak4104-objs := ak4104.o
7snd-soc-ak4535-objs := ak4535.o 8snd-soc-ak4535-objs := ak4535.o
8snd-soc-ak4642-objs := ak4642.o 9snd-soc-ak4642-objs := ak4642.o
10snd-soc-ak4671-objs := ak4671.o
9snd-soc-cs4270-objs := cs4270.o 11snd-soc-cs4270-objs := cs4270.o
10snd-soc-cx20442-objs := cx20442.o 12snd-soc-cx20442-objs := cx20442.o
11snd-soc-l3-objs := l3.o 13snd-soc-l3-objs := l3.o
@@ -16,6 +18,7 @@ snd-soc-stac9766-objs := stac9766.o
16snd-soc-tlv320aic23-objs := tlv320aic23.o 18snd-soc-tlv320aic23-objs := tlv320aic23.o
17snd-soc-tlv320aic26-objs := tlv320aic26.o 19snd-soc-tlv320aic26-objs := tlv320aic26.o
18snd-soc-tlv320aic3x-objs := tlv320aic3x.o 20snd-soc-tlv320aic3x-objs := tlv320aic3x.o
21snd-soc-tlv320dac33-objs := tlv320dac33.o
19snd-soc-twl4030-objs := twl4030.o 22snd-soc-twl4030-objs := twl4030.o
20snd-soc-uda134x-objs := uda134x.o 23snd-soc-uda134x-objs := uda134x.o
21snd-soc-uda1380-objs := uda1380.o 24snd-soc-uda1380-objs := uda1380.o
@@ -24,6 +27,8 @@ snd-soc-wm8400-objs := wm8400.o
24snd-soc-wm8510-objs := wm8510.o 27snd-soc-wm8510-objs := wm8510.o
25snd-soc-wm8523-objs := wm8523.o 28snd-soc-wm8523-objs := wm8523.o
26snd-soc-wm8580-objs := wm8580.o 29snd-soc-wm8580-objs := wm8580.o
30snd-soc-wm8711-objs := wm8711.o
31snd-soc-wm8727-objs := wm8727.o
27snd-soc-wm8728-objs := wm8728.o 32snd-soc-wm8728-objs := wm8728.o
28snd-soc-wm8731-objs := wm8731.o 33snd-soc-wm8731-objs := wm8731.o
29snd-soc-wm8750-objs := wm8750.o 34snd-soc-wm8750-objs := wm8750.o
@@ -47,15 +52,18 @@ snd-soc-wm-hubs-objs := wm_hubs.o
47 52
48# Amp 53# Amp
49snd-soc-max9877-objs := max9877.o 54snd-soc-max9877-objs := max9877.o
55snd-soc-tpa6130a2-objs := tpa6130a2.o
50 56
51obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o 57obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
52obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o 58obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
53obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o 59obj-$(CONFIG_SND_SOC_AD1938) += snd-soc-ad1938.o
54obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o 60obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
55obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o 61obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
62obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
56obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o 63obj-$(CONFIG_SND_SOC_AK4104) += snd-soc-ak4104.o
57obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o 64obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
58obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o 65obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
66obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
59obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o 67obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
60obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o 68obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
61obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o 69obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
@@ -66,6 +74,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
66obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o 74obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
67obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o 75obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
68obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o 76obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
77obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
69obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o 78obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
70obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 79obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
71obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 80obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
@@ -74,6 +83,8 @@ obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
74obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o 83obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
75obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o 84obj-$(CONFIG_SND_SOC_WM8523) += snd-soc-wm8523.o
76obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o 85obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
86obj-$(CONFIG_SND_SOC_WM8711) += snd-soc-wm8711.o
87obj-$(CONFIG_SND_SOC_WM8727) += snd-soc-wm8727.o
77obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o 88obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
78obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o 89obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
79obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o 90obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
@@ -97,3 +108,4 @@ obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
97 108
98# Amp 109# Amp
99obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o 110obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
111obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.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..2c18e3d1b71e 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -385,19 +385,7 @@ static int ad1836_probe(struct platform_device *pdev)
385 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets, 385 snd_soc_dapm_new_controls(codec, ad1836_dapm_widgets,
386 ARRAY_SIZE(ad1836_dapm_widgets)); 386 ARRAY_SIZE(ad1836_dapm_widgets));
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);
389 388
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: 389pcm_err:
402 return ret; 390 return ret;
403} 391}
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index 34b30efc3cb0..5d489186c05b 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -592,21 +592,9 @@ static int ad1938_probe(struct platform_device *pdev)
592 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets, 592 snd_soc_dapm_new_controls(codec, ad1938_dapm_widgets,
593 ARRAY_SIZE(ad1938_dapm_widgets)); 593 ARRAY_SIZE(ad1938_dapm_widgets));
594 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 594 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
595 snd_soc_dapm_new_widgets(codec);
596 595
597 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 596 ad1938_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
598 597
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: 598pcm_err:
611 return ret; 599 return ret;
612} 600}
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/ads117x.c b/sound/soc/codecs/ads117x.c
new file mode 100644
index 000000000000..cc96411ca3e6
--- /dev/null
+++ b/sound/soc/codecs/ads117x.c
@@ -0,0 +1,123 @@
1/*
2 * ads117x.c -- Driver for ads1174/8 ADC chips
3 *
4 * Copyright 2009 ShotSpotter Inc.
5 * Author: Graeme Gregory <gg@slimlogic.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/kernel.h>
14#include <linux/init.h>
15#include <linux/device.h>
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/initval.h>
19#include <sound/soc.h>
20
21#include "ads117x.h"
22
23#define ADS117X_RATES (SNDRV_PCM_RATE_8000_48000)
24
25#define ADS117X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
26
27struct snd_soc_dai ads117x_dai = {
28/* ADC */
29 .name = "ADS117X ADC",
30 .id = 1,
31 .capture = {
32 .stream_name = "Capture",
33 .channels_min = 1,
34 .channels_max = 32,
35 .rates = ADS117X_RATES,
36 .formats = ADS117X_FORMATS,},
37};
38EXPORT_SYMBOL_GPL(ads117x_dai);
39
40static int ads117x_probe(struct platform_device *pdev)
41{
42 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
43 struct snd_soc_codec *codec;
44 int ret;
45
46 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
47 if (codec == NULL)
48 return -ENOMEM;
49
50 socdev->card->codec = codec;
51 mutex_init(&codec->mutex);
52 INIT_LIST_HEAD(&codec->dapm_widgets);
53 INIT_LIST_HEAD(&codec->dapm_paths);
54 codec->name = "ADS117X";
55 codec->owner = THIS_MODULE;
56 codec->dai = &ads117x_dai;
57 codec->num_dai = 1;
58
59 /* register pcms */
60 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
61 if (ret < 0) {
62 printk(KERN_ERR "ads117x: failed to create pcms\n");
63 kfree(codec);
64 return ret;
65 }
66
67 return 0;
68}
69
70static int ads117x_remove(struct platform_device *pdev)
71{
72 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
73 struct snd_soc_codec *codec = socdev->card->codec;
74
75 snd_soc_free_pcms(socdev);
76 kfree(codec);
77
78 return 0;
79}
80
81struct snd_soc_codec_device soc_codec_dev_ads117x = {
82 .probe = ads117x_probe,
83 .remove = ads117x_remove,
84};
85EXPORT_SYMBOL_GPL(soc_codec_dev_ads117x);
86
87static __devinit int ads117x_platform_probe(struct platform_device *pdev)
88{
89 ads117x_dai.dev = &pdev->dev;
90 return snd_soc_register_dai(&ads117x_dai);
91}
92
93static int __devexit ads117x_platform_remove(struct platform_device *pdev)
94{
95 snd_soc_unregister_dai(&ads117x_dai);
96 return 0;
97}
98
99static struct platform_driver ads117x_codec_driver = {
100 .driver = {
101 .name = "ads117x",
102 .owner = THIS_MODULE,
103 },
104
105 .probe = ads117x_platform_probe,
106 .remove = __devexit_p(ads117x_platform_remove),
107};
108
109static int __init ads117x_init(void)
110{
111 return platform_driver_register(&ads117x_codec_driver);
112}
113module_init(ads117x_init);
114
115static void __exit ads117x_exit(void)
116{
117 platform_driver_unregister(&ads117x_codec_driver);
118}
119module_exit(ads117x_exit);
120
121MODULE_DESCRIPTION("ASoC ads117x driver");
122MODULE_AUTHOR("Graeme Gregory");
123MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
new file mode 100644
index 000000000000..dbcf50ec9bd1
--- /dev/null
+++ b/sound/soc/codecs/ads117x.h
@@ -0,0 +1,13 @@
1/*
2 * ads117x.h -- Driver for ads1174/8 ADC chips
3 *
4 * Copyright 2009 ShotSpotter Inc.
5 * Author: Graeme Gregory <gg@slimlogic.co.uk>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12extern struct snd_soc_dai ads117x_dai;
13extern struct snd_soc_codec_device soc_codec_dev_ads117x;
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..ff966567e2ba 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -294,7 +294,6 @@ static int ak4535_add_widgets(struct snd_soc_codec *codec)
294 294
295 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 295 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
296 296
297 snd_soc_dapm_new_widgets(codec);
298 return 0; 297 return 0;
299} 298}
300 299
@@ -485,17 +484,9 @@ static int ak4535_init(struct snd_soc_device *socdev)
485 snd_soc_add_controls(codec, ak4535_snd_controls, 484 snd_soc_add_controls(codec, ak4535_snd_controls,
486 ARRAY_SIZE(ak4535_snd_controls)); 485 ARRAY_SIZE(ak4535_snd_controls));
487 ak4535_add_widgets(codec); 486 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 487
494 return ret; 488 return ret;
495 489
496card_err:
497 snd_soc_free_pcms(socdev);
498 snd_soc_dapm_free(socdev);
499pcm_err: 490pcm_err:
500 kfree(codec->reg_cache); 491 kfree(codec->reg_cache);
501 492
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
new file mode 100644
index 000000000000..82fca284d007
--- /dev/null
+++ b/sound/soc/codecs/ak4671.c
@@ -0,0 +1,815 @@
1/*
2 * ak4671.c -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/init.h>
16#include <linux/i2c.h>
17#include <linux/delay.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20#include <sound/initval.h>
21#include <sound/tlv.h>
22
23#include "ak4671.h"
24
25static struct snd_soc_codec *ak4671_codec;
26
27/* codec private data */
28struct ak4671_priv {
29 struct snd_soc_codec codec;
30 u8 reg_cache[AK4671_CACHEREGNUM];
31};
32
33/* ak4671 register cache & default register settings */
34static const u8 ak4671_reg[AK4671_CACHEREGNUM] = {
35 0x00, /* AK4671_AD_DA_POWER_MANAGEMENT (0x00) */
36 0xf6, /* AK4671_PLL_MODE_SELECT0 (0x01) */
37 0x00, /* AK4671_PLL_MODE_SELECT1 (0x02) */
38 0x02, /* AK4671_FORMAT_SELECT (0x03) */
39 0x00, /* AK4671_MIC_SIGNAL_SELECT (0x04) */
40 0x55, /* AK4671_MIC_AMP_GAIN (0x05) */
41 0x00, /* AK4671_MIXING_POWER_MANAGEMENT0 (0x06) */
42 0x00, /* AK4671_MIXING_POWER_MANAGEMENT1 (0x07) */
43 0xb5, /* AK4671_OUTPUT_VOLUME_CONTROL (0x08) */
44 0x00, /* AK4671_LOUT1_SIGNAL_SELECT (0x09) */
45 0x00, /* AK4671_ROUT1_SIGNAL_SELECT (0x0a) */
46 0x00, /* AK4671_LOUT2_SIGNAL_SELECT (0x0b) */
47 0x00, /* AK4671_ROUT2_SIGNAL_SELECT (0x0c) */
48 0x00, /* AK4671_LOUT3_SIGNAL_SELECT (0x0d) */
49 0x00, /* AK4671_ROUT3_SIGNAL_SELECT (0x0e) */
50 0x00, /* AK4671_LOUT1_POWER_MANAGERMENT (0x0f) */
51 0x00, /* AK4671_LOUT2_POWER_MANAGERMENT (0x10) */
52 0x80, /* AK4671_LOUT3_POWER_MANAGERMENT (0x11) */
53 0x91, /* AK4671_LCH_INPUT_VOLUME_CONTROL (0x12) */
54 0x91, /* AK4671_RCH_INPUT_VOLUME_CONTROL (0x13) */
55 0xe1, /* AK4671_ALC_REFERENCE_SELECT (0x14) */
56 0x00, /* AK4671_DIGITAL_MIXING_CONTROL (0x15) */
57 0x00, /* AK4671_ALC_TIMER_SELECT (0x16) */
58 0x00, /* AK4671_ALC_MODE_CONTROL (0x17) */
59 0x02, /* AK4671_MODE_CONTROL1 (0x18) */
60 0x01, /* AK4671_MODE_CONTROL2 (0x19) */
61 0x18, /* AK4671_LCH_OUTPUT_VOLUME_CONTROL (0x1a) */
62 0x18, /* AK4671_RCH_OUTPUT_VOLUME_CONTROL (0x1b) */
63 0x00, /* AK4671_SIDETONE_A_CONTROL (0x1c) */
64 0x02, /* AK4671_DIGITAL_FILTER_SELECT (0x1d) */
65 0x00, /* AK4671_FIL3_COEFFICIENT0 (0x1e) */
66 0x00, /* AK4671_FIL3_COEFFICIENT1 (0x1f) */
67 0x00, /* AK4671_FIL3_COEFFICIENT2 (0x20) */
68 0x00, /* AK4671_FIL3_COEFFICIENT3 (0x21) */
69 0x00, /* AK4671_EQ_COEFFICIENT0 (0x22) */
70 0x00, /* AK4671_EQ_COEFFICIENT1 (0x23) */
71 0x00, /* AK4671_EQ_COEFFICIENT2 (0x24) */
72 0x00, /* AK4671_EQ_COEFFICIENT3 (0x25) */
73 0x00, /* AK4671_EQ_COEFFICIENT4 (0x26) */
74 0x00, /* AK4671_EQ_COEFFICIENT5 (0x27) */
75 0xa9, /* AK4671_FIL1_COEFFICIENT0 (0x28) */
76 0x1f, /* AK4671_FIL1_COEFFICIENT1 (0x29) */
77 0xad, /* AK4671_FIL1_COEFFICIENT2 (0x2a) */
78 0x20, /* AK4671_FIL1_COEFFICIENT3 (0x2b) */
79 0x00, /* AK4671_FIL2_COEFFICIENT0 (0x2c) */
80 0x00, /* AK4671_FIL2_COEFFICIENT1 (0x2d) */
81 0x00, /* AK4671_FIL2_COEFFICIENT2 (0x2e) */
82 0x00, /* AK4671_FIL2_COEFFICIENT3 (0x2f) */
83 0x00, /* AK4671_DIGITAL_FILTER_SELECT2 (0x30) */
84 0x00, /* this register not used */
85 0x00, /* AK4671_E1_COEFFICIENT0 (0x32) */
86 0x00, /* AK4671_E1_COEFFICIENT1 (0x33) */
87 0x00, /* AK4671_E1_COEFFICIENT2 (0x34) */
88 0x00, /* AK4671_E1_COEFFICIENT3 (0x35) */
89 0x00, /* AK4671_E1_COEFFICIENT4 (0x36) */
90 0x00, /* AK4671_E1_COEFFICIENT5 (0x37) */
91 0x00, /* AK4671_E2_COEFFICIENT0 (0x38) */
92 0x00, /* AK4671_E2_COEFFICIENT1 (0x39) */
93 0x00, /* AK4671_E2_COEFFICIENT2 (0x3a) */
94 0x00, /* AK4671_E2_COEFFICIENT3 (0x3b) */
95 0x00, /* AK4671_E2_COEFFICIENT4 (0x3c) */
96 0x00, /* AK4671_E2_COEFFICIENT5 (0x3d) */
97 0x00, /* AK4671_E3_COEFFICIENT0 (0x3e) */
98 0x00, /* AK4671_E3_COEFFICIENT1 (0x3f) */
99 0x00, /* AK4671_E3_COEFFICIENT2 (0x40) */
100 0x00, /* AK4671_E3_COEFFICIENT3 (0x41) */
101 0x00, /* AK4671_E3_COEFFICIENT4 (0x42) */
102 0x00, /* AK4671_E3_COEFFICIENT5 (0x43) */
103 0x00, /* AK4671_E4_COEFFICIENT0 (0x44) */
104 0x00, /* AK4671_E4_COEFFICIENT1 (0x45) */
105 0x00, /* AK4671_E4_COEFFICIENT2 (0x46) */
106 0x00, /* AK4671_E4_COEFFICIENT3 (0x47) */
107 0x00, /* AK4671_E4_COEFFICIENT4 (0x48) */
108 0x00, /* AK4671_E4_COEFFICIENT5 (0x49) */
109 0x00, /* AK4671_E5_COEFFICIENT0 (0x4a) */
110 0x00, /* AK4671_E5_COEFFICIENT1 (0x4b) */
111 0x00, /* AK4671_E5_COEFFICIENT2 (0x4c) */
112 0x00, /* AK4671_E5_COEFFICIENT3 (0x4d) */
113 0x00, /* AK4671_E5_COEFFICIENT4 (0x4e) */
114 0x00, /* AK4671_E5_COEFFICIENT5 (0x4f) */
115 0x88, /* AK4671_EQ_CONTROL_250HZ_100HZ (0x50) */
116 0x88, /* AK4671_EQ_CONTROL_3500HZ_1KHZ (0x51) */
117 0x08, /* AK4671_EQ_CONTRO_10KHZ (0x52) */
118 0x00, /* AK4671_PCM_IF_CONTROL0 (0x53) */
119 0x00, /* AK4671_PCM_IF_CONTROL1 (0x54) */
120 0x00, /* AK4671_PCM_IF_CONTROL2 (0x55) */
121 0x18, /* AK4671_DIGITAL_VOLUME_B_CONTROL (0x56) */
122 0x18, /* AK4671_DIGITAL_VOLUME_C_CONTROL (0x57) */
123 0x00, /* AK4671_SIDETONE_VOLUME_CONTROL (0x58) */
124 0x00, /* AK4671_DIGITAL_MIXING_CONTROL2 (0x59) */
125 0x00, /* AK4671_SAR_ADC_CONTROL (0x5a) */
126};
127
128/*
129 * LOUT1/ROUT1 output volume control:
130 * from -24 to 6 dB in 6 dB steps (mute instead of -30 dB)
131 */
132static DECLARE_TLV_DB_SCALE(out1_tlv, -3000, 600, 1);
133
134/*
135 * LOUT2/ROUT2 output volume control:
136 * from -33 to 6 dB in 3 dB steps (mute instead of -33 dB)
137 */
138static DECLARE_TLV_DB_SCALE(out2_tlv, -3300, 300, 1);
139
140/*
141 * LOUT3/ROUT3 output volume control:
142 * from -6 to 3 dB in 3 dB steps
143 */
144static DECLARE_TLV_DB_SCALE(out3_tlv, -600, 300, 0);
145
146/*
147 * Mic amp gain control:
148 * from -15 to 30 dB in 3 dB steps
149 * REVISIT: The actual min value(0x01) is -12 dB and the reg value 0x00 is not
150 * available
151 */
152static DECLARE_TLV_DB_SCALE(mic_amp_tlv, -1500, 300, 0);
153
154static const struct snd_kcontrol_new ak4671_snd_controls[] = {
155 /* Common playback gain controls */
156 SOC_SINGLE_TLV("Line Output1 Playback Volume",
157 AK4671_OUTPUT_VOLUME_CONTROL, 0, 0x6, 0, out1_tlv),
158 SOC_SINGLE_TLV("Headphone Output2 Playback Volume",
159 AK4671_OUTPUT_VOLUME_CONTROL, 4, 0xd, 0, out2_tlv),
160 SOC_SINGLE_TLV("Line Output3 Playback Volume",
161 AK4671_LOUT3_POWER_MANAGERMENT, 6, 0x3, 0, out3_tlv),
162
163 /* Common capture gain controls */
164 SOC_DOUBLE_TLV("Mic Amp Capture Volume",
165 AK4671_MIC_AMP_GAIN, 0, 4, 0xf, 0, mic_amp_tlv),
166};
167
168/* event handlers */
169static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
170 struct snd_kcontrol *kcontrol, int event)
171{
172 struct snd_soc_codec *codec = w->codec;
173 u8 reg;
174
175 switch (event) {
176 case SND_SOC_DAPM_POST_PMU:
177 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
178 reg |= AK4671_MUTEN;
179 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
180 break;
181 case SND_SOC_DAPM_PRE_PMD:
182 reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
183 reg &= ~AK4671_MUTEN;
184 snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
185 break;
186 }
187
188 return 0;
189}
190
191/* Output Mixers */
192static const struct snd_kcontrol_new ak4671_lout1_mixer_controls[] = {
193 SOC_DAPM_SINGLE("DACL", AK4671_LOUT1_SIGNAL_SELECT, 0, 1, 0),
194 SOC_DAPM_SINGLE("LINL1", AK4671_LOUT1_SIGNAL_SELECT, 1, 1, 0),
195 SOC_DAPM_SINGLE("LINL2", AK4671_LOUT1_SIGNAL_SELECT, 2, 1, 0),
196 SOC_DAPM_SINGLE("LINL3", AK4671_LOUT1_SIGNAL_SELECT, 3, 1, 0),
197 SOC_DAPM_SINGLE("LINL4", AK4671_LOUT1_SIGNAL_SELECT, 4, 1, 0),
198 SOC_DAPM_SINGLE("LOOPL", AK4671_LOUT1_SIGNAL_SELECT, 5, 1, 0),
199};
200
201static const struct snd_kcontrol_new ak4671_rout1_mixer_controls[] = {
202 SOC_DAPM_SINGLE("DACR", AK4671_ROUT1_SIGNAL_SELECT, 0, 1, 0),
203 SOC_DAPM_SINGLE("RINR1", AK4671_ROUT1_SIGNAL_SELECT, 1, 1, 0),
204 SOC_DAPM_SINGLE("RINR2", AK4671_ROUT1_SIGNAL_SELECT, 2, 1, 0),
205 SOC_DAPM_SINGLE("RINR3", AK4671_ROUT1_SIGNAL_SELECT, 3, 1, 0),
206 SOC_DAPM_SINGLE("RINR4", AK4671_ROUT1_SIGNAL_SELECT, 4, 1, 0),
207 SOC_DAPM_SINGLE("LOOPR", AK4671_ROUT1_SIGNAL_SELECT, 5, 1, 0),
208};
209
210static const struct snd_kcontrol_new ak4671_lout2_mixer_controls[] = {
211 SOC_DAPM_SINGLE("DACHL", AK4671_LOUT2_SIGNAL_SELECT, 0, 1, 0),
212 SOC_DAPM_SINGLE("LINH1", AK4671_LOUT2_SIGNAL_SELECT, 1, 1, 0),
213 SOC_DAPM_SINGLE("LINH2", AK4671_LOUT2_SIGNAL_SELECT, 2, 1, 0),
214 SOC_DAPM_SINGLE("LINH3", AK4671_LOUT2_SIGNAL_SELECT, 3, 1, 0),
215 SOC_DAPM_SINGLE("LINH4", AK4671_LOUT2_SIGNAL_SELECT, 4, 1, 0),
216 SOC_DAPM_SINGLE("LOOPHL", AK4671_LOUT2_SIGNAL_SELECT, 5, 1, 0),
217};
218
219static const struct snd_kcontrol_new ak4671_rout2_mixer_controls[] = {
220 SOC_DAPM_SINGLE("DACHR", AK4671_ROUT2_SIGNAL_SELECT, 0, 1, 0),
221 SOC_DAPM_SINGLE("RINH1", AK4671_ROUT2_SIGNAL_SELECT, 1, 1, 0),
222 SOC_DAPM_SINGLE("RINH2", AK4671_ROUT2_SIGNAL_SELECT, 2, 1, 0),
223 SOC_DAPM_SINGLE("RINH3", AK4671_ROUT2_SIGNAL_SELECT, 3, 1, 0),
224 SOC_DAPM_SINGLE("RINH4", AK4671_ROUT2_SIGNAL_SELECT, 4, 1, 0),
225 SOC_DAPM_SINGLE("LOOPHR", AK4671_ROUT2_SIGNAL_SELECT, 5, 1, 0),
226};
227
228static const struct snd_kcontrol_new ak4671_lout3_mixer_controls[] = {
229 SOC_DAPM_SINGLE("DACSL", AK4671_LOUT3_SIGNAL_SELECT, 0, 1, 0),
230 SOC_DAPM_SINGLE("LINS1", AK4671_LOUT3_SIGNAL_SELECT, 1, 1, 0),
231 SOC_DAPM_SINGLE("LINS2", AK4671_LOUT3_SIGNAL_SELECT, 2, 1, 0),
232 SOC_DAPM_SINGLE("LINS3", AK4671_LOUT3_SIGNAL_SELECT, 3, 1, 0),
233 SOC_DAPM_SINGLE("LINS4", AK4671_LOUT3_SIGNAL_SELECT, 4, 1, 0),
234 SOC_DAPM_SINGLE("LOOPSL", AK4671_LOUT3_SIGNAL_SELECT, 5, 1, 0),
235};
236
237static const struct snd_kcontrol_new ak4671_rout3_mixer_controls[] = {
238 SOC_DAPM_SINGLE("DACSR", AK4671_ROUT3_SIGNAL_SELECT, 0, 1, 0),
239 SOC_DAPM_SINGLE("RINS1", AK4671_ROUT3_SIGNAL_SELECT, 1, 1, 0),
240 SOC_DAPM_SINGLE("RINS2", AK4671_ROUT3_SIGNAL_SELECT, 2, 1, 0),
241 SOC_DAPM_SINGLE("RINS3", AK4671_ROUT3_SIGNAL_SELECT, 3, 1, 0),
242 SOC_DAPM_SINGLE("RINS4", AK4671_ROUT3_SIGNAL_SELECT, 4, 1, 0),
243 SOC_DAPM_SINGLE("LOOPSR", AK4671_ROUT3_SIGNAL_SELECT, 5, 1, 0),
244};
245
246/* Input MUXs */
247static const char *ak4671_lin_mux_texts[] =
248 {"LIN1", "LIN2", "LIN3", "LIN4"};
249static const struct soc_enum ak4671_lin_mux_enum =
250 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 0,
251 ARRAY_SIZE(ak4671_lin_mux_texts),
252 ak4671_lin_mux_texts);
253static const struct snd_kcontrol_new ak4671_lin_mux_control =
254 SOC_DAPM_ENUM("Route", ak4671_lin_mux_enum);
255
256static const char *ak4671_rin_mux_texts[] =
257 {"RIN1", "RIN2", "RIN3", "RIN4"};
258static const struct soc_enum ak4671_rin_mux_enum =
259 SOC_ENUM_SINGLE(AK4671_MIC_SIGNAL_SELECT, 2,
260 ARRAY_SIZE(ak4671_rin_mux_texts),
261 ak4671_rin_mux_texts);
262static const struct snd_kcontrol_new ak4671_rin_mux_control =
263 SOC_DAPM_ENUM("Route", ak4671_rin_mux_enum);
264
265static const struct snd_soc_dapm_widget ak4671_dapm_widgets[] = {
266 /* Inputs */
267 SND_SOC_DAPM_INPUT("LIN1"),
268 SND_SOC_DAPM_INPUT("RIN1"),
269 SND_SOC_DAPM_INPUT("LIN2"),
270 SND_SOC_DAPM_INPUT("RIN2"),
271 SND_SOC_DAPM_INPUT("LIN3"),
272 SND_SOC_DAPM_INPUT("RIN3"),
273 SND_SOC_DAPM_INPUT("LIN4"),
274 SND_SOC_DAPM_INPUT("RIN4"),
275
276 /* Outputs */
277 SND_SOC_DAPM_OUTPUT("LOUT1"),
278 SND_SOC_DAPM_OUTPUT("ROUT1"),
279 SND_SOC_DAPM_OUTPUT("LOUT2"),
280 SND_SOC_DAPM_OUTPUT("ROUT2"),
281 SND_SOC_DAPM_OUTPUT("LOUT3"),
282 SND_SOC_DAPM_OUTPUT("ROUT3"),
283
284 /* DAC */
285 SND_SOC_DAPM_DAC("DAC Left", "Left HiFi Playback",
286 AK4671_AD_DA_POWER_MANAGEMENT, 6, 0),
287 SND_SOC_DAPM_DAC("DAC Right", "Right HiFi Playback",
288 AK4671_AD_DA_POWER_MANAGEMENT, 7, 0),
289
290 /* ADC */
291 SND_SOC_DAPM_ADC("ADC Left", "Left HiFi Capture",
292 AK4671_AD_DA_POWER_MANAGEMENT, 4, 0),
293 SND_SOC_DAPM_ADC("ADC Right", "Right HiFi Capture",
294 AK4671_AD_DA_POWER_MANAGEMENT, 5, 0),
295
296 /* PGA */
297 SND_SOC_DAPM_PGA("LOUT2 Mix Amp",
298 AK4671_LOUT2_POWER_MANAGERMENT, 5, 0, NULL, 0),
299 SND_SOC_DAPM_PGA("ROUT2 Mix Amp",
300 AK4671_LOUT2_POWER_MANAGERMENT, 6, 0, NULL, 0),
301
302 SND_SOC_DAPM_PGA("LIN1 Mixing Circuit",
303 AK4671_MIXING_POWER_MANAGEMENT1, 0, 0, NULL, 0),
304 SND_SOC_DAPM_PGA("RIN1 Mixing Circuit",
305 AK4671_MIXING_POWER_MANAGEMENT1, 1, 0, NULL, 0),
306 SND_SOC_DAPM_PGA("LIN2 Mixing Circuit",
307 AK4671_MIXING_POWER_MANAGEMENT1, 2, 0, NULL, 0),
308 SND_SOC_DAPM_PGA("RIN2 Mixing Circuit",
309 AK4671_MIXING_POWER_MANAGEMENT1, 3, 0, NULL, 0),
310 SND_SOC_DAPM_PGA("LIN3 Mixing Circuit",
311 AK4671_MIXING_POWER_MANAGEMENT1, 4, 0, NULL, 0),
312 SND_SOC_DAPM_PGA("RIN3 Mixing Circuit",
313 AK4671_MIXING_POWER_MANAGEMENT1, 5, 0, NULL, 0),
314 SND_SOC_DAPM_PGA("LIN4 Mixing Circuit",
315 AK4671_MIXING_POWER_MANAGEMENT1, 6, 0, NULL, 0),
316 SND_SOC_DAPM_PGA("RIN4 Mixing Circuit",
317 AK4671_MIXING_POWER_MANAGEMENT1, 7, 0, NULL, 0),
318
319 /* Output Mixers */
320 SND_SOC_DAPM_MIXER("LOUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 0, 0,
321 &ak4671_lout1_mixer_controls[0],
322 ARRAY_SIZE(ak4671_lout1_mixer_controls)),
323 SND_SOC_DAPM_MIXER("ROUT1 Mixer", AK4671_LOUT1_POWER_MANAGERMENT, 1, 0,
324 &ak4671_rout1_mixer_controls[0],
325 ARRAY_SIZE(ak4671_rout1_mixer_controls)),
326 SND_SOC_DAPM_MIXER_E("LOUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
327 0, 0, &ak4671_lout2_mixer_controls[0],
328 ARRAY_SIZE(ak4671_lout2_mixer_controls),
329 ak4671_out2_event,
330 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
331 SND_SOC_DAPM_MIXER_E("ROUT2 Mixer", AK4671_LOUT2_POWER_MANAGERMENT,
332 1, 0, &ak4671_rout2_mixer_controls[0],
333 ARRAY_SIZE(ak4671_rout2_mixer_controls),
334 ak4671_out2_event,
335 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_PRE_PMD),
336 SND_SOC_DAPM_MIXER("LOUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 0, 0,
337 &ak4671_lout3_mixer_controls[0],
338 ARRAY_SIZE(ak4671_lout3_mixer_controls)),
339 SND_SOC_DAPM_MIXER("ROUT3 Mixer", AK4671_LOUT3_POWER_MANAGERMENT, 1, 0,
340 &ak4671_rout3_mixer_controls[0],
341 ARRAY_SIZE(ak4671_rout3_mixer_controls)),
342
343 /* Input MUXs */
344 SND_SOC_DAPM_MUX("LIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 2, 0,
345 &ak4671_lin_mux_control),
346 SND_SOC_DAPM_MUX("RIN MUX", AK4671_AD_DA_POWER_MANAGEMENT, 3, 0,
347 &ak4671_rin_mux_control),
348
349 /* Mic Power */
350 SND_SOC_DAPM_MICBIAS("Mic Bias", AK4671_AD_DA_POWER_MANAGEMENT, 1, 0),
351
352 /* Supply */
353 SND_SOC_DAPM_SUPPLY("PMPLL", AK4671_PLL_MODE_SELECT1, 0, 0, NULL, 0),
354};
355
356static const struct snd_soc_dapm_route intercon[] = {
357 {"DAC Left", "NULL", "PMPLL"},
358 {"DAC Right", "NULL", "PMPLL"},
359 {"ADC Left", "NULL", "PMPLL"},
360 {"ADC Right", "NULL", "PMPLL"},
361
362 /* Outputs */
363 {"LOUT1", "NULL", "LOUT1 Mixer"},
364 {"ROUT1", "NULL", "ROUT1 Mixer"},
365 {"LOUT2", "NULL", "LOUT2 Mix Amp"},
366 {"ROUT2", "NULL", "ROUT2 Mix Amp"},
367 {"LOUT3", "NULL", "LOUT3 Mixer"},
368 {"ROUT3", "NULL", "ROUT3 Mixer"},
369
370 {"LOUT1 Mixer", "DACL", "DAC Left"},
371 {"ROUT1 Mixer", "DACR", "DAC Right"},
372 {"LOUT2 Mixer", "DACHL", "DAC Left"},
373 {"ROUT2 Mixer", "DACHR", "DAC Right"},
374 {"LOUT2 Mix Amp", "NULL", "LOUT2 Mixer"},
375 {"ROUT2 Mix Amp", "NULL", "ROUT2 Mixer"},
376 {"LOUT3 Mixer", "DACSL", "DAC Left"},
377 {"ROUT3 Mixer", "DACSR", "DAC Right"},
378
379 /* Inputs */
380 {"LIN MUX", "LIN1", "LIN1"},
381 {"LIN MUX", "LIN2", "LIN2"},
382 {"LIN MUX", "LIN3", "LIN3"},
383 {"LIN MUX", "LIN4", "LIN4"},
384
385 {"RIN MUX", "RIN1", "RIN1"},
386 {"RIN MUX", "RIN2", "RIN2"},
387 {"RIN MUX", "RIN3", "RIN3"},
388 {"RIN MUX", "RIN4", "RIN4"},
389
390 {"LIN1", NULL, "Mic Bias"},
391 {"RIN1", NULL, "Mic Bias"},
392 {"LIN2", NULL, "Mic Bias"},
393 {"RIN2", NULL, "Mic Bias"},
394
395 {"ADC Left", "NULL", "LIN MUX"},
396 {"ADC Right", "NULL", "RIN MUX"},
397
398 /* Analog Loops */
399 {"LIN1 Mixing Circuit", "NULL", "LIN1"},
400 {"RIN1 Mixing Circuit", "NULL", "RIN1"},
401 {"LIN2 Mixing Circuit", "NULL", "LIN2"},
402 {"RIN2 Mixing Circuit", "NULL", "RIN2"},
403 {"LIN3 Mixing Circuit", "NULL", "LIN3"},
404 {"RIN3 Mixing Circuit", "NULL", "RIN3"},
405 {"LIN4 Mixing Circuit", "NULL", "LIN4"},
406 {"RIN4 Mixing Circuit", "NULL", "RIN4"},
407
408 {"LOUT1 Mixer", "LINL1", "LIN1 Mixing Circuit"},
409 {"ROUT1 Mixer", "RINR1", "RIN1 Mixing Circuit"},
410 {"LOUT2 Mixer", "LINH1", "LIN1 Mixing Circuit"},
411 {"ROUT2 Mixer", "RINH1", "RIN1 Mixing Circuit"},
412 {"LOUT3 Mixer", "LINS1", "LIN1 Mixing Circuit"},
413 {"ROUT3 Mixer", "RINS1", "RIN1 Mixing Circuit"},
414
415 {"LOUT1 Mixer", "LINL2", "LIN2 Mixing Circuit"},
416 {"ROUT1 Mixer", "RINR2", "RIN2 Mixing Circuit"},
417 {"LOUT2 Mixer", "LINH2", "LIN2 Mixing Circuit"},
418 {"ROUT2 Mixer", "RINH2", "RIN2 Mixing Circuit"},
419 {"LOUT3 Mixer", "LINS2", "LIN2 Mixing Circuit"},
420 {"ROUT3 Mixer", "RINS2", "RIN2 Mixing Circuit"},
421
422 {"LOUT1 Mixer", "LINL3", "LIN3 Mixing Circuit"},
423 {"ROUT1 Mixer", "RINR3", "RIN3 Mixing Circuit"},
424 {"LOUT2 Mixer", "LINH3", "LIN3 Mixing Circuit"},
425 {"ROUT2 Mixer", "RINH3", "RIN3 Mixing Circuit"},
426 {"LOUT3 Mixer", "LINS3", "LIN3 Mixing Circuit"},
427 {"ROUT3 Mixer", "RINS3", "RIN3 Mixing Circuit"},
428
429 {"LOUT1 Mixer", "LINL4", "LIN4 Mixing Circuit"},
430 {"ROUT1 Mixer", "RINR4", "RIN4 Mixing Circuit"},
431 {"LOUT2 Mixer", "LINH4", "LIN4 Mixing Circuit"},
432 {"ROUT2 Mixer", "RINH4", "RIN4 Mixing Circuit"},
433 {"LOUT3 Mixer", "LINS4", "LIN4 Mixing Circuit"},
434 {"ROUT3 Mixer", "RINS4", "RIN4 Mixing Circuit"},
435};
436
437static int ak4671_add_widgets(struct snd_soc_codec *codec)
438{
439 snd_soc_dapm_new_controls(codec, ak4671_dapm_widgets,
440 ARRAY_SIZE(ak4671_dapm_widgets));
441
442 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
443
444 return 0;
445}
446
447static int ak4671_hw_params(struct snd_pcm_substream *substream,
448 struct snd_pcm_hw_params *params,
449 struct snd_soc_dai *dai)
450{
451 struct snd_soc_codec *codec = dai->codec;
452 u8 fs;
453
454 fs = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
455 fs &= ~AK4671_FS;
456
457 switch (params_rate(params)) {
458 case 8000:
459 fs |= AK4671_FS_8KHZ;
460 break;
461 case 12000:
462 fs |= AK4671_FS_12KHZ;
463 break;
464 case 16000:
465 fs |= AK4671_FS_16KHZ;
466 break;
467 case 24000:
468 fs |= AK4671_FS_24KHZ;
469 break;
470 case 11025:
471 fs |= AK4671_FS_11_025KHZ;
472 break;
473 case 22050:
474 fs |= AK4671_FS_22_05KHZ;
475 break;
476 case 32000:
477 fs |= AK4671_FS_32KHZ;
478 break;
479 case 44100:
480 fs |= AK4671_FS_44_1KHZ;
481 break;
482 case 48000:
483 fs |= AK4671_FS_48KHZ;
484 break;
485 default:
486 return -EINVAL;
487 }
488
489 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, fs);
490
491 return 0;
492}
493
494static int ak4671_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
495 unsigned int freq, int dir)
496{
497 struct snd_soc_codec *codec = dai->codec;
498 u8 pll;
499
500 pll = snd_soc_read(codec, AK4671_PLL_MODE_SELECT0);
501 pll &= ~AK4671_PLL;
502
503 switch (freq) {
504 case 11289600:
505 pll |= AK4671_PLL_11_2896MHZ;
506 break;
507 case 12000000:
508 pll |= AK4671_PLL_12MHZ;
509 break;
510 case 12288000:
511 pll |= AK4671_PLL_12_288MHZ;
512 break;
513 case 13000000:
514 pll |= AK4671_PLL_13MHZ;
515 break;
516 case 13500000:
517 pll |= AK4671_PLL_13_5MHZ;
518 break;
519 case 19200000:
520 pll |= AK4671_PLL_19_2MHZ;
521 break;
522 case 24000000:
523 pll |= AK4671_PLL_24MHZ;
524 break;
525 case 26000000:
526 pll |= AK4671_PLL_26MHZ;
527 break;
528 case 27000000:
529 pll |= AK4671_PLL_27MHZ;
530 break;
531 default:
532 return -EINVAL;
533 }
534
535 snd_soc_write(codec, AK4671_PLL_MODE_SELECT0, pll);
536
537 return 0;
538}
539
540static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
541{
542 struct snd_soc_codec *codec = dai->codec;
543 u8 mode;
544 u8 format;
545
546 /* set master/slave audio interface */
547 mode = snd_soc_read(codec, AK4671_PLL_MODE_SELECT1);
548
549 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
550 case SND_SOC_DAIFMT_CBM_CFM:
551 mode |= AK4671_M_S;
552 break;
553 case SND_SOC_DAIFMT_CBM_CFS:
554 mode &= ~(AK4671_M_S);
555 break;
556 default:
557 return -EINVAL;
558 }
559
560 /* interface format */
561 format = snd_soc_read(codec, AK4671_FORMAT_SELECT);
562 format &= ~AK4671_DIF;
563
564 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
565 case SND_SOC_DAIFMT_I2S:
566 format |= AK4671_DIF_I2S_MODE;
567 break;
568 case SND_SOC_DAIFMT_LEFT_J:
569 format |= AK4671_DIF_MSB_MODE;
570 break;
571 case SND_SOC_DAIFMT_DSP_A:
572 format |= AK4671_DIF_DSP_MODE;
573 format |= AK4671_BCKP;
574 format |= AK4671_MSBS;
575 break;
576 default:
577 return -EINVAL;
578 }
579
580 /* set mode and format */
581 snd_soc_write(codec, AK4671_PLL_MODE_SELECT1, mode);
582 snd_soc_write(codec, AK4671_FORMAT_SELECT, format);
583
584 return 0;
585}
586
587static int ak4671_set_bias_level(struct snd_soc_codec *codec,
588 enum snd_soc_bias_level level)
589{
590 u8 reg;
591
592 switch (level) {
593 case SND_SOC_BIAS_ON:
594 case SND_SOC_BIAS_PREPARE:
595 case SND_SOC_BIAS_STANDBY:
596 reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
597 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
598 reg | AK4671_PMVCM);
599 break;
600 case SND_SOC_BIAS_OFF:
601 snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
602 break;
603 }
604 codec->bias_level = level;
605 return 0;
606}
607
608#define AK4671_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
609 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
610 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
611 SNDRV_PCM_RATE_48000)
612
613#define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE
614
615static struct snd_soc_dai_ops ak4671_dai_ops = {
616 .hw_params = ak4671_hw_params,
617 .set_sysclk = ak4671_set_dai_sysclk,
618 .set_fmt = ak4671_set_dai_fmt,
619};
620
621struct snd_soc_dai ak4671_dai = {
622 .name = "AK4671",
623 .playback = {
624 .stream_name = "Playback",
625 .channels_min = 1,
626 .channels_max = 2,
627 .rates = AK4671_RATES,
628 .formats = AK4671_FORMATS,},
629 .capture = {
630 .stream_name = "Capture",
631 .channels_min = 1,
632 .channels_max = 2,
633 .rates = AK4671_RATES,
634 .formats = AK4671_FORMATS,},
635 .ops = &ak4671_dai_ops,
636};
637EXPORT_SYMBOL_GPL(ak4671_dai);
638
639static int ak4671_probe(struct platform_device *pdev)
640{
641 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
642 struct snd_soc_codec *codec;
643 int ret = 0;
644
645 if (ak4671_codec == NULL) {
646 dev_err(&pdev->dev, "Codec device not registered\n");
647 return -ENODEV;
648 }
649
650 socdev->card->codec = ak4671_codec;
651 codec = ak4671_codec;
652
653 /* register pcms */
654 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
655 if (ret < 0) {
656 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
657 goto pcm_err;
658 }
659
660 snd_soc_add_controls(codec, ak4671_snd_controls,
661 ARRAY_SIZE(ak4671_snd_controls));
662 ak4671_add_widgets(codec);
663
664 ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
665
666 return ret;
667
668pcm_err:
669 return ret;
670}
671
672static int ak4671_remove(struct platform_device *pdev)
673{
674 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
675
676 snd_soc_free_pcms(socdev);
677 snd_soc_dapm_free(socdev);
678
679 return 0;
680}
681
682struct snd_soc_codec_device soc_codec_dev_ak4671 = {
683 .probe = ak4671_probe,
684 .remove = ak4671_remove,
685};
686EXPORT_SYMBOL_GPL(soc_codec_dev_ak4671);
687
688static int ak4671_register(struct ak4671_priv *ak4671,
689 enum snd_soc_control_type control)
690{
691 int ret;
692 struct snd_soc_codec *codec = &ak4671->codec;
693
694 if (ak4671_codec) {
695 dev_err(codec->dev, "Another AK4671 is registered\n");
696 ret = -EINVAL;
697 goto err;
698 }
699
700 mutex_init(&codec->mutex);
701 INIT_LIST_HEAD(&codec->dapm_widgets);
702 INIT_LIST_HEAD(&codec->dapm_paths);
703
704 codec->private_data = ak4671;
705 codec->name = "AK4671";
706 codec->owner = THIS_MODULE;
707 codec->bias_level = SND_SOC_BIAS_OFF;
708 codec->set_bias_level = ak4671_set_bias_level;
709 codec->dai = &ak4671_dai;
710 codec->num_dai = 1;
711 codec->reg_cache_size = AK4671_CACHEREGNUM;
712 codec->reg_cache = &ak4671->reg_cache;
713
714 memcpy(codec->reg_cache, ak4671_reg, sizeof(ak4671_reg));
715
716 ret = snd_soc_codec_set_cache_io(codec, 8, 8, control);
717 if (ret < 0) {
718 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
719 goto err;
720 }
721
722 ak4671_dai.dev = codec->dev;
723 ak4671_codec = codec;
724
725 ret = snd_soc_register_codec(codec);
726 if (ret != 0) {
727 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
728 goto err;
729 }
730
731 ret = snd_soc_register_dai(&ak4671_dai);
732 if (ret != 0) {
733 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
734 goto err_codec;
735 }
736
737 return 0;
738
739err_codec:
740 snd_soc_unregister_codec(codec);
741err:
742 kfree(ak4671);
743 return ret;
744}
745
746static void ak4671_unregister(struct ak4671_priv *ak4671)
747{
748 ak4671_set_bias_level(&ak4671->codec, SND_SOC_BIAS_OFF);
749 snd_soc_unregister_dai(&ak4671_dai);
750 snd_soc_unregister_codec(&ak4671->codec);
751 kfree(ak4671);
752 ak4671_codec = NULL;
753}
754
755static int __devinit ak4671_i2c_probe(struct i2c_client *client,
756 const struct i2c_device_id *id)
757{
758 struct ak4671_priv *ak4671;
759 struct snd_soc_codec *codec;
760
761 ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
762 if (ak4671 == NULL)
763 return -ENOMEM;
764
765 codec = &ak4671->codec;
766 codec->hw_write = (hw_write_t)i2c_master_send;
767
768 i2c_set_clientdata(client, ak4671);
769 codec->control_data = client;
770
771 codec->dev = &client->dev;
772
773 return ak4671_register(ak4671, SND_SOC_I2C);
774}
775
776static __devexit int ak4671_i2c_remove(struct i2c_client *client)
777{
778 struct ak4671_priv *ak4671 = i2c_get_clientdata(client);
779
780 ak4671_unregister(ak4671);
781
782 return 0;
783}
784
785static const struct i2c_device_id ak4671_i2c_id[] = {
786 { "ak4671", 0 },
787 { }
788};
789MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
790
791static struct i2c_driver ak4671_i2c_driver = {
792 .driver = {
793 .name = "ak4671",
794 .owner = THIS_MODULE,
795 },
796 .probe = ak4671_i2c_probe,
797 .remove = __devexit_p(ak4671_i2c_remove),
798 .id_table = ak4671_i2c_id,
799};
800
801static int __init ak4671_modinit(void)
802{
803 return i2c_add_driver(&ak4671_i2c_driver);
804}
805module_init(ak4671_modinit);
806
807static void __exit ak4671_exit(void)
808{
809 i2c_del_driver(&ak4671_i2c_driver);
810}
811module_exit(ak4671_exit);
812
813MODULE_DESCRIPTION("ASoC AK4671 codec driver");
814MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
815MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4671.h b/sound/soc/codecs/ak4671.h
new file mode 100644
index 000000000000..e2fad964e88b
--- /dev/null
+++ b/sound/soc/codecs/ak4671.h
@@ -0,0 +1,156 @@
1/*
2 * ak4671.h -- audio driver for AK4671
3 *
4 * Copyright (C) 2009 Samsung Electronics Co.Ltd
5 * Author: Joonyoung Shim <jy0922.shim@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 *
12 */
13
14#ifndef _AK4671_H
15#define _AK4671_H
16
17#define AK4671_AD_DA_POWER_MANAGEMENT 0x00
18#define AK4671_PLL_MODE_SELECT0 0x01
19#define AK4671_PLL_MODE_SELECT1 0x02
20#define AK4671_FORMAT_SELECT 0x03
21#define AK4671_MIC_SIGNAL_SELECT 0x04
22#define AK4671_MIC_AMP_GAIN 0x05
23#define AK4671_MIXING_POWER_MANAGEMENT0 0x06
24#define AK4671_MIXING_POWER_MANAGEMENT1 0x07
25#define AK4671_OUTPUT_VOLUME_CONTROL 0x08
26#define AK4671_LOUT1_SIGNAL_SELECT 0x09
27#define AK4671_ROUT1_SIGNAL_SELECT 0x0a
28#define AK4671_LOUT2_SIGNAL_SELECT 0x0b
29#define AK4671_ROUT2_SIGNAL_SELECT 0x0c
30#define AK4671_LOUT3_SIGNAL_SELECT 0x0d
31#define AK4671_ROUT3_SIGNAL_SELECT 0x0e
32#define AK4671_LOUT1_POWER_MANAGERMENT 0x0f
33#define AK4671_LOUT2_POWER_MANAGERMENT 0x10
34#define AK4671_LOUT3_POWER_MANAGERMENT 0x11
35#define AK4671_LCH_INPUT_VOLUME_CONTROL 0x12
36#define AK4671_RCH_INPUT_VOLUME_CONTROL 0x13
37#define AK4671_ALC_REFERENCE_SELECT 0x14
38#define AK4671_DIGITAL_MIXING_CONTROL 0x15
39#define AK4671_ALC_TIMER_SELECT 0x16
40#define AK4671_ALC_MODE_CONTROL 0x17
41#define AK4671_MODE_CONTROL1 0x18
42#define AK4671_MODE_CONTROL2 0x19
43#define AK4671_LCH_OUTPUT_VOLUME_CONTROL 0x1a
44#define AK4671_RCH_OUTPUT_VOLUME_CONTROL 0x1b
45#define AK4671_SIDETONE_A_CONTROL 0x1c
46#define AK4671_DIGITAL_FILTER_SELECT 0x1d
47#define AK4671_FIL3_COEFFICIENT0 0x1e
48#define AK4671_FIL3_COEFFICIENT1 0x1f
49#define AK4671_FIL3_COEFFICIENT2 0x20
50#define AK4671_FIL3_COEFFICIENT3 0x21
51#define AK4671_EQ_COEFFICIENT0 0x22
52#define AK4671_EQ_COEFFICIENT1 0x23
53#define AK4671_EQ_COEFFICIENT2 0x24
54#define AK4671_EQ_COEFFICIENT3 0x25
55#define AK4671_EQ_COEFFICIENT4 0x26
56#define AK4671_EQ_COEFFICIENT5 0x27
57#define AK4671_FIL1_COEFFICIENT0 0x28
58#define AK4671_FIL1_COEFFICIENT1 0x29
59#define AK4671_FIL1_COEFFICIENT2 0x2a
60#define AK4671_FIL1_COEFFICIENT3 0x2b
61#define AK4671_FIL2_COEFFICIENT0 0x2c
62#define AK4671_FIL2_COEFFICIENT1 0x2d
63#define AK4671_FIL2_COEFFICIENT2 0x2e
64#define AK4671_FIL2_COEFFICIENT3 0x2f
65#define AK4671_DIGITAL_FILTER_SELECT2 0x30
66#define AK4671_E1_COEFFICIENT0 0x32
67#define AK4671_E1_COEFFICIENT1 0x33
68#define AK4671_E1_COEFFICIENT2 0x34
69#define AK4671_E1_COEFFICIENT3 0x35
70#define AK4671_E1_COEFFICIENT4 0x36
71#define AK4671_E1_COEFFICIENT5 0x37
72#define AK4671_E2_COEFFICIENT0 0x38
73#define AK4671_E2_COEFFICIENT1 0x39
74#define AK4671_E2_COEFFICIENT2 0x3a
75#define AK4671_E2_COEFFICIENT3 0x3b
76#define AK4671_E2_COEFFICIENT4 0x3c
77#define AK4671_E2_COEFFICIENT5 0x3d
78#define AK4671_E3_COEFFICIENT0 0x3e
79#define AK4671_E3_COEFFICIENT1 0x3f
80#define AK4671_E3_COEFFICIENT2 0x40
81#define AK4671_E3_COEFFICIENT3 0x41
82#define AK4671_E3_COEFFICIENT4 0x42
83#define AK4671_E3_COEFFICIENT5 0x43
84#define AK4671_E4_COEFFICIENT0 0x44
85#define AK4671_E4_COEFFICIENT1 0x45
86#define AK4671_E4_COEFFICIENT2 0x46
87#define AK4671_E4_COEFFICIENT3 0x47
88#define AK4671_E4_COEFFICIENT4 0x48
89#define AK4671_E4_COEFFICIENT5 0x49
90#define AK4671_E5_COEFFICIENT0 0x4a
91#define AK4671_E5_COEFFICIENT1 0x4b
92#define AK4671_E5_COEFFICIENT2 0x4c
93#define AK4671_E5_COEFFICIENT3 0x4d
94#define AK4671_E5_COEFFICIENT4 0x4e
95#define AK4671_E5_COEFFICIENT5 0x4f
96#define AK4671_EQ_CONTROL_250HZ_100HZ 0x50
97#define AK4671_EQ_CONTROL_3500HZ_1KHZ 0x51
98#define AK4671_EQ_CONTRO_10KHZ 0x52
99#define AK4671_PCM_IF_CONTROL0 0x53
100#define AK4671_PCM_IF_CONTROL1 0x54
101#define AK4671_PCM_IF_CONTROL2 0x55
102#define AK4671_DIGITAL_VOLUME_B_CONTROL 0x56
103#define AK4671_DIGITAL_VOLUME_C_CONTROL 0x57
104#define AK4671_SIDETONE_VOLUME_CONTROL 0x58
105#define AK4671_DIGITAL_MIXING_CONTROL2 0x59
106#define AK4671_SAR_ADC_CONTROL 0x5a
107
108#define AK4671_CACHEREGNUM (AK4671_SAR_ADC_CONTROL + 1)
109
110/* Bitfield Definitions */
111
112/* AK4671_AD_DA_POWER_MANAGEMENT (0x00) Fields */
113#define AK4671_PMVCM 0x01
114
115/* AK4671_PLL_MODE_SELECT0 (0x01) Fields */
116#define AK4671_PLL 0x0f
117#define AK4671_PLL_11_2896MHZ (4 << 0)
118#define AK4671_PLL_12_288MHZ (5 << 0)
119#define AK4671_PLL_12MHZ (6 << 0)
120#define AK4671_PLL_24MHZ (7 << 0)
121#define AK4671_PLL_19_2MHZ (8 << 0)
122#define AK4671_PLL_13_5MHZ (12 << 0)
123#define AK4671_PLL_27MHZ (13 << 0)
124#define AK4671_PLL_13MHZ (14 << 0)
125#define AK4671_PLL_26MHZ (15 << 0)
126#define AK4671_FS 0xf0
127#define AK4671_FS_8KHZ (0 << 4)
128#define AK4671_FS_12KHZ (1 << 4)
129#define AK4671_FS_16KHZ (2 << 4)
130#define AK4671_FS_24KHZ (3 << 4)
131#define AK4671_FS_11_025KHZ (5 << 4)
132#define AK4671_FS_22_05KHZ (7 << 4)
133#define AK4671_FS_32KHZ (10 << 4)
134#define AK4671_FS_48KHZ (11 << 4)
135#define AK4671_FS_44_1KHZ (15 << 4)
136
137/* AK4671_PLL_MODE_SELECT1 (0x02) Fields */
138#define AK4671_PMPLL 0x01
139#define AK4671_M_S 0x02
140
141/* AK4671_FORMAT_SELECT (0x03) Fields */
142#define AK4671_DIF 0x03
143#define AK4671_DIF_DSP_MODE (0 << 0)
144#define AK4671_DIF_MSB_MODE (2 << 0)
145#define AK4671_DIF_I2S_MODE (3 << 0)
146#define AK4671_BCKP 0x04
147#define AK4671_MSBS 0x08
148#define AK4671_SDOD 0x10
149
150/* AK4671_LOUT2_POWER_MANAGEMENT (0x10) Fields */
151#define AK4671_MUTEN 0x04
152
153extern struct snd_soc_dai ak4671_dai;
154extern struct snd_soc_codec_device soc_codec_dev_ak4671;
155
156#endif
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index ca1e24a8f12a..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:
@@ -802,22 +796,6 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
802 * and all registers are written back to the hardware when resuming. 796 * and all registers are written back to the hardware when resuming.
803 */ 797 */
804 798
805static int cs4270_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
806{
807 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
808 struct snd_soc_codec *codec = &cs4270->codec;
809
810 return snd_soc_suspend_device(codec->dev);
811}
812
813static int cs4270_i2c_resume(struct i2c_client *client)
814{
815 struct cs4270_private *cs4270 = i2c_get_clientdata(client);
816 struct snd_soc_codec *codec = &cs4270->codec;
817
818 return snd_soc_resume_device(codec->dev);
819}
820
821static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg) 799static int cs4270_soc_suspend(struct platform_device *pdev, pm_message_t mesg)
822{ 800{
823 struct snd_soc_codec *codec = cs4270_codec; 801 struct snd_soc_codec *codec = cs4270_codec;
@@ -853,8 +831,6 @@ static int cs4270_soc_resume(struct platform_device *pdev)
853 return snd_soc_write(codec, CS4270_PWRCTL, reg); 831 return snd_soc_write(codec, CS4270_PWRCTL, reg);
854} 832}
855#else 833#else
856#define cs4270_i2c_suspend NULL
857#define cs4270_i2c_resume NULL
858#define cs4270_soc_suspend NULL 834#define cs4270_soc_suspend NULL
859#define cs4270_soc_resume NULL 835#define cs4270_soc_resume NULL
860#endif /* CONFIG_PM */ 836#endif /* CONFIG_PM */
@@ -873,8 +849,6 @@ static struct i2c_driver cs4270_i2c_driver = {
873 .id_table = cs4270_id, 849 .id_table = cs4270_id,
874 .probe = cs4270_i2c_probe, 850 .probe = cs4270_i2c_probe,
875 .remove = cs4270_i2c_remove, 851 .remove = cs4270_i2c_remove,
876 .suspend = cs4270_i2c_suspend,
877 .resume = cs4270_i2c_resume,
878}; 852};
879 853
880/* 854/*
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index 38eac9c866e1..e000cdfec1ec 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -93,7 +93,6 @@ static int cx20442_add_widgets(struct snd_soc_codec *codec)
93 snd_soc_dapm_add_routes(codec, cx20442_audio_map, 93 snd_soc_dapm_add_routes(codec, cx20442_audio_map,
94 ARRAY_SIZE(cx20442_audio_map)); 94 ARRAY_SIZE(cx20442_audio_map));
95 95
96 snd_soc_dapm_new_widgets(codec);
97 return 0; 96 return 0;
98} 97}
99 98
@@ -355,17 +354,6 @@ static int cx20442_codec_probe(struct platform_device *pdev)
355 354
356 cx20442_add_widgets(codec); 355 cx20442_add_widgets(codec);
357 356
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: 357pcm_err:
370 return ret; 358 return ret;
371} 359}
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..d2ff1cde6883 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -210,7 +210,6 @@ static int ssm2602_add_widgets(struct snd_soc_codec *codec)
210 210
211 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn)); 211 snd_soc_dapm_add_routes(codec, audio_conn, ARRAY_SIZE(audio_conn));
212 212
213 snd_soc_dapm_new_widgets(codec);
214 return 0; 213 return 0;
215} 214}
216 215
@@ -613,17 +612,9 @@ static int ssm2602_init(struct snd_soc_device *socdev)
613 snd_soc_add_controls(codec, ssm2602_snd_controls, 612 snd_soc_add_controls(codec, ssm2602_snd_controls,
614 ARRAY_SIZE(ssm2602_snd_controls)); 613 ARRAY_SIZE(ssm2602_snd_controls));
615 ssm2602_add_widgets(codec); 614 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 615
622 return ret; 616 return ret;
623 617
624card_err:
625 snd_soc_free_pcms(socdev);
626 snd_soc_dapm_free(socdev);
627pcm_err: 618pcm_err:
628 kfree(codec->reg_cache); 619 kfree(codec->reg_cache);
629 return ret; 620 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 35606ae60868..a9dc5fb54774 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -265,8 +265,8 @@ static const int bosr_usb_divisor_table[] = {
265#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15)) 265#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
266static const unsigned short sr_valid_mask[] = { 266static const unsigned short sr_valid_mask[] = {
267 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/ 267 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
268 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
269 LOWER_GROUP, /* Usb, bosr - 0*/ 268 LOWER_GROUP, /* Usb, bosr - 0*/
269 LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
270 UPPER_GROUP, /* Usb, bosr - 1*/ 270 UPPER_GROUP, /* Usb, bosr - 1*/
271}; 271};
272/* 272/*
@@ -395,7 +395,6 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
395 /* set up audio path interconnects */ 395 /* set up audio path interconnects */
396 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 396 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
397 397
398 snd_soc_dapm_new_widgets(codec);
399 return 0; 398 return 0;
400} 399}
401 400
@@ -625,11 +624,10 @@ static int tlv320aic23_resume(struct platform_device *pdev)
625{ 624{
626 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 625 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
627 struct snd_soc_codec *codec = socdev->card->codec; 626 struct snd_soc_codec *codec = socdev->card->codec;
628 int i;
629 u16 reg; 627 u16 reg;
630 628
631 /* Sync reg_cache with the hardware */ 629 /* Sync reg_cache with the hardware */
632 for (reg = 0; reg < ARRAY_SIZE(tlv320aic23_reg); i++) { 630 for (reg = 0; reg < TLV320AIC23_RESET; reg++) {
633 u16 val = tlv320aic23_read_reg_cache(codec, reg); 631 u16 val = tlv320aic23_read_reg_cache(codec, reg);
634 tlv320aic23_write(codec, reg, val); 632 tlv320aic23_write(codec, reg, val);
635 } 633 }
@@ -707,17 +705,9 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
707 snd_soc_add_controls(codec, tlv320aic23_snd_controls, 705 snd_soc_add_controls(codec, tlv320aic23_snd_controls,
708 ARRAY_SIZE(tlv320aic23_snd_controls)); 706 ARRAY_SIZE(tlv320aic23_snd_controls));
709 tlv320aic23_add_widgets(codec); 707 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 708
716 return ret; 709 return ret;
717 710
718card_err:
719 snd_soc_free_pcms(socdev);
720 snd_soc_dapm_free(socdev);
721pcm_err: 711pcm_err:
722 kfree(codec->reg_cache); 712 kfree(codec->reg_cache);
723 return ret; 713 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..2b4dc2b0b017 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -753,7 +753,6 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
753 /* set up audio path interconnects */ 753 /* set up audio path interconnects */
754 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 754 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
755 755
756 snd_soc_dapm_new_widgets(codec);
757 return 0; 756 return 0;
758} 757}
759 758
@@ -1405,18 +1404,8 @@ static int aic3x_probe(struct platform_device *pdev)
1405 1404
1406 aic3x_add_widgets(codec); 1405 aic3x_add_widgets(codec);
1407 1406
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; 1407 return ret;
1415 1408
1416card_err:
1417 snd_soc_free_pcms(socdev);
1418 snd_soc_dapm_free(socdev);
1419
1420pcm_err: 1409pcm_err:
1421 kfree(codec->reg_cache); 1410 kfree(codec->reg_cache);
1422 return ret; 1411 return ret;
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
new file mode 100644
index 000000000000..9c8903dbe647
--- /dev/null
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -0,0 +1,1229 @@
1/*
2 * ALSA SoC Texas Instruments TLV320DAC33 codec driver
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/init.h>
27#include <linux/delay.h>
28#include <linux/pm.h>
29#include <linux/i2c.h>
30#include <linux/platform_device.h>
31#include <linux/interrupt.h>
32#include <linux/gpio.h>
33#include <sound/core.h>
34#include <sound/pcm.h>
35#include <sound/pcm_params.h>
36#include <sound/soc.h>
37#include <sound/soc-dapm.h>
38#include <sound/initval.h>
39#include <sound/tlv.h>
40
41#include <sound/tlv320dac33-plat.h>
42#include "tlv320dac33.h"
43
44#define DAC33_BUFFER_SIZE_BYTES 24576 /* bytes, 12288 16 bit words,
45 * 6144 stereo */
46#define DAC33_BUFFER_SIZE_SAMPLES 6144
47
48#define NSAMPLE_MAX 5700
49
50#define LATENCY_TIME_MS 20
51
52static struct snd_soc_codec *tlv320dac33_codec;
53
54enum dac33_state {
55 DAC33_IDLE = 0,
56 DAC33_PREFILL,
57 DAC33_PLAYBACK,
58 DAC33_FLUSH,
59};
60
61struct tlv320dac33_priv {
62 struct mutex mutex;
63 struct workqueue_struct *dac33_wq;
64 struct work_struct work;
65 struct snd_soc_codec codec;
66 int power_gpio;
67 int chip_power;
68 int irq;
69 unsigned int refclk;
70
71 unsigned int alarm_threshold; /* set to be half of LATENCY_TIME_MS */
72 unsigned int nsample_min; /* nsample should not be lower than
73 * this */
74 unsigned int nsample_max; /* nsample should not be higher than
75 * this */
76 unsigned int nsample_switch; /* Use FIFO or bypass FIFO switch */
77 unsigned int nsample; /* burst read amount from host */
78
79 enum dac33_state state;
80};
81
82static const u8 dac33_reg[DAC33_CACHEREGNUM] = {
830x00, 0x00, 0x00, 0x00, /* 0x00 - 0x03 */
840x00, 0x00, 0x00, 0x00, /* 0x04 - 0x07 */
850x00, 0x00, 0x00, 0x00, /* 0x08 - 0x0b */
860x00, 0x00, 0x00, 0x00, /* 0x0c - 0x0f */
870x00, 0x00, 0x00, 0x00, /* 0x10 - 0x13 */
880x00, 0x00, 0x00, 0x00, /* 0x14 - 0x17 */
890x00, 0x00, 0x00, 0x00, /* 0x18 - 0x1b */
900x00, 0x00, 0x00, 0x00, /* 0x1c - 0x1f */
910x00, 0x00, 0x00, 0x00, /* 0x20 - 0x23 */
920x00, 0x00, 0x00, 0x00, /* 0x24 - 0x27 */
930x00, 0x00, 0x00, 0x00, /* 0x28 - 0x2b */
940x00, 0x00, 0x00, 0x80, /* 0x2c - 0x2f */
950x80, 0x00, 0x00, 0x00, /* 0x30 - 0x33 */
960x00, 0x00, 0x00, 0x00, /* 0x34 - 0x37 */
970x00, 0x00, /* 0x38 - 0x39 */
98/* Registers 0x3a - 0x3f are reserved */
99 0x00, 0x00, /* 0x3a - 0x3b */
1000x00, 0x00, 0x00, 0x00, /* 0x3c - 0x3f */
101
1020x00, 0x00, 0x00, 0x00, /* 0x40 - 0x43 */
1030x00, 0x80, /* 0x44 - 0x45 */
104/* Registers 0x46 - 0x47 are reserved */
105 0x80, 0x80, /* 0x46 - 0x47 */
106
1070x80, 0x00, 0x00, /* 0x48 - 0x4a */
108/* Registers 0x4b - 0x7c are reserved */
109 0x00, /* 0x4b */
1100x00, 0x00, 0x00, 0x00, /* 0x4c - 0x4f */
1110x00, 0x00, 0x00, 0x00, /* 0x50 - 0x53 */
1120x00, 0x00, 0x00, 0x00, /* 0x54 - 0x57 */
1130x00, 0x00, 0x00, 0x00, /* 0x58 - 0x5b */
1140x00, 0x00, 0x00, 0x00, /* 0x5c - 0x5f */
1150x00, 0x00, 0x00, 0x00, /* 0x60 - 0x63 */
1160x00, 0x00, 0x00, 0x00, /* 0x64 - 0x67 */
1170x00, 0x00, 0x00, 0x00, /* 0x68 - 0x6b */
1180x00, 0x00, 0x00, 0x00, /* 0x6c - 0x6f */
1190x00, 0x00, 0x00, 0x00, /* 0x70 - 0x73 */
1200x00, 0x00, 0x00, 0x00, /* 0x74 - 0x77 */
1210x00, 0x00, 0x00, 0x00, /* 0x78 - 0x7b */
1220x00, /* 0x7c */
123
124 0xda, 0x33, 0x03, /* 0x7d - 0x7f */
125};
126
127/* Register read and write */
128static inline unsigned int dac33_read_reg_cache(struct snd_soc_codec *codec,
129 unsigned reg)
130{
131 u8 *cache = codec->reg_cache;
132 if (reg >= DAC33_CACHEREGNUM)
133 return 0;
134
135 return cache[reg];
136}
137
138static inline void dac33_write_reg_cache(struct snd_soc_codec *codec,
139 u8 reg, u8 value)
140{
141 u8 *cache = codec->reg_cache;
142 if (reg >= DAC33_CACHEREGNUM)
143 return;
144
145 cache[reg] = value;
146}
147
148static int dac33_read(struct snd_soc_codec *codec, unsigned int reg,
149 u8 *value)
150{
151 struct tlv320dac33_priv *dac33 = codec->private_data;
152 int val;
153
154 *value = reg & 0xff;
155
156 /* If powered off, return the cached value */
157 if (dac33->chip_power) {
158 val = i2c_smbus_read_byte_data(codec->control_data, value[0]);
159 if (val < 0) {
160 dev_err(codec->dev, "Read failed (%d)\n", val);
161 value[0] = dac33_read_reg_cache(codec, reg);
162 } else {
163 value[0] = val;
164 dac33_write_reg_cache(codec, reg, val);
165 }
166 } else {
167 value[0] = dac33_read_reg_cache(codec, reg);
168 }
169
170 return 0;
171}
172
173static int dac33_write(struct snd_soc_codec *codec, unsigned int reg,
174 unsigned int value)
175{
176 struct tlv320dac33_priv *dac33 = codec->private_data;
177 u8 data[2];
178 int ret = 0;
179
180 /*
181 * data is
182 * D15..D8 dac33 register offset
183 * D7...D0 register data
184 */
185 data[0] = reg & 0xff;
186 data[1] = value & 0xff;
187
188 dac33_write_reg_cache(codec, data[0], data[1]);
189 if (dac33->chip_power) {
190 ret = codec->hw_write(codec->control_data, data, 2);
191 if (ret != 2)
192 dev_err(codec->dev, "Write failed (%d)\n", ret);
193 else
194 ret = 0;
195 }
196
197 return ret;
198}
199
200static int dac33_write_locked(struct snd_soc_codec *codec, unsigned int reg,
201 unsigned int value)
202{
203 struct tlv320dac33_priv *dac33 = codec->private_data;
204 int ret;
205
206 mutex_lock(&dac33->mutex);
207 ret = dac33_write(codec, reg, value);
208 mutex_unlock(&dac33->mutex);
209
210 return ret;
211}
212
213#define DAC33_I2C_ADDR_AUTOINC 0x80
214static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg,
215 unsigned int value)
216{
217 struct tlv320dac33_priv *dac33 = codec->private_data;
218 u8 data[3];
219 int ret = 0;
220
221 /*
222 * data is
223 * D23..D16 dac33 register offset
224 * D15..D8 register data MSB
225 * D7...D0 register data LSB
226 */
227 data[0] = reg & 0xff;
228 data[1] = (value >> 8) & 0xff;
229 data[2] = value & 0xff;
230
231 dac33_write_reg_cache(codec, data[0], data[1]);
232 dac33_write_reg_cache(codec, data[0] + 1, data[2]);
233
234 if (dac33->chip_power) {
235 /* We need to set autoincrement mode for 16 bit writes */
236 data[0] |= DAC33_I2C_ADDR_AUTOINC;
237 ret = codec->hw_write(codec->control_data, data, 3);
238 if (ret != 3)
239 dev_err(codec->dev, "Write failed (%d)\n", ret);
240 else
241 ret = 0;
242 }
243
244 return ret;
245}
246
247static void dac33_restore_regs(struct snd_soc_codec *codec)
248{
249 struct tlv320dac33_priv *dac33 = codec->private_data;
250 u8 *cache = codec->reg_cache;
251 u8 data[2];
252 int i, ret;
253
254 if (!dac33->chip_power)
255 return;
256
257 for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) {
258 data[0] = i;
259 data[1] = cache[i];
260 /* Skip the read only registers */
261 if ((i >= DAC33_INT_OSC_STATUS &&
262 i <= DAC33_INT_OSC_FREQ_RAT_READ_B) ||
263 (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) ||
264 i == DAC33_DAC_STATUS_FLAGS ||
265 i == DAC33_SRC_EST_REF_CLK_RATIO_A ||
266 i == DAC33_SRC_EST_REF_CLK_RATIO_B)
267 continue;
268 ret = codec->hw_write(codec->control_data, data, 2);
269 if (ret != 2)
270 dev_err(codec->dev, "Write failed (%d)\n", ret);
271 }
272 for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) {
273 data[0] = i;
274 data[1] = cache[i];
275 ret = codec->hw_write(codec->control_data, data, 2);
276 if (ret != 2)
277 dev_err(codec->dev, "Write failed (%d)\n", ret);
278 }
279 for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) {
280 data[0] = i;
281 data[1] = cache[i];
282 ret = codec->hw_write(codec->control_data, data, 2);
283 if (ret != 2)
284 dev_err(codec->dev, "Write failed (%d)\n", ret);
285 }
286}
287
288static inline void dac33_soft_power(struct snd_soc_codec *codec, int power)
289{
290 u8 reg;
291
292 reg = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
293 if (power)
294 reg |= DAC33_PDNALLB;
295 else
296 reg &= ~DAC33_PDNALLB;
297 dac33_write(codec, DAC33_PWR_CTRL, reg);
298}
299
300static void dac33_hard_power(struct snd_soc_codec *codec, int power)
301{
302 struct tlv320dac33_priv *dac33 = codec->private_data;
303
304 mutex_lock(&dac33->mutex);
305 if (power) {
306 if (dac33->power_gpio >= 0) {
307 gpio_set_value(dac33->power_gpio, 1);
308 dac33->chip_power = 1;
309 /* Restore registers */
310 dac33_restore_regs(codec);
311 }
312 dac33_soft_power(codec, 1);
313 } else {
314 dac33_soft_power(codec, 0);
315 if (dac33->power_gpio >= 0) {
316 gpio_set_value(dac33->power_gpio, 0);
317 dac33->chip_power = 0;
318 }
319 }
320 mutex_unlock(&dac33->mutex);
321
322}
323
324static int dac33_get_nsample(struct snd_kcontrol *kcontrol,
325 struct snd_ctl_elem_value *ucontrol)
326{
327 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
328 struct tlv320dac33_priv *dac33 = codec->private_data;
329
330 ucontrol->value.integer.value[0] = dac33->nsample;
331
332 return 0;
333}
334
335static int dac33_set_nsample(struct snd_kcontrol *kcontrol,
336 struct snd_ctl_elem_value *ucontrol)
337{
338 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
339 struct tlv320dac33_priv *dac33 = codec->private_data;
340 int ret = 0;
341
342 if (dac33->nsample == ucontrol->value.integer.value[0])
343 return 0;
344
345 if (ucontrol->value.integer.value[0] < dac33->nsample_min ||
346 ucontrol->value.integer.value[0] > dac33->nsample_max)
347 ret = -EINVAL;
348 else
349 dac33->nsample = ucontrol->value.integer.value[0];
350
351 return ret;
352}
353
354static int dac33_get_nsample_switch(struct snd_kcontrol *kcontrol,
355 struct snd_ctl_elem_value *ucontrol)
356{
357 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
358 struct tlv320dac33_priv *dac33 = codec->private_data;
359
360 ucontrol->value.integer.value[0] = dac33->nsample_switch;
361
362 return 0;
363}
364
365static int dac33_set_nsample_switch(struct snd_kcontrol *kcontrol,
366 struct snd_ctl_elem_value *ucontrol)
367{
368 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
369 struct tlv320dac33_priv *dac33 = codec->private_data;
370 int ret = 0;
371
372 if (dac33->nsample_switch == ucontrol->value.integer.value[0])
373 return 0;
374 /* Do not allow changes while stream is running*/
375 if (codec->active)
376 return -EPERM;
377
378 if (ucontrol->value.integer.value[0] < 0 ||
379 ucontrol->value.integer.value[0] > 1)
380 ret = -EINVAL;
381 else
382 dac33->nsample_switch = ucontrol->value.integer.value[0];
383
384 return ret;
385}
386
387/*
388 * DACL/R digital volume control:
389 * from 0 dB to -63.5 in 0.5 dB steps
390 * Need to be inverted later on:
391 * 0x00 == 0 dB
392 * 0x7f == -63.5 dB
393 */
394static DECLARE_TLV_DB_SCALE(dac_digivol_tlv, -6350, 50, 0);
395
396static const struct snd_kcontrol_new dac33_snd_controls[] = {
397 SOC_DOUBLE_R_TLV("DAC Digital Playback Volume",
398 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL,
399 0, 0x7f, 1, dac_digivol_tlv),
400 SOC_DOUBLE_R("DAC Digital Playback Switch",
401 DAC33_LDAC_DIG_VOL_CTRL, DAC33_RDAC_DIG_VOL_CTRL, 7, 1, 1),
402 SOC_DOUBLE_R("Line to Line Out Volume",
403 DAC33_LINEL_TO_LLO_VOL, DAC33_LINER_TO_RLO_VOL, 0, 127, 1),
404};
405
406static const struct snd_kcontrol_new dac33_nsample_snd_controls[] = {
407 SOC_SINGLE_EXT("nSample", 0, 0, 5900, 0,
408 dac33_get_nsample, dac33_set_nsample),
409 SOC_SINGLE_EXT("nSample Switch", 0, 0, 1, 0,
410 dac33_get_nsample_switch, dac33_set_nsample_switch),
411};
412
413/* Analog bypass */
414static const struct snd_kcontrol_new dac33_dapm_abypassl_control =
415 SOC_DAPM_SINGLE("Switch", DAC33_LINEL_TO_LLO_VOL, 7, 1, 1);
416
417static const struct snd_kcontrol_new dac33_dapm_abypassr_control =
418 SOC_DAPM_SINGLE("Switch", DAC33_LINER_TO_RLO_VOL, 7, 1, 1);
419
420static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = {
421 SND_SOC_DAPM_OUTPUT("LEFT_LO"),
422 SND_SOC_DAPM_OUTPUT("RIGHT_LO"),
423
424 SND_SOC_DAPM_INPUT("LINEL"),
425 SND_SOC_DAPM_INPUT("LINER"),
426
427 SND_SOC_DAPM_DAC("DACL", "Left Playback", DAC33_LDAC_PWR_CTRL, 2, 0),
428 SND_SOC_DAPM_DAC("DACR", "Right Playback", DAC33_RDAC_PWR_CTRL, 2, 0),
429
430 /* Analog bypass */
431 SND_SOC_DAPM_SWITCH("Analog Left Bypass", SND_SOC_NOPM, 0, 0,
432 &dac33_dapm_abypassl_control),
433 SND_SOC_DAPM_SWITCH("Analog Right Bypass", SND_SOC_NOPM, 0, 0,
434 &dac33_dapm_abypassr_control),
435
436 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Left Amp Power",
437 DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0),
438 SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power",
439 DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0),
440};
441
442static const struct snd_soc_dapm_route audio_map[] = {
443 /* Analog bypass */
444 {"Analog Left Bypass", "Switch", "LINEL"},
445 {"Analog Right Bypass", "Switch", "LINER"},
446
447 {"Output Left Amp Power", NULL, "DACL"},
448 {"Output Right Amp Power", NULL, "DACR"},
449
450 {"Output Left Amp Power", NULL, "Analog Left Bypass"},
451 {"Output Right Amp Power", NULL, "Analog Right Bypass"},
452
453 /* output */
454 {"LEFT_LO", NULL, "Output Left Amp Power"},
455 {"RIGHT_LO", NULL, "Output Right Amp Power"},
456};
457
458static int dac33_add_widgets(struct snd_soc_codec *codec)
459{
460 snd_soc_dapm_new_controls(codec, dac33_dapm_widgets,
461 ARRAY_SIZE(dac33_dapm_widgets));
462
463 /* set up audio path interconnects */
464 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
465
466 return 0;
467}
468
469static int dac33_set_bias_level(struct snd_soc_codec *codec,
470 enum snd_soc_bias_level level)
471{
472 switch (level) {
473 case SND_SOC_BIAS_ON:
474 dac33_soft_power(codec, 1);
475 break;
476 case SND_SOC_BIAS_PREPARE:
477 break;
478 case SND_SOC_BIAS_STANDBY:
479 if (codec->bias_level == SND_SOC_BIAS_OFF)
480 dac33_hard_power(codec, 1);
481 dac33_soft_power(codec, 0);
482 break;
483 case SND_SOC_BIAS_OFF:
484 dac33_hard_power(codec, 0);
485 break;
486 }
487 codec->bias_level = level;
488
489 return 0;
490}
491
492static void dac33_work(struct work_struct *work)
493{
494 struct snd_soc_codec *codec;
495 struct tlv320dac33_priv *dac33;
496 u8 reg;
497
498 dac33 = container_of(work, struct tlv320dac33_priv, work);
499 codec = &dac33->codec;
500
501 mutex_lock(&dac33->mutex);
502 switch (dac33->state) {
503 case DAC33_PREFILL:
504 dac33->state = DAC33_PLAYBACK;
505 dac33_write16(codec, DAC33_NSAMPLE_MSB,
506 DAC33_THRREG(dac33->nsample));
507 dac33_write16(codec, DAC33_PREFILL_MSB,
508 DAC33_THRREG(dac33->alarm_threshold));
509 break;
510 case DAC33_PLAYBACK:
511 dac33_write16(codec, DAC33_NSAMPLE_MSB,
512 DAC33_THRREG(dac33->nsample));
513 break;
514 case DAC33_IDLE:
515 break;
516 case DAC33_FLUSH:
517 dac33->state = DAC33_IDLE;
518 /* Mask all interrupts from dac33 */
519 dac33_write(codec, DAC33_FIFO_IRQ_MASK, 0);
520
521 /* flush fifo */
522 reg = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A);
523 reg |= DAC33_FIFOFLUSH;
524 dac33_write(codec, DAC33_FIFO_CTRL_A, reg);
525 break;
526 }
527 mutex_unlock(&dac33->mutex);
528}
529
530static irqreturn_t dac33_interrupt_handler(int irq, void *dev)
531{
532 struct snd_soc_codec *codec = dev;
533 struct tlv320dac33_priv *dac33 = codec->private_data;
534
535 queue_work(dac33->dac33_wq, &dac33->work);
536
537 return IRQ_HANDLED;
538}
539
540static void dac33_shutdown(struct snd_pcm_substream *substream,
541 struct snd_soc_dai *dai)
542{
543 struct snd_soc_pcm_runtime *rtd = substream->private_data;
544 struct snd_soc_device *socdev = rtd->socdev;
545 struct snd_soc_codec *codec = socdev->card->codec;
546 struct tlv320dac33_priv *dac33 = codec->private_data;
547 unsigned int pwr_ctrl;
548
549 /* Stop pending workqueue */
550 if (dac33->nsample_switch)
551 cancel_work_sync(&dac33->work);
552
553 mutex_lock(&dac33->mutex);
554 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
555 pwr_ctrl &= ~(DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB);
556 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
557 mutex_unlock(&dac33->mutex);
558}
559
560static void dac33_oscwait(struct snd_soc_codec *codec)
561{
562 int timeout = 20;
563 u8 reg;
564
565 do {
566 msleep(1);
567 dac33_read(codec, DAC33_INT_OSC_STATUS, &reg);
568 } while (((reg & 0x03) != DAC33_OSCSTATUS_NORMAL) && timeout--);
569 if ((reg & 0x03) != DAC33_OSCSTATUS_NORMAL)
570 dev_err(codec->dev,
571 "internal oscillator calibration failed\n");
572}
573
574static int dac33_hw_params(struct snd_pcm_substream *substream,
575 struct snd_pcm_hw_params *params,
576 struct snd_soc_dai *dai)
577{
578 struct snd_soc_pcm_runtime *rtd = substream->private_data;
579 struct snd_soc_device *socdev = rtd->socdev;
580 struct snd_soc_codec *codec = socdev->card->codec;
581
582 /* Check parameters for validity */
583 switch (params_rate(params)) {
584 case 44100:
585 case 48000:
586 break;
587 default:
588 dev_err(codec->dev, "unsupported rate %d\n",
589 params_rate(params));
590 return -EINVAL;
591 }
592
593 switch (params_format(params)) {
594 case SNDRV_PCM_FORMAT_S16_LE:
595 break;
596 default:
597 dev_err(codec->dev, "unsupported format %d\n",
598 params_format(params));
599 return -EINVAL;
600 }
601
602 return 0;
603}
604
605#define CALC_OSCSET(rate, refclk) ( \
606 ((((rate * 10000) / refclk) * 4096) + 5000) / 10000)
607#define CALC_RATIOSET(rate, refclk) ( \
608 ((((refclk * 100000) / rate) * 16384) + 50000) / 100000)
609
610/*
611 * tlv320dac33 is strict on the sequence of the register writes, if the register
612 * writes happens in different order, than dac33 might end up in unknown state.
613 * Use the known, working sequence of register writes to initialize the dac33.
614 */
615static int dac33_prepare_chip(struct snd_pcm_substream *substream)
616{
617 struct snd_soc_pcm_runtime *rtd = substream->private_data;
618 struct snd_soc_device *socdev = rtd->socdev;
619 struct snd_soc_codec *codec = socdev->card->codec;
620 struct tlv320dac33_priv *dac33 = codec->private_data;
621 unsigned int oscset, ratioset, pwr_ctrl, reg_tmp;
622 u8 aictrl_a, fifoctrl_a;
623
624 switch (substream->runtime->rate) {
625 case 44100:
626 case 48000:
627 oscset = CALC_OSCSET(substream->runtime->rate, dac33->refclk);
628 ratioset = CALC_RATIOSET(substream->runtime->rate,
629 dac33->refclk);
630 break;
631 default:
632 dev_err(codec->dev, "unsupported rate %d\n",
633 substream->runtime->rate);
634 return -EINVAL;
635 }
636
637
638 aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A);
639 aictrl_a &= ~(DAC33_NCYCL_MASK | DAC33_WLEN_MASK);
640 fifoctrl_a = dac33_read_reg_cache(codec, DAC33_FIFO_CTRL_A);
641 fifoctrl_a &= ~DAC33_WIDTH;
642 switch (substream->runtime->format) {
643 case SNDRV_PCM_FORMAT_S16_LE:
644 aictrl_a |= (DAC33_NCYCL_16 | DAC33_WLEN_16);
645 fifoctrl_a |= DAC33_WIDTH;
646 break;
647 default:
648 dev_err(codec->dev, "unsupported format %d\n",
649 substream->runtime->format);
650 return -EINVAL;
651 }
652
653 mutex_lock(&dac33->mutex);
654 dac33_soft_power(codec, 1);
655
656 reg_tmp = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
657 dac33_write(codec, DAC33_INT_OSC_CTRL, reg_tmp);
658
659 /* Write registers 0x08 and 0x09 (MSB, LSB) */
660 dac33_write16(codec, DAC33_INT_OSC_FREQ_RAT_A, oscset);
661
662 /* calib time: 128 is a nice number ;) */
663 dac33_write(codec, DAC33_CALIB_TIME, 128);
664
665 /* adjustment treshold & step */
666 dac33_write(codec, DAC33_INT_OSC_CTRL_B, DAC33_ADJTHRSHLD(2) |
667 DAC33_ADJSTEP(1));
668
669 /* div=4 / gain=1 / div */
670 dac33_write(codec, DAC33_INT_OSC_CTRL_C, DAC33_REFDIV(4));
671
672 pwr_ctrl = dac33_read_reg_cache(codec, DAC33_PWR_CTRL);
673 pwr_ctrl |= DAC33_OSCPDNB | DAC33_DACRPDNB | DAC33_DACLPDNB;
674 dac33_write(codec, DAC33_PWR_CTRL, pwr_ctrl);
675
676 dac33_oscwait(codec);
677
678 if (dac33->nsample_switch) {
679 /* 50-51 : ASRC Control registers */
680 dac33_write(codec, DAC33_ASRC_CTRL_A, (1 << 4)); /* div=2 */
681 dac33_write(codec, DAC33_ASRC_CTRL_B, 1); /* ??? */
682
683 /* Write registers 0x34 and 0x35 (MSB, LSB) */
684 dac33_write16(codec, DAC33_SRC_REF_CLK_RATIO_A, ratioset);
685
686 /* Set interrupts to high active */
687 dac33_write(codec, DAC33_INTP_CTRL_A, DAC33_INTPM_AHIGH);
688
689 dac33_write(codec, DAC33_FIFO_IRQ_MODE_B,
690 DAC33_ATM(DAC33_FIFO_IRQ_MODE_LEVEL));
691 dac33_write(codec, DAC33_FIFO_IRQ_MASK, DAC33_MAT);
692 } else {
693 /* 50-51 : ASRC Control registers */
694 dac33_write(codec, DAC33_ASRC_CTRL_A, DAC33_SRCBYP);
695 dac33_write(codec, DAC33_ASRC_CTRL_B, 0); /* ??? */
696 }
697
698 if (dac33->nsample_switch)
699 fifoctrl_a &= ~DAC33_FBYPAS;
700 else
701 fifoctrl_a |= DAC33_FBYPAS;
702 dac33_write(codec, DAC33_FIFO_CTRL_A, fifoctrl_a);
703
704 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a);
705 reg_tmp = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
706 if (dac33->nsample_switch)
707 reg_tmp &= ~DAC33_BCLKON;
708 else
709 reg_tmp |= DAC33_BCLKON;
710 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_B, reg_tmp);
711
712 if (dac33->nsample_switch) {
713 /* 20: BCLK divide ratio */
714 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 3);
715
716 dac33_write16(codec, DAC33_ATHR_MSB,
717 DAC33_THRREG(dac33->alarm_threshold));
718 } else {
719 dac33_write(codec, DAC33_SER_AUDIOIF_CTRL_C, 32);
720 }
721
722 mutex_unlock(&dac33->mutex);
723
724 return 0;
725}
726
727static void dac33_calculate_times(struct snd_pcm_substream *substream)
728{
729 struct snd_soc_pcm_runtime *rtd = substream->private_data;
730 struct snd_soc_device *socdev = rtd->socdev;
731 struct snd_soc_codec *codec = socdev->card->codec;
732 struct tlv320dac33_priv *dac33 = codec->private_data;
733 unsigned int nsample_limit;
734
735 /* Number of samples (16bit, stereo) in one period */
736 dac33->nsample_min = snd_pcm_lib_period_bytes(substream) / 4;
737
738 /* Number of samples (16bit, stereo) in ALSA buffer */
739 dac33->nsample_max = snd_pcm_lib_buffer_bytes(substream) / 4;
740 /* Subtract one period from the total */
741 dac33->nsample_max -= dac33->nsample_min;
742
743 /* Number of samples for LATENCY_TIME_MS / 2 */
744 dac33->alarm_threshold = substream->runtime->rate /
745 (1000 / (LATENCY_TIME_MS / 2));
746
747 /* Find and fix up the lowest nsmaple limit */
748 nsample_limit = substream->runtime->rate / (1000 / LATENCY_TIME_MS);
749
750 if (dac33->nsample_min < nsample_limit)
751 dac33->nsample_min = nsample_limit;
752
753 if (dac33->nsample < dac33->nsample_min)
754 dac33->nsample = dac33->nsample_min;
755
756 /*
757 * Find and fix up the highest nsmaple limit
758 * In order to not overflow the DAC33 buffer substract the
759 * alarm_threshold value from the size of the DAC33 buffer
760 */
761 nsample_limit = DAC33_BUFFER_SIZE_SAMPLES - dac33->alarm_threshold;
762
763 if (dac33->nsample_max > nsample_limit)
764 dac33->nsample_max = nsample_limit;
765
766 if (dac33->nsample > dac33->nsample_max)
767 dac33->nsample = dac33->nsample_max;
768}
769
770static int dac33_pcm_prepare(struct snd_pcm_substream *substream,
771 struct snd_soc_dai *dai)
772{
773 dac33_calculate_times(substream);
774 dac33_prepare_chip(substream);
775
776 return 0;
777}
778
779static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
780 struct snd_soc_dai *dai)
781{
782 struct snd_soc_pcm_runtime *rtd = substream->private_data;
783 struct snd_soc_device *socdev = rtd->socdev;
784 struct snd_soc_codec *codec = socdev->card->codec;
785 struct tlv320dac33_priv *dac33 = codec->private_data;
786 int ret = 0;
787
788 switch (cmd) {
789 case SNDRV_PCM_TRIGGER_START:
790 case SNDRV_PCM_TRIGGER_RESUME:
791 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
792 if (dac33->nsample_switch) {
793 dac33->state = DAC33_PREFILL;
794 queue_work(dac33->dac33_wq, &dac33->work);
795 }
796 break;
797 case SNDRV_PCM_TRIGGER_STOP:
798 case SNDRV_PCM_TRIGGER_SUSPEND:
799 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
800 if (dac33->nsample_switch) {
801 dac33->state = DAC33_FLUSH;
802 queue_work(dac33->dac33_wq, &dac33->work);
803 }
804 break;
805 default:
806 ret = -EINVAL;
807 }
808
809 return ret;
810}
811
812static int dac33_set_dai_sysclk(struct snd_soc_dai *codec_dai,
813 int clk_id, unsigned int freq, int dir)
814{
815 struct snd_soc_codec *codec = codec_dai->codec;
816 struct tlv320dac33_priv *dac33 = codec->private_data;
817 u8 ioc_reg, asrcb_reg;
818
819 ioc_reg = dac33_read_reg_cache(codec, DAC33_INT_OSC_CTRL);
820 asrcb_reg = dac33_read_reg_cache(codec, DAC33_ASRC_CTRL_B);
821 switch (clk_id) {
822 case TLV320DAC33_MCLK:
823 ioc_reg |= DAC33_REFSEL;
824 asrcb_reg |= DAC33_SRCREFSEL;
825 break;
826 case TLV320DAC33_SLEEPCLK:
827 ioc_reg &= ~DAC33_REFSEL;
828 asrcb_reg &= ~DAC33_SRCREFSEL;
829 break;
830 default:
831 dev_err(codec->dev, "Invalid clock ID (%d)\n", clk_id);
832 break;
833 }
834 dac33->refclk = freq;
835
836 dac33_write_reg_cache(codec, DAC33_INT_OSC_CTRL, ioc_reg);
837 dac33_write_reg_cache(codec, DAC33_ASRC_CTRL_B, asrcb_reg);
838
839 return 0;
840}
841
842static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai,
843 unsigned int fmt)
844{
845 struct snd_soc_codec *codec = codec_dai->codec;
846 u8 aictrl_a, aictrl_b;
847
848 aictrl_a = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A);
849 aictrl_b = dac33_read_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B);
850 /* set master/slave audio interface */
851 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
852 case SND_SOC_DAIFMT_CBM_CFM:
853 /* Codec Master */
854 aictrl_a |= (DAC33_MSBCLK | DAC33_MSWCLK);
855 break;
856 case SND_SOC_DAIFMT_CBS_CFS:
857 /* Codec Slave */
858 aictrl_a &= ~(DAC33_MSBCLK | DAC33_MSWCLK);
859 break;
860 default:
861 return -EINVAL;
862 }
863
864 aictrl_a &= ~DAC33_AFMT_MASK;
865 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
866 case SND_SOC_DAIFMT_I2S:
867 aictrl_a |= DAC33_AFMT_I2S;
868 break;
869 case SND_SOC_DAIFMT_DSP_A:
870 aictrl_a |= DAC33_AFMT_DSP;
871 aictrl_b &= ~DAC33_DATA_DELAY_MASK;
872 aictrl_b |= DAC33_DATA_DELAY(1); /* 1 bit delay */
873 break;
874 case SND_SOC_DAIFMT_DSP_B:
875 aictrl_a |= DAC33_AFMT_DSP;
876 aictrl_b &= ~DAC33_DATA_DELAY_MASK; /* No delay */
877 break;
878 case SND_SOC_DAIFMT_RIGHT_J:
879 aictrl_a |= DAC33_AFMT_RIGHT_J;
880 break;
881 case SND_SOC_DAIFMT_LEFT_J:
882 aictrl_a |= DAC33_AFMT_LEFT_J;
883 break;
884 default:
885 dev_err(codec->dev, "Unsupported format (%u)\n",
886 fmt & SND_SOC_DAIFMT_FORMAT_MASK);
887 return -EINVAL;
888 }
889
890 dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_A, aictrl_a);
891 dac33_write_reg_cache(codec, DAC33_SER_AUDIOIF_CTRL_B, aictrl_b);
892
893 return 0;
894}
895
896static void dac33_init_chip(struct snd_soc_codec *codec)
897{
898 /* 44-46: DAC Control Registers */
899 /* A : DAC sample rate Fsref/1.5 */
900 dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(1));
901 /* B : DAC src=normal, not muted */
902 dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT |
903 DAC33_DACSRCL_LEFT);
904 /* C : (defaults) */
905 dac33_write(codec, DAC33_DAC_CTRL_C, 0x00);
906
907 /* 64-65 : L&R DAC power control
908 Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/
909 dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
910 dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2));
911
912 /* 73 : volume soft stepping control,
913 clock source = internal osc (?) */
914 dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN);
915
916 /* 66 : LOP/LOM Modes */
917 dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff);
918
919 /* 68 : LOM inverted from LOP */
920 dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2));
921
922 dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB);
923}
924
925static int dac33_soc_probe(struct platform_device *pdev)
926{
927 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
928 struct snd_soc_codec *codec;
929 struct tlv320dac33_priv *dac33;
930 int ret = 0;
931
932 BUG_ON(!tlv320dac33_codec);
933
934 codec = tlv320dac33_codec;
935 socdev->card->codec = codec;
936 dac33 = codec->private_data;
937
938 /* Power up the codec */
939 dac33_hard_power(codec, 1);
940 /* Set default configuration */
941 dac33_init_chip(codec);
942
943 /* register pcms */
944 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
945 if (ret < 0) {
946 dev_err(codec->dev, "failed to create pcms\n");
947 goto pcm_err;
948 }
949
950 snd_soc_add_controls(codec, dac33_snd_controls,
951 ARRAY_SIZE(dac33_snd_controls));
952 /* Only add the nSample controls, if we have valid IRQ number */
953 if (dac33->irq >= 0)
954 snd_soc_add_controls(codec, dac33_nsample_snd_controls,
955 ARRAY_SIZE(dac33_nsample_snd_controls));
956
957 dac33_add_widgets(codec);
958
959 /* power on device */
960 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
961
962 return 0;
963
964pcm_err:
965 dac33_hard_power(codec, 0);
966 return ret;
967}
968
969static int dac33_soc_remove(struct platform_device *pdev)
970{
971 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
972 struct snd_soc_codec *codec = socdev->card->codec;
973
974 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
975
976 snd_soc_free_pcms(socdev);
977 snd_soc_dapm_free(socdev);
978
979 return 0;
980}
981
982static int dac33_soc_suspend(struct platform_device *pdev, pm_message_t state)
983{
984 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
985 struct snd_soc_codec *codec = socdev->card->codec;
986
987 dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
988
989 return 0;
990}
991
992static int dac33_soc_resume(struct platform_device *pdev)
993{
994 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
995 struct snd_soc_codec *codec = socdev->card->codec;
996
997 dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
998 dac33_set_bias_level(codec, codec->suspend_bias_level);
999
1000 return 0;
1001}
1002
1003struct snd_soc_codec_device soc_codec_dev_tlv320dac33 = {
1004 .probe = dac33_soc_probe,
1005 .remove = dac33_soc_remove,
1006 .suspend = dac33_soc_suspend,
1007 .resume = dac33_soc_resume,
1008};
1009EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33);
1010
1011#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
1012 SNDRV_PCM_RATE_48000)
1013#define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE
1014
1015static struct snd_soc_dai_ops dac33_dai_ops = {
1016 .shutdown = dac33_shutdown,
1017 .hw_params = dac33_hw_params,
1018 .prepare = dac33_pcm_prepare,
1019 .trigger = dac33_pcm_trigger,
1020 .set_sysclk = dac33_set_dai_sysclk,
1021 .set_fmt = dac33_set_dai_fmt,
1022};
1023
1024struct snd_soc_dai dac33_dai = {
1025 .name = "tlv320dac33",
1026 .playback = {
1027 .stream_name = "Playback",
1028 .channels_min = 2,
1029 .channels_max = 2,
1030 .rates = DAC33_RATES,
1031 .formats = DAC33_FORMATS,},
1032 .ops = &dac33_dai_ops,
1033};
1034EXPORT_SYMBOL_GPL(dac33_dai);
1035
1036static int dac33_i2c_probe(struct i2c_client *client,
1037 const struct i2c_device_id *id)
1038{
1039 struct tlv320dac33_platform_data *pdata;
1040 struct tlv320dac33_priv *dac33;
1041 struct snd_soc_codec *codec;
1042 int ret = 0;
1043
1044 if (client->dev.platform_data == NULL) {
1045 dev_err(&client->dev, "Platform data not set\n");
1046 return -ENODEV;
1047 }
1048 pdata = client->dev.platform_data;
1049
1050 dac33 = kzalloc(sizeof(struct tlv320dac33_priv), GFP_KERNEL);
1051 if (dac33 == NULL)
1052 return -ENOMEM;
1053
1054 codec = &dac33->codec;
1055 codec->private_data = dac33;
1056 codec->control_data = client;
1057
1058 mutex_init(&codec->mutex);
1059 mutex_init(&dac33->mutex);
1060 INIT_LIST_HEAD(&codec->dapm_widgets);
1061 INIT_LIST_HEAD(&codec->dapm_paths);
1062
1063 codec->name = "tlv320dac33";
1064 codec->owner = THIS_MODULE;
1065 codec->read = dac33_read_reg_cache;
1066 codec->write = dac33_write_locked;
1067 codec->hw_write = (hw_write_t) i2c_master_send;
1068 codec->bias_level = SND_SOC_BIAS_OFF;
1069 codec->set_bias_level = dac33_set_bias_level;
1070 codec->dai = &dac33_dai;
1071 codec->num_dai = 1;
1072 codec->reg_cache_size = ARRAY_SIZE(dac33_reg);
1073 codec->reg_cache = kmemdup(dac33_reg, ARRAY_SIZE(dac33_reg),
1074 GFP_KERNEL);
1075 if (codec->reg_cache == NULL) {
1076 ret = -ENOMEM;
1077 goto error_reg;
1078 }
1079
1080 i2c_set_clientdata(client, dac33);
1081
1082 dac33->power_gpio = pdata->power_gpio;
1083 dac33->irq = client->irq;
1084 dac33->nsample = NSAMPLE_MAX;
1085 /* Disable FIFO use by default */
1086 dac33->nsample_switch = 0;
1087
1088 tlv320dac33_codec = codec;
1089
1090 codec->dev = &client->dev;
1091 dac33_dai.dev = codec->dev;
1092
1093 /* Check if the reset GPIO number is valid and request it */
1094 if (dac33->power_gpio >= 0) {
1095 ret = gpio_request(dac33->power_gpio, "tlv320dac33 reset");
1096 if (ret < 0) {
1097 dev_err(codec->dev,
1098 "Failed to request reset GPIO (%d)\n",
1099 dac33->power_gpio);
1100 snd_soc_unregister_dai(&dac33_dai);
1101 snd_soc_unregister_codec(codec);
1102 goto error_gpio;
1103 }
1104 gpio_direction_output(dac33->power_gpio, 0);
1105 } else {
1106 dac33->chip_power = 1;
1107 }
1108
1109 /* Check if the IRQ number is valid and request it */
1110 if (dac33->irq >= 0) {
1111 ret = request_irq(dac33->irq, dac33_interrupt_handler,
1112 IRQF_TRIGGER_RISING | IRQF_DISABLED,
1113 codec->name, codec);
1114 if (ret < 0) {
1115 dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
1116 dac33->irq, ret);
1117 dac33->irq = -1;
1118 }
1119 if (dac33->irq != -1) {
1120 /* Setup work queue */
1121 dac33->dac33_wq =
1122 create_singlethread_workqueue("tlv320dac33");
1123 if (dac33->dac33_wq == NULL) {
1124 free_irq(dac33->irq, &dac33->codec);
1125 ret = -ENOMEM;
1126 goto error_wq;
1127 }
1128
1129 INIT_WORK(&dac33->work, dac33_work);
1130 }
1131 }
1132
1133 ret = snd_soc_register_codec(codec);
1134 if (ret != 0) {
1135 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1136 goto error_codec;
1137 }
1138
1139 ret = snd_soc_register_dai(&dac33_dai);
1140 if (ret != 0) {
1141 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1142 snd_soc_unregister_codec(codec);
1143 goto error_codec;
1144 }
1145
1146 /* Shut down the codec for now */
1147 dac33_hard_power(codec, 0);
1148
1149 return ret;
1150
1151error_codec:
1152 if (dac33->irq >= 0) {
1153 free_irq(dac33->irq, &dac33->codec);
1154 destroy_workqueue(dac33->dac33_wq);
1155 }
1156error_wq:
1157 if (dac33->power_gpio >= 0)
1158 gpio_free(dac33->power_gpio);
1159error_gpio:
1160 kfree(codec->reg_cache);
1161error_reg:
1162 tlv320dac33_codec = NULL;
1163 kfree(dac33);
1164
1165 return ret;
1166}
1167
1168static int dac33_i2c_remove(struct i2c_client *client)
1169{
1170 struct tlv320dac33_priv *dac33;
1171
1172 dac33 = i2c_get_clientdata(client);
1173 dac33_hard_power(&dac33->codec, 0);
1174
1175 if (dac33->power_gpio >= 0)
1176 gpio_free(dac33->power_gpio);
1177 if (dac33->irq >= 0)
1178 free_irq(dac33->irq, &dac33->codec);
1179
1180 destroy_workqueue(dac33->dac33_wq);
1181 snd_soc_unregister_dai(&dac33_dai);
1182 snd_soc_unregister_codec(&dac33->codec);
1183 kfree(dac33->codec.reg_cache);
1184 kfree(dac33);
1185 tlv320dac33_codec = NULL;
1186
1187 return 0;
1188}
1189
1190static const struct i2c_device_id tlv320dac33_i2c_id[] = {
1191 {
1192 .name = "tlv320dac33",
1193 .driver_data = 0,
1194 },
1195 { },
1196};
1197
1198static struct i2c_driver tlv320dac33_i2c_driver = {
1199 .driver = {
1200 .name = "tlv320dac33",
1201 .owner = THIS_MODULE,
1202 },
1203 .probe = dac33_i2c_probe,
1204 .remove = __devexit_p(dac33_i2c_remove),
1205 .id_table = tlv320dac33_i2c_id,
1206};
1207
1208static int __init dac33_module_init(void)
1209{
1210 int r;
1211 r = i2c_add_driver(&tlv320dac33_i2c_driver);
1212 if (r < 0) {
1213 printk(KERN_ERR "DAC33: driver registration failed\n");
1214 return r;
1215 }
1216 return 0;
1217}
1218module_init(dac33_module_init);
1219
1220static void __exit dac33_module_exit(void)
1221{
1222 i2c_del_driver(&tlv320dac33_i2c_driver);
1223}
1224module_exit(dac33_module_exit);
1225
1226
1227MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver");
1228MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@nokia.com>");
1229MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320dac33.h b/sound/soc/codecs/tlv320dac33.h
new file mode 100644
index 000000000000..eb8ae07f0bd2
--- /dev/null
+++ b/sound/soc/codecs/tlv320dac33.h
@@ -0,0 +1,267 @@
1/*
2 * ALSA SoC Texas Instruments TLV320DAC33 codec driver
3 *
4 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
5 *
6 * Copyright: (C) 2009 Nokia Corporation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __TLV320DAC33_H
25#define __TLV320DAC33_H
26
27#define DAC33_PAGE_SELECT 0x00
28#define DAC33_PWR_CTRL 0x01
29#define DAC33_PLL_CTRL_A 0x02
30#define DAC33_PLL_CTRL_B 0x03
31#define DAC33_PLL_CTRL_C 0x04
32#define DAC33_PLL_CTRL_D 0x05
33#define DAC33_PLL_CTRL_E 0x06
34#define DAC33_INT_OSC_CTRL 0x07
35#define DAC33_INT_OSC_FREQ_RAT_A 0x08
36#define DAC33_INT_OSC_FREQ_RAT_B 0x09
37#define DAC33_INT_OSC_DAC_RATIO_SET 0x0A
38#define DAC33_CALIB_TIME 0x0B
39#define DAC33_INT_OSC_CTRL_B 0x0C
40#define DAC33_INT_OSC_CTRL_C 0x0D
41#define DAC33_INT_OSC_STATUS 0x0E
42#define DAC33_INT_OSC_DAC_RATIO_READ 0x0F
43#define DAC33_INT_OSC_FREQ_RAT_READ_A 0x10
44#define DAC33_INT_OSC_FREQ_RAT_READ_B 0x11
45#define DAC33_SER_AUDIOIF_CTRL_A 0x12
46#define DAC33_SER_AUDIOIF_CTRL_B 0x13
47#define DAC33_SER_AUDIOIF_CTRL_C 0x14
48#define DAC33_FIFO_CTRL_A 0x15
49#define DAC33_UTHR_MSB 0x16
50#define DAC33_UTHR_LSB 0x17
51#define DAC33_ATHR_MSB 0x18
52#define DAC33_ATHR_LSB 0x19
53#define DAC33_LTHR_MSB 0x1A
54#define DAC33_LTHR_LSB 0x1B
55#define DAC33_PREFILL_MSB 0x1C
56#define DAC33_PREFILL_LSB 0x1D
57#define DAC33_NSAMPLE_MSB 0x1E
58#define DAC33_NSAMPLE_LSB 0x1F
59#define DAC33_FIFO_WPTR_MSB 0x20
60#define DAC33_FIFO_WPTR_LSB 0x21
61#define DAC33_FIFO_RPTR_MSB 0x22
62#define DAC33_FIFO_RPTR_LSB 0x23
63#define DAC33_FIFO_DEPTH_MSB 0x24
64#define DAC33_FIFO_DEPTH_LSB 0x25
65#define DAC33_SAMPLES_REMAINING_MSB 0x26
66#define DAC33_SAMPLES_REMAINING_LSB 0x27
67#define DAC33_FIFO_IRQ_FLAG 0x28
68#define DAC33_FIFO_IRQ_MASK 0x29
69#define DAC33_FIFO_IRQ_MODE_A 0x2A
70#define DAC33_FIFO_IRQ_MODE_B 0x2B
71#define DAC33_DAC_CTRL_A 0x2C
72#define DAC33_DAC_CTRL_B 0x2D
73#define DAC33_DAC_CTRL_C 0x2E
74#define DAC33_LDAC_DIG_VOL_CTRL 0x2F
75#define DAC33_RDAC_DIG_VOL_CTRL 0x30
76#define DAC33_DAC_STATUS_FLAGS 0x31
77#define DAC33_ASRC_CTRL_A 0x32
78#define DAC33_ASRC_CTRL_B 0x33
79#define DAC33_SRC_REF_CLK_RATIO_A 0x34
80#define DAC33_SRC_REF_CLK_RATIO_B 0x35
81#define DAC33_SRC_EST_REF_CLK_RATIO_A 0x36
82#define DAC33_SRC_EST_REF_CLK_RATIO_B 0x37
83#define DAC33_INTP_CTRL_A 0x38
84#define DAC33_INTP_CTRL_B 0x39
85/* Registers 0x3A - 0x3F Reserved */
86#define DAC33_LDAC_PWR_CTRL 0x40
87#define DAC33_RDAC_PWR_CTRL 0x41
88#define DAC33_OUT_AMP_CM_CTRL 0x42
89#define DAC33_OUT_AMP_PWR_CTRL 0x43
90#define DAC33_OUT_AMP_CTRL 0x44
91#define DAC33_LINEL_TO_LLO_VOL 0x45
92/* Registers 0x45 - 0x47 Reserved */
93#define DAC33_LINER_TO_RLO_VOL 0x48
94#define DAC33_ANA_VOL_SOFT_STEP_CTRL 0x49
95#define DAC33_OSC_TRIM 0x4A
96/* Registers 0x4B - 0x7C Reserved */
97#define DAC33_DEVICE_ID_MSB 0x7D
98#define DAC33_DEVICE_ID_LSB 0x7E
99#define DAC33_DEVICE_REV_ID 0x7F
100
101#define DAC33_CACHEREGNUM 128
102
103/* Bit definitions */
104
105/* DAC33_PWR_CTRL (0x01) */
106#define DAC33_DACRPDNB (0x01 << 0)
107#define DAC33_DACLPDNB (0x01 << 1)
108#define DAC33_OSCPDNB (0x01 << 2)
109#define DAC33_PLLPDNB (0x01 << 3)
110#define DAC33_PDNALLB (0x01 << 4)
111#define DAC33_SOFT_RESET (0x01 << 7)
112
113/* DAC33_INT_OSC_CTRL (0x07) */
114#define DAC33_REFSEL (0x01 << 1)
115
116/* DAC33_INT_OSC_CTRL_B (0x0C) */
117#define DAC33_ADJSTEP(x) (x << 0)
118#define DAC33_ADJTHRSHLD(x) (x << 4)
119
120/* DAC33_INT_OSC_CTRL_C (0x0D) */
121#define DAC33_REFDIV(x) (x << 4)
122
123/* DAC33_INT_OSC_STATUS (0x0E) */
124#define DAC33_OSCSTATUS_IDLE_CALIB (0x00)
125#define DAC33_OSCSTATUS_NORMAL (0x01)
126#define DAC33_OSCSTATUS_ADJUSTMENT (0x03)
127#define DAC33_OSCSTATUS_NOT_USED (0x02)
128
129/* DAC33_SER_AUDIOIF_CTRL_A (0x12) */
130#define DAC33_MSWCLK (0x01 << 0)
131#define DAC33_MSBCLK (0x01 << 1)
132#define DAC33_AFMT_MASK (0x03 << 2)
133#define DAC33_AFMT_I2S (0x00 << 2)
134#define DAC33_AFMT_DSP (0x01 << 2)
135#define DAC33_AFMT_RIGHT_J (0x02 << 2)
136#define DAC33_AFMT_LEFT_J (0x03 << 2)
137#define DAC33_WLEN_MASK (0x03 << 4)
138#define DAC33_WLEN_16 (0x00 << 4)
139#define DAC33_WLEN_20 (0x01 << 4)
140#define DAC33_WLEN_24 (0x02 << 4)
141#define DAC33_WLEN_32 (0x03 << 4)
142#define DAC33_NCYCL_MASK (0x03 << 6)
143#define DAC33_NCYCL_16 (0x00 << 6)
144#define DAC33_NCYCL_20 (0x01 << 6)
145#define DAC33_NCYCL_24 (0x02 << 6)
146#define DAC33_NCYCL_32 (0x03 << 6)
147
148/* DAC33_SER_AUDIOIF_CTRL_B (0x13) */
149#define DAC33_DATA_DELAY_MASK (0x03 << 2)
150#define DAC33_DATA_DELAY(x) (x << 2)
151#define DAC33_BCLKON (0x01 << 5)
152
153/* DAC33_FIFO_CTRL_A (0x15) */
154#define DAC33_WIDTH (0x01 << 0)
155#define DAC33_FBYPAS (0x01 << 1)
156#define DAC33_FAUTO (0x01 << 2)
157#define DAC33_FIFOFLUSH (0x01 << 3)
158
159/*
160 * UTHR, ATHR, LTHR, PREFILL, NSAMPLE (0x16 - 0x1F)
161 * 13-bit values
162*/
163#define DAC33_THRREG(x) (((x) & 0x1FFF) << 3)
164
165/* DAC33_FIFO_IRQ_MASK (0x29) */
166#define DAC33_MNS (0x01 << 0)
167#define DAC33_MPS (0x01 << 1)
168#define DAC33_MAT (0x01 << 2)
169#define DAC33_MLT (0x01 << 3)
170#define DAC33_MUT (0x01 << 4)
171#define DAC33_MUF (0x01 << 5)
172#define DAC33_MOF (0x01 << 6)
173
174#define DAC33_FIFO_IRQ_MODE_MASK (0x03)
175#define DAC33_FIFO_IRQ_MODE_RISING (0x00)
176#define DAC33_FIFO_IRQ_MODE_FALLING (0x01)
177#define DAC33_FIFO_IRQ_MODE_LEVEL (0x02)
178#define DAC33_FIFO_IRQ_MODE_EDGE (0x03)
179
180/* DAC33_FIFO_IRQ_MODE_A (0x2A) */
181#define DAC33_UTM(x) (x << 0)
182#define DAC33_UFM(x) (x << 2)
183#define DAC33_OFM(x) (x << 4)
184
185/* DAC33_FIFO_IRQ_MODE_B (0x2B) */
186#define DAC33_NSM(x) (x << 0)
187#define DAC33_PSM(x) (x << 2)
188#define DAC33_ATM(x) (x << 4)
189#define DAC33_LTM(x) (x << 6)
190
191/* DAC33_DAC_CTRL_A (0x2C) */
192#define DAC33_DACRATE(x) (x << 0)
193#define DAC33_DACDUAL (0x01 << 4)
194#define DAC33_DACLKSEL_MASK (0x03 << 5)
195#define DAC33_DACLKSEL_INTSOC (0x00 << 5)
196#define DAC33_DACLKSEL_PLL (0x01 << 5)
197#define DAC33_DACLKSEL_MCLK (0x02 << 5)
198#define DAC33_DACLKSEL_BCLK (0x03 << 5)
199
200/* DAC33_DAC_CTRL_B (0x2D) */
201#define DAC33_DACSRCR_MASK (0x03 << 0)
202#define DAC33_DACSRCR_MUTE (0x00 << 0)
203#define DAC33_DACSRCR_RIGHT (0x01 << 0)
204#define DAC33_DACSRCR_LEFT (0x02 << 0)
205#define DAC33_DACSRCR_MONOMIX (0x03 << 0)
206#define DAC33_DACSRCL_MASK (0x03 << 2)
207#define DAC33_DACSRCL_MUTE (0x00 << 2)
208#define DAC33_DACSRCL_LEFT (0x01 << 2)
209#define DAC33_DACSRCL_RIGHT (0x02 << 2)
210#define DAC33_DACSRCL_MONOMIX (0x03 << 2)
211#define DAC33_DVOLSTEP_MASK (0x03 << 4)
212#define DAC33_DVOLSTEP_SS_PERFS (0x00 << 4)
213#define DAC33_DVOLSTEP_SS_PER2FS (0x01 << 4)
214#define DAC33_DVOLSTEP_SS_DISABLED (0x02 << 4)
215#define DAC33_DVOLCTRL_MASK (0x03 << 6)
216#define DAC33_DVOLCTRL_LR_INDEPENDENT1 (0x00 << 6)
217#define DAC33_DVOLCTRL_LR_RIGHT_CONTROL (0x01 << 6)
218#define DAC33_DVOLCTRL_LR_LEFT_CONTROL (0x02 << 6)
219#define DAC33_DVOLCTRL_LR_INDEPENDENT2 (0x03 << 6)
220
221/* DAC33_DAC_CTRL_C (0x2E) */
222#define DAC33_DEEMENR (0x01 << 0)
223#define DAC33_EFFENR (0x01 << 1)
224#define DAC33_DEEMENL (0x01 << 2)
225#define DAC33_EFFENL (0x01 << 3)
226#define DAC33_EN3D (0x01 << 4)
227#define DAC33_RESYNMUTE (0x01 << 5)
228#define DAC33_RESYNEN (0x01 << 6)
229
230/* DAC33_ASRC_CTRL_A (0x32) */
231#define DAC33_SRCBYP (0x01 << 0)
232#define DAC33_SRCLKSEL_MASK (0x03 << 1)
233#define DAC33_SRCLKSEL_INTSOC (0x00 << 1)
234#define DAC33_SRCLKSEL_PLL (0x01 << 1)
235#define DAC33_SRCLKSEL_MCLK (0x02 << 1)
236#define DAC33_SRCLKSEL_BCLK (0x03 << 1)
237#define DAC33_SRCLKDIV(x) (x << 3)
238
239/* DAC33_ASRC_CTRL_B (0x33) */
240#define DAC33_SRCSETUP(x) (x << 0)
241#define DAC33_SRCREFSEL (0x01 << 4)
242#define DAC33_SRCREFDIV(x) (x << 5)
243
244/* DAC33_INTP_CTRL_A (0x38) */
245#define DAC33_INTPSEL (0x01 << 0)
246#define DAC33_INTPM_MASK (0x03 << 1)
247#define DAC33_INTPM_ALOW_OPENDRAIN (0x00 << 1)
248#define DAC33_INTPM_ALOW (0x01 << 1)
249#define DAC33_INTPM_AHIGH (0x02 << 1)
250
251/* DAC33_LDAC_PWR_CTRL (0x40) */
252/* DAC33_RDAC_PWR_CTRL (0x41) */
253#define DAC33_DACLRNUM (0x01 << 2)
254#define DAC33_LROUT_GAIN(x) (x << 0)
255
256/* DAC33_ANA_VOL_SOFT_STEP_CTRL (0x49) */
257#define DAC33_VOLCLKSEL (0x01 << 0)
258#define DAC33_VOLCLKEN (0x01 << 1)
259#define DAC33_VOLBYPASS (0x01 << 2)
260
261#define TLV320DAC33_MCLK 0
262#define TLV320DAC33_SLEEPCLK 1
263
264extern struct snd_soc_dai dac33_dai;
265extern struct snd_soc_codec_device soc_codec_dev_tlv320dac33;
266
267#endif /* __TLV320DAC33_H */
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
new file mode 100644
index 000000000000..6b650c1aa3d1
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -0,0 +1,463 @@
1/*
2 * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
3 *
4 * Copyright (C) Nokia Corporation
5 *
6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 */
22
23#include <linux/module.h>
24#include <linux/errno.h>
25#include <linux/device.h>
26#include <linux/i2c.h>
27#include <linux/gpio.h>
28#include <sound/tpa6130a2-plat.h>
29#include <sound/soc.h>
30#include <sound/soc-dapm.h>
31#include <sound/tlv.h>
32
33#include "tpa6130a2.h"
34
35static struct i2c_client *tpa6130a2_client;
36
37/* This struct is used to save the context */
38struct tpa6130a2_data {
39 struct mutex mutex;
40 unsigned char regs[TPA6130A2_CACHEREGNUM];
41 int power_gpio;
42 unsigned char power_state;
43};
44
45static int tpa6130a2_i2c_read(int reg)
46{
47 struct tpa6130a2_data *data;
48 int val;
49
50 BUG_ON(tpa6130a2_client == NULL);
51 data = i2c_get_clientdata(tpa6130a2_client);
52
53 /* If powered off, return the cached value */
54 if (data->power_state) {
55 val = i2c_smbus_read_byte_data(tpa6130a2_client, reg);
56 if (val < 0)
57 dev_err(&tpa6130a2_client->dev, "Read failed\n");
58 else
59 data->regs[reg] = val;
60 } else {
61 val = data->regs[reg];
62 }
63
64 return val;
65}
66
67static int tpa6130a2_i2c_write(int reg, u8 value)
68{
69 struct tpa6130a2_data *data;
70 int val = 0;
71
72 BUG_ON(tpa6130a2_client == NULL);
73 data = i2c_get_clientdata(tpa6130a2_client);
74
75 if (data->power_state) {
76 val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value);
77 if (val < 0)
78 dev_err(&tpa6130a2_client->dev, "Write failed\n");
79 }
80
81 /* Either powered on or off, we save the context */
82 data->regs[reg] = value;
83
84 return val;
85}
86
87static u8 tpa6130a2_read(int reg)
88{
89 struct tpa6130a2_data *data;
90
91 BUG_ON(tpa6130a2_client == NULL);
92 data = i2c_get_clientdata(tpa6130a2_client);
93
94 return data->regs[reg];
95}
96
97static void tpa6130a2_initialize(void)
98{
99 struct tpa6130a2_data *data;
100 int i;
101
102 BUG_ON(tpa6130a2_client == NULL);
103 data = i2c_get_clientdata(tpa6130a2_client);
104
105 for (i = 1; i < TPA6130A2_REG_VERSION; i++)
106 tpa6130a2_i2c_write(i, data->regs[i]);
107}
108
109static void tpa6130a2_power(int power)
110{
111 struct tpa6130a2_data *data;
112 u8 val;
113
114 BUG_ON(tpa6130a2_client == NULL);
115 data = i2c_get_clientdata(tpa6130a2_client);
116
117 mutex_lock(&data->mutex);
118 if (power) {
119 /* Power on */
120 if (data->power_gpio >= 0) {
121 gpio_set_value(data->power_gpio, 1);
122 data->power_state = 1;
123 tpa6130a2_initialize();
124 }
125 /* Clear SWS */
126 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
127 val &= ~TPA6130A2_SWS;
128 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
129 } else {
130 /* set SWS */
131 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
132 val |= TPA6130A2_SWS;
133 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
134 /* Power off */
135 if (data->power_gpio >= 0) {
136 gpio_set_value(data->power_gpio, 0);
137 data->power_state = 0;
138 }
139 }
140 mutex_unlock(&data->mutex);
141}
142
143static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
144 struct snd_ctl_elem_value *ucontrol)
145{
146 struct soc_mixer_control *mc =
147 (struct soc_mixer_control *)kcontrol->private_value;
148 struct tpa6130a2_data *data;
149 unsigned int reg = mc->reg;
150 unsigned int shift = mc->shift;
151 unsigned int mask = mc->max;
152 unsigned int invert = mc->invert;
153
154 BUG_ON(tpa6130a2_client == NULL);
155 data = i2c_get_clientdata(tpa6130a2_client);
156
157 mutex_lock(&data->mutex);
158
159 ucontrol->value.integer.value[0] =
160 (tpa6130a2_read(reg) >> shift) & mask;
161
162 if (invert)
163 ucontrol->value.integer.value[0] =
164 mask - ucontrol->value.integer.value[0];
165
166 mutex_unlock(&data->mutex);
167 return 0;
168}
169
170static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol,
171 struct snd_ctl_elem_value *ucontrol)
172{
173 struct soc_mixer_control *mc =
174 (struct soc_mixer_control *)kcontrol->private_value;
175 struct tpa6130a2_data *data;
176 unsigned int reg = mc->reg;
177 unsigned int shift = mc->shift;
178 unsigned int mask = mc->max;
179 unsigned int invert = mc->invert;
180 unsigned int val = (ucontrol->value.integer.value[0] & mask);
181 unsigned int val_reg;
182
183 BUG_ON(tpa6130a2_client == NULL);
184 data = i2c_get_clientdata(tpa6130a2_client);
185
186 if (invert)
187 val = mask - val;
188
189 mutex_lock(&data->mutex);
190
191 val_reg = tpa6130a2_read(reg);
192 if (((val_reg >> shift) & mask) == val) {
193 mutex_unlock(&data->mutex);
194 return 0;
195 }
196
197 val_reg &= ~(mask << shift);
198 val_reg |= val << shift;
199 tpa6130a2_i2c_write(reg, val_reg);
200
201 mutex_unlock(&data->mutex);
202
203 return 1;
204}
205
206/*
207 * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
208 * down in gain.
209 */
210static const unsigned int tpa6130_tlv[] = {
211 TLV_DB_RANGE_HEAD(10),
212 0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
213 2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
214 4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
215 6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
216 8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
217 10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
218 12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
219 14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
220 21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
221 38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0),
222};
223
224static const struct snd_kcontrol_new tpa6130a2_controls[] = {
225 SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume",
226 TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
227 tpa6130a2_get_reg, tpa6130a2_set_reg,
228 tpa6130_tlv),
229};
230
231/*
232 * Enable or disable channel (left or right)
233 * The bit number for mute and amplifier are the same per channel:
234 * bit 6: Right channel
235 * bit 7: Left channel
236 * in both registers.
237 */
238static void tpa6130a2_channel_enable(u8 channel, int enable)
239{
240 struct tpa6130a2_data *data;
241 u8 val;
242
243 BUG_ON(tpa6130a2_client == NULL);
244 data = i2c_get_clientdata(tpa6130a2_client);
245
246 if (enable) {
247 /* Enable channel */
248 /* Enable amplifier */
249 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
250 val |= channel;
251 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
252
253 /* Unmute channel */
254 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
255 val &= ~channel;
256 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
257 } else {
258 /* Disable channel */
259 /* Mute channel */
260 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
261 val |= channel;
262 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
263
264 /* Disable amplifier */
265 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
266 val &= ~channel;
267 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
268 }
269}
270
271static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w,
272 struct snd_kcontrol *kcontrol, int event)
273{
274 switch (event) {
275 case SND_SOC_DAPM_POST_PMU:
276 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1);
277 break;
278 case SND_SOC_DAPM_POST_PMD:
279 tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0);
280 break;
281 }
282 return 0;
283}
284
285static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
286 struct snd_kcontrol *kcontrol, int event)
287{
288 switch (event) {
289 case SND_SOC_DAPM_POST_PMU:
290 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1);
291 break;
292 case SND_SOC_DAPM_POST_PMD:
293 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0);
294 break;
295 }
296 return 0;
297}
298
299static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event)
301{
302 switch (event) {
303 case SND_SOC_DAPM_POST_PMU:
304 tpa6130a2_power(1);
305 break;
306 case SND_SOC_DAPM_POST_PMD:
307 tpa6130a2_power(0);
308 break;
309 }
310 return 0;
311}
312
313static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
314 SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM,
315 0, 0, NULL, 0, tpa6130a2_left_event,
316 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
317 SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM,
318 0, 0, NULL, 0, tpa6130a2_right_event,
319 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
320 SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM,
321 0, 0, tpa6130a2_supply_event,
322 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
323 /* Outputs */
324 SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL),
325 SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL),
326};
327
328static const struct snd_soc_dapm_route audio_map[] = {
329 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"},
330 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"},
331
332 {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"},
333 {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"},
334};
335
336int tpa6130a2_add_controls(struct snd_soc_codec *codec)
337{
338 snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
339 ARRAY_SIZE(tpa6130a2_dapm_widgets));
340
341 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
342
343 return snd_soc_add_controls(codec, tpa6130a2_controls,
344 ARRAY_SIZE(tpa6130a2_controls));
345
346}
347EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
348
349static int tpa6130a2_probe(struct i2c_client *client,
350 const struct i2c_device_id *id)
351{
352 struct device *dev;
353 struct tpa6130a2_data *data;
354 struct tpa6130a2_platform_data *pdata;
355 int ret;
356
357 dev = &client->dev;
358
359 if (client->dev.platform_data == NULL) {
360 dev_err(dev, "Platform data not set\n");
361 dump_stack();
362 return -ENODEV;
363 }
364
365 data = kzalloc(sizeof(*data), GFP_KERNEL);
366 if (data == NULL) {
367 dev_err(dev, "Can not allocate memory\n");
368 return -ENOMEM;
369 }
370
371 tpa6130a2_client = client;
372
373 i2c_set_clientdata(tpa6130a2_client, data);
374
375 pdata = client->dev.platform_data;
376 data->power_gpio = pdata->power_gpio;
377
378 mutex_init(&data->mutex);
379
380 /* Set default register values */
381 data->regs[TPA6130A2_REG_CONTROL] = TPA6130A2_SWS;
382 data->regs[TPA6130A2_REG_VOL_MUTE] = TPA6130A2_MUTE_R |
383 TPA6130A2_MUTE_L;
384
385 if (data->power_gpio >= 0) {
386 ret = gpio_request(data->power_gpio, "tpa6130a2 enable");
387 if (ret < 0) {
388 dev_err(dev, "Failed to request power GPIO (%d)\n",
389 data->power_gpio);
390 goto fail;
391 }
392 gpio_direction_output(data->power_gpio, 0);
393 } else {
394 data->power_state = 1;
395 tpa6130a2_initialize();
396 }
397
398 tpa6130a2_power(1);
399
400 /* Read version */
401 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
402 TPA6130A2_VERSION_MASK;
403 if ((ret != 1) && (ret != 2))
404 dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
405
406 /* Disable the chip */
407 tpa6130a2_power(0);
408
409 return 0;
410fail:
411 kfree(data);
412 i2c_set_clientdata(tpa6130a2_client, NULL);
413 tpa6130a2_client = NULL;
414
415 return ret;
416}
417
418static int tpa6130a2_remove(struct i2c_client *client)
419{
420 struct tpa6130a2_data *data = i2c_get_clientdata(client);
421
422 tpa6130a2_power(0);
423
424 if (data->power_gpio >= 0)
425 gpio_free(data->power_gpio);
426 kfree(data);
427 tpa6130a2_client = NULL;
428
429 return 0;
430}
431
432static const struct i2c_device_id tpa6130a2_id[] = {
433 { "tpa6130a2", 0 },
434 { }
435};
436MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
437
438static struct i2c_driver tpa6130a2_i2c_driver = {
439 .driver = {
440 .name = "tpa6130a2",
441 .owner = THIS_MODULE,
442 },
443 .probe = tpa6130a2_probe,
444 .remove = __devexit_p(tpa6130a2_remove),
445 .id_table = tpa6130a2_id,
446};
447
448static int __init tpa6130a2_init(void)
449{
450 return i2c_add_driver(&tpa6130a2_i2c_driver);
451}
452
453static void __exit tpa6130a2_exit(void)
454{
455 i2c_del_driver(&tpa6130a2_i2c_driver);
456}
457
458MODULE_AUTHOR("Peter Ujfalusi");
459MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
460MODULE_LICENSE("GPL");
461
462module_init(tpa6130a2_init);
463module_exit(tpa6130a2_exit);
diff --git a/sound/soc/codecs/tpa6130a2.h b/sound/soc/codecs/tpa6130a2.h
new file mode 100644
index 000000000000..57e867fd86d1
--- /dev/null
+++ b/sound/soc/codecs/tpa6130a2.h
@@ -0,0 +1,61 @@
1/*
2 * ALSA SoC TPA6130A2 amplifier driver
3 *
4 * Copyright (C) Nokia Corporation
5 *
6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA
21 *
22 */
23
24#ifndef __TPA6130A2_H__
25#define __TPA6130A2_H__
26
27/* Register addresses */
28#define TPA6130A2_REG_CONTROL 0x01
29#define TPA6130A2_REG_VOL_MUTE 0x02
30#define TPA6130A2_REG_OUT_IMPEDANCE 0x03
31#define TPA6130A2_REG_VERSION 0x04
32
33#define TPA6130A2_CACHEREGNUM (TPA6130A2_REG_VERSION + 1)
34
35/* Register bits */
36/* TPA6130A2_REG_CONTROL (0x01) */
37#define TPA6130A2_SWS (0x01 << 0)
38#define TPA6130A2_TERMAL (0x01 << 1)
39#define TPA6130A2_MODE(x) (x << 4)
40#define TPA6130A2_MODE_STEREO (0x00)
41#define TPA6130A2_MODE_DUAL_MONO (0x01)
42#define TPA6130A2_MODE_BRIDGE (0x02)
43#define TPA6130A2_MODE_MASK (0x03)
44#define TPA6130A2_HP_EN_R (0x01 << 6)
45#define TPA6130A2_HP_EN_L (0x01 << 7)
46
47/* TPA6130A2_REG_VOL_MUTE (0x02) */
48#define TPA6130A2_VOLUME(x) ((x & 0x3f) << 0)
49#define TPA6130A2_MUTE_R (0x01 << 6)
50#define TPA6130A2_MUTE_L (0x01 << 7)
51
52/* TPA6130A2_REG_OUT_IMPEDANCE (0x03) */
53#define TPA6130A2_HIZ_R (0x01 << 0)
54#define TPA6130A2_HIZ_L (0x01 << 1)
55
56/* TPA6130A2_REG_VERSION (0x04) */
57#define TPA6130A2_VERSION_MASK (0x0f)
58
59extern int tpa6130a2_add_controls(struct snd_soc_codec *codec);
60
61#endif /* __TPA6130A2_H__ */
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 4df7c6c61c76..5f1681f6ca76 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -120,9 +120,10 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
120 120
121/* codec private data */ 121/* codec private data */
122struct twl4030_priv { 122struct twl4030_priv {
123 unsigned int bypass_state; 123 struct snd_soc_codec codec;
124
124 unsigned int codec_powered; 125 unsigned int codec_powered;
125 unsigned int codec_muted; 126 unsigned int apll_enabled;
126 127
127 struct snd_pcm_substream *master_substream; 128 struct snd_pcm_substream *master_substream;
128 struct snd_pcm_substream *slave_substream; 129 struct snd_pcm_substream *slave_substream;
@@ -183,19 +184,20 @@ static int twl4030_write(struct snd_soc_codec *codec,
183static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable) 184static void twl4030_codec_enable(struct snd_soc_codec *codec, int enable)
184{ 185{
185 struct twl4030_priv *twl4030 = codec->private_data; 186 struct twl4030_priv *twl4030 = codec->private_data;
186 u8 mode; 187 int mode;
187 188
188 if (enable == twl4030->codec_powered) 189 if (enable == twl4030->codec_powered)
189 return; 190 return;
190 191
191 mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
192 if (enable) 192 if (enable)
193 mode |= TWL4030_CODECPDZ; 193 mode = twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER);
194 else 194 else
195 mode &= ~TWL4030_CODECPDZ; 195 mode = twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER);
196 196
197 twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode); 197 if (mode >= 0) {
198 twl4030->codec_powered = enable; 198 twl4030_write_reg_cache(codec, TWL4030_REG_CODEC_MODE, mode);
199 twl4030->codec_powered = enable;
200 }
199 201
200 /* REVISIT: this delay is present in TI sample drivers */ 202 /* REVISIT: this delay is present in TI sample drivers */
201 /* but there seems to be no TRM requirement for it */ 203 /* but there seems to be no TRM requirement for it */
@@ -212,31 +214,30 @@ static void twl4030_init_chip(struct snd_soc_codec *codec)
212 214
213 /* set all audio section registers to reasonable defaults */ 215 /* set all audio section registers to reasonable defaults */
214 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++) 216 for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
215 twl4030_write(codec, i, cache[i]); 217 if (i != TWL4030_REG_APLL_CTL)
218 twl4030_write(codec, i, cache[i]);
216 219
217} 220}
218 221
219static void twl4030_codec_mute(struct snd_soc_codec *codec, int mute) 222static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable)
220{ 223{
221 struct twl4030_priv *twl4030 = codec->private_data; 224 struct twl4030_priv *twl4030 = codec->private_data;
222 u8 reg_val; 225 int status;
223 226
224 if (mute == twl4030->codec_muted) 227 if (enable == twl4030->apll_enabled)
225 return; 228 return;
226 229
227 if (mute) { 230 if (enable)
228 /* Disable PLL */
229 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL);
230 reg_val &= ~TWL4030_APLL_EN;
231 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val);
232 } else {
233 /* Enable PLL */ 231 /* Enable PLL */
234 reg_val = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL); 232 status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL);
235 reg_val |= TWL4030_APLL_EN; 233 else
236 twl4030_write(codec, TWL4030_REG_APLL_CTL, reg_val); 234 /* Disable PLL */
237 } 235 status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL);
236
237 if (status >= 0)
238 twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status);
238 239
239 twl4030->codec_muted = mute; 240 twl4030->apll_enabled = enable;
240} 241}
241 242
242static void twl4030_power_up(struct snd_soc_codec *codec) 243static void twl4030_power_up(struct snd_soc_codec *codec)
@@ -613,6 +614,27 @@ static int handsfreerpga_event(struct snd_soc_dapm_widget *w,
613 return 0; 614 return 0;
614} 615}
615 616
617static int vibramux_event(struct snd_soc_dapm_widget *w,
618 struct snd_kcontrol *kcontrol, int event)
619{
620 twl4030_write(w->codec, TWL4030_REG_VIBRA_SET, 0xff);
621 return 0;
622}
623
624static int apll_event(struct snd_soc_dapm_widget *w,
625 struct snd_kcontrol *kcontrol, int event)
626{
627 switch (event) {
628 case SND_SOC_DAPM_PRE_PMU:
629 twl4030_apll_enable(w->codec, 1);
630 break;
631 case SND_SOC_DAPM_POST_PMD:
632 twl4030_apll_enable(w->codec, 0);
633 break;
634 }
635 return 0;
636}
637
616static void headset_ramp(struct snd_soc_codec *codec, int ramp) 638static void headset_ramp(struct snd_soc_codec *codec, int ramp)
617{ 639{
618 struct snd_soc_device *socdev = codec->socdev; 640 struct snd_soc_device *socdev = codec->socdev;
@@ -724,67 +746,6 @@ static int headsetrpga_event(struct snd_soc_dapm_widget *w,
724 return 0; 746 return 0;
725} 747}
726 748
727static int bypass_event(struct snd_soc_dapm_widget *w,
728 struct snd_kcontrol *kcontrol, int event)
729{
730 struct soc_mixer_control *m =
731 (struct soc_mixer_control *)w->kcontrols->private_value;
732 struct twl4030_priv *twl4030 = w->codec->private_data;
733 unsigned char reg, misc;
734
735 reg = twl4030_read_reg_cache(w->codec, m->reg);
736
737 /*
738 * bypass_state[0:3] - analog HiFi bypass
739 * bypass_state[4] - analog voice bypass
740 * bypass_state[5] - digital voice bypass
741 * bypass_state[6:7] - digital HiFi bypass
742 */
743 if (m->reg == TWL4030_REG_VSTPGA) {
744 /* Voice digital bypass */
745 if (reg)
746 twl4030->bypass_state |= (1 << 5);
747 else
748 twl4030->bypass_state &= ~(1 << 5);
749 } else if (m->reg <= TWL4030_REG_ARXR2_APGA_CTL) {
750 /* Analog bypass */
751 if (reg & (1 << m->shift))
752 twl4030->bypass_state |=
753 (1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
754 else
755 twl4030->bypass_state &=
756 ~(1 << (m->reg - TWL4030_REG_ARXL1_APGA_CTL));
757 } else if (m->reg == TWL4030_REG_VDL_APGA_CTL) {
758 /* Analog voice bypass */
759 if (reg & (1 << m->shift))
760 twl4030->bypass_state |= (1 << 4);
761 else
762 twl4030->bypass_state &= ~(1 << 4);
763 } else {
764 /* Digital bypass */
765 if (reg & (0x7 << m->shift))
766 twl4030->bypass_state |= (1 << (m->shift ? 7 : 6));
767 else
768 twl4030->bypass_state &= ~(1 << (m->shift ? 7 : 6));
769 }
770
771 /* Enable master analog loopback mode if any analog switch is enabled*/
772 misc = twl4030_read_reg_cache(w->codec, TWL4030_REG_MISC_SET_1);
773 if (twl4030->bypass_state & 0x1F)
774 misc |= TWL4030_FMLOOP_EN;
775 else
776 misc &= ~TWL4030_FMLOOP_EN;
777 twl4030_write(w->codec, TWL4030_REG_MISC_SET_1, misc);
778
779 if (w->codec->bias_level == SND_SOC_BIAS_STANDBY) {
780 if (twl4030->bypass_state)
781 twl4030_codec_mute(w->codec, 0);
782 else
783 twl4030_codec_mute(w->codec, 1);
784 }
785 return 0;
786}
787
788/* 749/*
789 * Some of the gain controls in TWL (mostly those which are associated with 750 * Some of the gain controls in TWL (mostly those which are associated with
790 * the outputs) are implemented in an interesting way: 751 * the outputs) are implemented in an interesting way:
@@ -1192,32 +1153,28 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1192 SND_SOC_NOPM, 0, 0), 1153 SND_SOC_NOPM, 0, 0),
1193 1154
1194 /* Analog bypasses */ 1155 /* Analog bypasses */
1195 SND_SOC_DAPM_SWITCH_E("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1156 SND_SOC_DAPM_SWITCH("Right1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1196 &twl4030_dapm_abypassr1_control, bypass_event, 1157 &twl4030_dapm_abypassr1_control),
1197 SND_SOC_DAPM_POST_REG), 1158 SND_SOC_DAPM_SWITCH("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0,
1198 SND_SOC_DAPM_SWITCH_E("Left1 Analog Loopback", SND_SOC_NOPM, 0, 0, 1159 &twl4030_dapm_abypassl1_control),
1199 &twl4030_dapm_abypassl1_control, 1160 SND_SOC_DAPM_SWITCH("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1200 bypass_event, SND_SOC_DAPM_POST_REG), 1161 &twl4030_dapm_abypassr2_control),
1201 SND_SOC_DAPM_SWITCH_E("Right2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1162 SND_SOC_DAPM_SWITCH("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0,
1202 &twl4030_dapm_abypassr2_control, 1163 &twl4030_dapm_abypassl2_control),
1203 bypass_event, SND_SOC_DAPM_POST_REG), 1164 SND_SOC_DAPM_SWITCH("Voice Analog Loopback", SND_SOC_NOPM, 0, 0,
1204 SND_SOC_DAPM_SWITCH_E("Left2 Analog Loopback", SND_SOC_NOPM, 0, 0, 1165 &twl4030_dapm_abypassv_control),
1205 &twl4030_dapm_abypassl2_control, 1166
1206 bypass_event, SND_SOC_DAPM_POST_REG), 1167 /* Master analog loopback switch */
1207 SND_SOC_DAPM_SWITCH_E("Voice Analog Loopback", SND_SOC_NOPM, 0, 0, 1168 SND_SOC_DAPM_SUPPLY("FM Loop Enable", TWL4030_REG_MISC_SET_1, 5, 0,
1208 &twl4030_dapm_abypassv_control, 1169 NULL, 0),
1209 bypass_event, SND_SOC_DAPM_POST_REG),
1210 1170
1211 /* Digital bypasses */ 1171 /* Digital bypasses */
1212 SND_SOC_DAPM_SWITCH_E("Left Digital Loopback", SND_SOC_NOPM, 0, 0, 1172 SND_SOC_DAPM_SWITCH("Left Digital Loopback", SND_SOC_NOPM, 0, 0,
1213 &twl4030_dapm_dbypassl_control, bypass_event, 1173 &twl4030_dapm_dbypassl_control),
1214 SND_SOC_DAPM_POST_REG), 1174 SND_SOC_DAPM_SWITCH("Right Digital Loopback", SND_SOC_NOPM, 0, 0,
1215 SND_SOC_DAPM_SWITCH_E("Right Digital Loopback", SND_SOC_NOPM, 0, 0, 1175 &twl4030_dapm_dbypassr_control),
1216 &twl4030_dapm_dbypassr_control, bypass_event, 1176 SND_SOC_DAPM_SWITCH("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1217 SND_SOC_DAPM_POST_REG), 1177 &twl4030_dapm_dbypassv_control),
1218 SND_SOC_DAPM_SWITCH_E("Voice Digital Loopback", SND_SOC_NOPM, 0, 0,
1219 &twl4030_dapm_dbypassv_control, bypass_event,
1220 SND_SOC_DAPM_POST_REG),
1221 1178
1222 /* Digital mixers, power control for the physical DACs */ 1179 /* Digital mixers, power control for the physical DACs */
1223 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer", 1180 SND_SOC_DAPM_MIXER("Digital R1 Playback Mixer",
@@ -1243,6 +1200,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1243 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer", 1200 SND_SOC_DAPM_MIXER("Analog Voice Playback Mixer",
1244 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0), 1201 TWL4030_REG_VDL_APGA_CTL, 0, 0, NULL, 0),
1245 1202
1203 SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event,
1204 SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD),
1205
1246 /* Output MIXER controls */ 1206 /* Output MIXER controls */
1247 /* Earpiece */ 1207 /* Earpiece */
1248 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0, 1208 SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
@@ -1308,8 +1268,9 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
1308 0, 0, NULL, 0, handsfreerpga_event, 1268 0, 0, NULL, 0, handsfreerpga_event,
1309 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 1269 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
1310 /* Vibra */ 1270 /* Vibra */
1311 SND_SOC_DAPM_MUX("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0, 1271 SND_SOC_DAPM_MUX_E("Vibra Mux", TWL4030_REG_VIBRA_CTL, 0, 0,
1312 &twl4030_dapm_vibra_control), 1272 &twl4030_dapm_vibra_control, vibramux_event,
1273 SND_SOC_DAPM_PRE_PMU),
1313 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0, 1274 SND_SOC_DAPM_MUX("Vibra Route", SND_SOC_NOPM, 0, 0,
1314 &twl4030_dapm_vibrapath_control), 1275 &twl4030_dapm_vibrapath_control),
1315 1276
@@ -1369,6 +1330,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1369 {"Digital R2 Playback Mixer", NULL, "DAC Right2"}, 1330 {"Digital R2 Playback Mixer", NULL, "DAC Right2"},
1370 {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, 1331 {"Digital Voice Playback Mixer", NULL, "DAC Voice"},
1371 1332
1333 /* Supply for the digital part (APLL) */
1334 {"Digital R1 Playback Mixer", NULL, "APLL Enable"},
1335 {"Digital L1 Playback Mixer", NULL, "APLL Enable"},
1336 {"Digital R2 Playback Mixer", NULL, "APLL Enable"},
1337 {"Digital L2 Playback Mixer", NULL, "APLL Enable"},
1338 {"Digital Voice Playback Mixer", NULL, "APLL Enable"},
1339
1372 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"}, 1340 {"Analog L1 Playback Mixer", NULL, "Digital L1 Playback Mixer"},
1373 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"}, 1341 {"Analog R1 Playback Mixer", NULL, "Digital R1 Playback Mixer"},
1374 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"}, 1342 {"Analog L2 Playback Mixer", NULL, "Digital L2 Playback Mixer"},
@@ -1482,6 +1450,11 @@ static const struct snd_soc_dapm_route intercon[] = {
1482 {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, 1450 {"ADC Virtual Left2", NULL, "TX2 Capture Route"},
1483 {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, 1451 {"ADC Virtual Right2", NULL, "TX2 Capture Route"},
1484 1452
1453 {"ADC Virtual Left1", NULL, "APLL Enable"},
1454 {"ADC Virtual Right1", NULL, "APLL Enable"},
1455 {"ADC Virtual Left2", NULL, "APLL Enable"},
1456 {"ADC Virtual Right2", NULL, "APLL Enable"},
1457
1485 /* Analog bypass routes */ 1458 /* Analog bypass routes */
1486 {"Right1 Analog Loopback", "Switch", "Analog Right"}, 1459 {"Right1 Analog Loopback", "Switch", "Analog Right"},
1487 {"Left1 Analog Loopback", "Switch", "Analog Left"}, 1460 {"Left1 Analog Loopback", "Switch", "Analog Left"},
@@ -1489,6 +1462,13 @@ static const struct snd_soc_dapm_route intercon[] = {
1489 {"Left2 Analog Loopback", "Switch", "Analog Left"}, 1462 {"Left2 Analog Loopback", "Switch", "Analog Left"},
1490 {"Voice Analog Loopback", "Switch", "Analog Left"}, 1463 {"Voice Analog Loopback", "Switch", "Analog Left"},
1491 1464
1465 /* Supply for the Analog loopbacks */
1466 {"Right1 Analog Loopback", NULL, "FM Loop Enable"},
1467 {"Left1 Analog Loopback", NULL, "FM Loop Enable"},
1468 {"Right2 Analog Loopback", NULL, "FM Loop Enable"},
1469 {"Left2 Analog Loopback", NULL, "FM Loop Enable"},
1470 {"Voice Analog Loopback", NULL, "FM Loop Enable"},
1471
1492 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"}, 1472 {"Analog R1 Playback Mixer", NULL, "Right1 Analog Loopback"},
1493 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"}, 1473 {"Analog L1 Playback Mixer", NULL, "Left1 Analog Loopback"},
1494 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"}, 1474 {"Analog R2 Playback Mixer", NULL, "Right2 Analog Loopback"},
@@ -1513,32 +1493,20 @@ static int twl4030_add_widgets(struct snd_soc_codec *codec)
1513 1493
1514 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 1494 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
1515 1495
1516 snd_soc_dapm_new_widgets(codec);
1517 return 0; 1496 return 0;
1518} 1497}
1519 1498
1520static int twl4030_set_bias_level(struct snd_soc_codec *codec, 1499static int twl4030_set_bias_level(struct snd_soc_codec *codec,
1521 enum snd_soc_bias_level level) 1500 enum snd_soc_bias_level level)
1522{ 1501{
1523 struct twl4030_priv *twl4030 = codec->private_data;
1524
1525 switch (level) { 1502 switch (level) {
1526 case SND_SOC_BIAS_ON: 1503 case SND_SOC_BIAS_ON:
1527 twl4030_codec_mute(codec, 0);
1528 break; 1504 break;
1529 case SND_SOC_BIAS_PREPARE: 1505 case SND_SOC_BIAS_PREPARE:
1530 twl4030_power_up(codec);
1531 if (twl4030->bypass_state)
1532 twl4030_codec_mute(codec, 0);
1533 else
1534 twl4030_codec_mute(codec, 1);
1535 break; 1506 break;
1536 case SND_SOC_BIAS_STANDBY: 1507 case SND_SOC_BIAS_STANDBY:
1537 twl4030_power_up(codec); 1508 if (codec->bias_level == SND_SOC_BIAS_OFF)
1538 if (twl4030->bypass_state) 1509 twl4030_power_up(codec);
1539 twl4030_codec_mute(codec, 0);
1540 else
1541 twl4030_codec_mute(codec, 1);
1542 break; 1510 break;
1543 case SND_SOC_BIAS_OFF: 1511 case SND_SOC_BIAS_OFF:
1544 twl4030_power_down(codec); 1512 twl4030_power_down(codec);
@@ -1785,29 +1753,23 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1785{ 1753{
1786 struct snd_soc_codec *codec = codec_dai->codec; 1754 struct snd_soc_codec *codec = codec_dai->codec;
1787 struct twl4030_priv *twl4030 = codec->private_data; 1755 struct twl4030_priv *twl4030 = codec->private_data;
1788 u8 infreq;
1789 1756
1790 switch (freq) { 1757 switch (freq) {
1791 case 19200000: 1758 case 19200000:
1792 infreq = TWL4030_APLL_INFREQ_19200KHZ;
1793 twl4030->sysclk = 19200;
1794 break;
1795 case 26000000: 1759 case 26000000:
1796 infreq = TWL4030_APLL_INFREQ_26000KHZ;
1797 twl4030->sysclk = 26000;
1798 break;
1799 case 38400000: 1760 case 38400000:
1800 infreq = TWL4030_APLL_INFREQ_38400KHZ;
1801 twl4030->sysclk = 38400;
1802 break; 1761 break;
1803 default: 1762 default:
1804 printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n", 1763 dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
1805 freq);
1806 return -EINVAL; 1764 return -EINVAL;
1807 } 1765 }
1808 1766
1809 infreq |= TWL4030_APLL_EN; 1767 if ((freq / 1000) != twl4030->sysclk) {
1810 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq); 1768 dev_err(codec->dev,
1769 "Mismatch in APLL mclk: %u (configured: %u)\n",
1770 freq, twl4030->sysclk * 1000);
1771 return -EINVAL;
1772 }
1811 1773
1812 return 0; 1774 return 0;
1813} 1775}
@@ -1905,18 +1867,16 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
1905 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1867 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1906 struct snd_soc_device *socdev = rtd->socdev; 1868 struct snd_soc_device *socdev = rtd->socdev;
1907 struct snd_soc_codec *codec = socdev->card->codec; 1869 struct snd_soc_codec *codec = socdev->card->codec;
1908 u8 infreq; 1870 struct twl4030_priv *twl4030 = codec->private_data;
1909 u8 mode; 1871 u8 mode;
1910 1872
1911 /* If the system master clock is not 26MHz, the voice PCM interface is 1873 /* If the system master clock is not 26MHz, the voice PCM interface is
1912 * not avilable. 1874 * not avilable.
1913 */ 1875 */
1914 infreq = twl4030_read_reg_cache(codec, TWL4030_REG_APLL_CTL) 1876 if (twl4030->sysclk != 26000) {
1915 & TWL4030_APLL_INFREQ; 1877 dev_err(codec->dev, "The board is configured for %u Hz, while"
1916 1878 "the Voice interface needs 26MHz APLL mclk\n",
1917 if (infreq != TWL4030_APLL_INFREQ_26000KHZ) { 1879 twl4030->sysclk * 1000);
1918 printk(KERN_ERR "TWL4030 voice startup: "
1919 "MCLK is not 26MHz, call set_sysclk() on init\n");
1920 return -EINVAL; 1880 return -EINVAL;
1921 } 1881 }
1922 1882
@@ -1989,21 +1949,19 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1989 int clk_id, unsigned int freq, int dir) 1949 int clk_id, unsigned int freq, int dir)
1990{ 1950{
1991 struct snd_soc_codec *codec = codec_dai->codec; 1951 struct snd_soc_codec *codec = codec_dai->codec;
1992 u8 infreq; 1952 struct twl4030_priv *twl4030 = codec->private_data;
1993 1953
1994 switch (freq) { 1954 if (freq != 26000000) {
1995 case 26000000: 1955 dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
1996 infreq = TWL4030_APLL_INFREQ_26000KHZ; 1956 "interface needs 26MHz APLL mclk\n", freq);
1997 break; 1957 return -EINVAL;
1998 default: 1958 }
1999 printk(KERN_ERR "TWL4030 voice set sysclk: unknown rate %d\n", 1959 if ((freq / 1000) != twl4030->sysclk) {
2000 freq); 1960 dev_err(codec->dev,
1961 "Mismatch in APLL mclk: %u (configured: %u)\n",
1962 freq, twl4030->sysclk * 1000);
2001 return -EINVAL; 1963 return -EINVAL;
2002 } 1964 }
2003
2004 infreq |= TWL4030_APLL_EN;
2005 twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
2006
2007 return 0; 1965 return 0;
2008} 1966}
2009 1967
@@ -2121,7 +2079,7 @@ struct snd_soc_dai twl4030_dai[] = {
2121}; 2079};
2122EXPORT_SYMBOL_GPL(twl4030_dai); 2080EXPORT_SYMBOL_GPL(twl4030_dai);
2123 2081
2124static int twl4030_suspend(struct platform_device *pdev, pm_message_t state) 2082static int twl4030_soc_suspend(struct platform_device *pdev, pm_message_t state)
2125{ 2083{
2126 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2084 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2127 struct snd_soc_codec *codec = socdev->card->codec; 2085 struct snd_soc_codec *codec = socdev->card->codec;
@@ -2131,7 +2089,7 @@ static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
2131 return 0; 2089 return 0;
2132} 2090}
2133 2091
2134static int twl4030_resume(struct platform_device *pdev) 2092static int twl4030_soc_resume(struct platform_device *pdev)
2135{ 2093{
2136 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2094 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2137 struct snd_soc_codec *codec = socdev->card->codec; 2095 struct snd_soc_codec *codec = socdev->card->codec;
@@ -2141,147 +2099,181 @@ static int twl4030_resume(struct platform_device *pdev)
2141 return 0; 2099 return 0;
2142} 2100}
2143 2101
2144/* 2102static struct snd_soc_codec *twl4030_codec;
2145 * initialize the driver
2146 * register the mixer and dsp interfaces with the kernel
2147 */
2148 2103
2149static int twl4030_init(struct snd_soc_device *socdev) 2104static int twl4030_soc_probe(struct platform_device *pdev)
2150{ 2105{
2151 struct snd_soc_codec *codec = socdev->card->codec; 2106 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2152 struct twl4030_setup_data *setup = socdev->codec_data; 2107 struct twl4030_setup_data *setup = socdev->codec_data;
2153 struct twl4030_priv *twl4030 = codec->private_data; 2108 struct snd_soc_codec *codec;
2154 int ret = 0; 2109 struct twl4030_priv *twl4030;
2110 int ret;
2155 2111
2156 printk(KERN_INFO "TWL4030 Audio Codec init \n"); 2112 BUG_ON(!twl4030_codec);
2157 2113
2158 codec->name = "twl4030"; 2114 codec = twl4030_codec;
2159 codec->owner = THIS_MODULE; 2115 twl4030 = codec->private_data;
2160 codec->read = twl4030_read_reg_cache; 2116 socdev->card->codec = codec;
2161 codec->write = twl4030_write;
2162 codec->set_bias_level = twl4030_set_bias_level;
2163 codec->dai = twl4030_dai;
2164 codec->num_dai = ARRAY_SIZE(twl4030_dai),
2165 codec->reg_cache_size = sizeof(twl4030_reg);
2166 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
2167 GFP_KERNEL);
2168 if (codec->reg_cache == NULL)
2169 return -ENOMEM;
2170 2117
2171 /* Configuration for headset ramp delay from setup data */ 2118 /* Configuration for headset ramp delay from setup data */
2172 if (setup) { 2119 if (setup) {
2173 unsigned char hs_pop; 2120 unsigned char hs_pop;
2174 2121
2175 if (setup->sysclk) 2122 if (setup->sysclk != twl4030->sysclk)
2176 twl4030->sysclk = setup->sysclk; 2123 dev_warn(&pdev->dev,
2177 else 2124 "Mismatch in APLL mclk: %u (configured: %u)\n",
2178 twl4030->sysclk = 26000; 2125 setup->sysclk, twl4030->sysclk);
2179 2126
2180 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET); 2127 hs_pop = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
2181 hs_pop &= ~TWL4030_RAMP_DELAY; 2128 hs_pop &= ~TWL4030_RAMP_DELAY;
2182 hs_pop |= (setup->ramp_delay_value << 2); 2129 hs_pop |= (setup->ramp_delay_value << 2);
2183 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop); 2130 twl4030_write_reg_cache(codec, TWL4030_REG_HS_POPN_SET, hs_pop);
2184 } else {
2185 twl4030->sysclk = 26000;
2186 } 2131 }
2187 2132
2188 /* register pcms */ 2133 /* register pcms */
2189 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 2134 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
2190 if (ret < 0) { 2135 if (ret < 0) {
2191 printk(KERN_ERR "twl4030: failed to create pcms\n"); 2136 dev_err(&pdev->dev, "failed to create pcms\n");
2192 goto pcm_err; 2137 return ret;
2193 } 2138 }
2194 2139
2195 twl4030_init_chip(codec);
2196
2197 /* power on device */
2198 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2199
2200 snd_soc_add_controls(codec, twl4030_snd_controls, 2140 snd_soc_add_controls(codec, twl4030_snd_controls,
2201 ARRAY_SIZE(twl4030_snd_controls)); 2141 ARRAY_SIZE(twl4030_snd_controls));
2202 twl4030_add_widgets(codec); 2142 twl4030_add_widgets(codec);
2203 2143
2204 ret = snd_soc_init_card(socdev); 2144 return 0;
2205 if (ret < 0) { 2145}
2206 printk(KERN_ERR "twl4030: failed to register card\n");
2207 goto card_err;
2208 }
2209 2146
2210 return ret; 2147static int twl4030_soc_remove(struct platform_device *pdev)
2148{
2149 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
2150 struct snd_soc_codec *codec = socdev->card->codec;
2211 2151
2212card_err: 2152 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2213 snd_soc_free_pcms(socdev); 2153 snd_soc_free_pcms(socdev);
2214 snd_soc_dapm_free(socdev); 2154 snd_soc_dapm_free(socdev);
2215pcm_err: 2155 kfree(codec->private_data);
2216 kfree(codec->reg_cache); 2156 kfree(codec);
2217 return ret;
2218}
2219 2157
2220static struct snd_soc_device *twl4030_socdev; 2158 return 0;
2159}
2221 2160
2222static int twl4030_probe(struct platform_device *pdev) 2161static int __devinit twl4030_codec_probe(struct platform_device *pdev)
2223{ 2162{
2224 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2163 struct twl4030_codec_audio_data *pdata = pdev->dev.platform_data;
2225 struct snd_soc_codec *codec; 2164 struct snd_soc_codec *codec;
2226 struct twl4030_priv *twl4030; 2165 struct twl4030_priv *twl4030;
2166 int ret;
2227 2167
2228 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 2168 if (!pdata) {
2229 if (codec == NULL) 2169 dev_err(&pdev->dev, "platform_data is missing\n");
2230 return -ENOMEM; 2170 return -EINVAL;
2171 }
2231 2172
2232 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL); 2173 twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
2233 if (twl4030 == NULL) { 2174 if (twl4030 == NULL) {
2234 kfree(codec); 2175 dev_err(&pdev->dev, "Can not allocate memroy\n");
2235 return -ENOMEM; 2176 return -ENOMEM;
2236 } 2177 }
2237 2178
2179 codec = &twl4030->codec;
2238 codec->private_data = twl4030; 2180 codec->private_data = twl4030;
2239 socdev->card->codec = codec; 2181 codec->dev = &pdev->dev;
2182 twl4030_dai[0].dev = &pdev->dev;
2183 twl4030_dai[1].dev = &pdev->dev;
2184
2240 mutex_init(&codec->mutex); 2185 mutex_init(&codec->mutex);
2241 INIT_LIST_HEAD(&codec->dapm_widgets); 2186 INIT_LIST_HEAD(&codec->dapm_widgets);
2242 INIT_LIST_HEAD(&codec->dapm_paths); 2187 INIT_LIST_HEAD(&codec->dapm_paths);
2243 2188
2244 twl4030_socdev = socdev; 2189 codec->name = "twl4030";
2245 twl4030_init(socdev); 2190 codec->owner = THIS_MODULE;
2191 codec->read = twl4030_read_reg_cache;
2192 codec->write = twl4030_write;
2193 codec->set_bias_level = twl4030_set_bias_level;
2194 codec->dai = twl4030_dai;
2195 codec->num_dai = ARRAY_SIZE(twl4030_dai),
2196 codec->reg_cache_size = sizeof(twl4030_reg);
2197 codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
2198 GFP_KERNEL);
2199 if (codec->reg_cache == NULL) {
2200 ret = -ENOMEM;
2201 goto error_cache;
2202 }
2203
2204 platform_set_drvdata(pdev, twl4030);
2205 twl4030_codec = codec;
2206
2207 /* Set the defaults, and power up the codec */
2208 twl4030->sysclk = twl4030_codec_get_mclk() / 1000;
2209 twl4030_init_chip(codec);
2210 codec->bias_level = SND_SOC_BIAS_OFF;
2211 twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
2212
2213 ret = snd_soc_register_codec(codec);
2214 if (ret != 0) {
2215 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
2216 goto error_codec;
2217 }
2218
2219 ret = snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai));
2220 if (ret != 0) {
2221 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
2222 snd_soc_unregister_codec(codec);
2223 goto error_codec;
2224 }
2246 2225
2247 return 0; 2226 return 0;
2227
2228error_codec:
2229 twl4030_power_down(codec);
2230 kfree(codec->reg_cache);
2231error_cache:
2232 kfree(twl4030);
2233 return ret;
2248} 2234}
2249 2235
2250static int twl4030_remove(struct platform_device *pdev) 2236static int __devexit twl4030_codec_remove(struct platform_device *pdev)
2251{ 2237{
2252 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 2238 struct twl4030_priv *twl4030 = platform_get_drvdata(pdev);
2253 struct snd_soc_codec *codec = socdev->card->codec;
2254 2239
2255 printk(KERN_INFO "TWL4030 Audio Codec remove\n"); 2240 kfree(twl4030);
2256 twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
2257 snd_soc_free_pcms(socdev);
2258 snd_soc_dapm_free(socdev);
2259 kfree(codec->private_data);
2260 kfree(codec);
2261 2241
2242 twl4030_codec = NULL;
2262 return 0; 2243 return 0;
2263} 2244}
2264 2245
2265struct snd_soc_codec_device soc_codec_dev_twl4030 = { 2246MODULE_ALIAS("platform:twl4030_codec_audio");
2266 .probe = twl4030_probe, 2247
2267 .remove = twl4030_remove, 2248static struct platform_driver twl4030_codec_driver = {
2268 .suspend = twl4030_suspend, 2249 .probe = twl4030_codec_probe,
2269 .resume = twl4030_resume, 2250 .remove = __devexit_p(twl4030_codec_remove),
2251 .driver = {
2252 .name = "twl4030_codec_audio",
2253 .owner = THIS_MODULE,
2254 },
2270}; 2255};
2271EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
2272 2256
2273static int __init twl4030_modinit(void) 2257static int __init twl4030_modinit(void)
2274{ 2258{
2275 return snd_soc_register_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); 2259 return platform_driver_register(&twl4030_codec_driver);
2276} 2260}
2277module_init(twl4030_modinit); 2261module_init(twl4030_modinit);
2278 2262
2279static void __exit twl4030_exit(void) 2263static void __exit twl4030_exit(void)
2280{ 2264{
2281 snd_soc_unregister_dais(&twl4030_dai[0], ARRAY_SIZE(twl4030_dai)); 2265 platform_driver_unregister(&twl4030_codec_driver);
2282} 2266}
2283module_exit(twl4030_exit); 2267module_exit(twl4030_exit);
2284 2268
2269struct snd_soc_codec_device soc_codec_dev_twl4030 = {
2270 .probe = twl4030_soc_probe,
2271 .remove = twl4030_soc_remove,
2272 .suspend = twl4030_soc_suspend,
2273 .resume = twl4030_soc_resume,
2274};
2275EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
2276
2285MODULE_DESCRIPTION("ASoC TWL4030 codec driver"); 2277MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
2286MODULE_AUTHOR("Steve Sakoman"); 2278MODULE_AUTHOR("Steve Sakoman");
2287MODULE_LICENSE("GPL"); 2279MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
index 2b4bfa23f985..dd6396ec9c79 100644
--- a/sound/soc/codecs/twl4030.h
+++ b/sound/soc/codecs/twl4030.h
@@ -22,245 +22,13 @@
22#ifndef __TWL4030_AUDIO_H__ 22#ifndef __TWL4030_AUDIO_H__
23#define __TWL4030_AUDIO_H__ 23#define __TWL4030_AUDIO_H__
24 24
25#define TWL4030_REG_CODEC_MODE 0x1 25/* Register descriptions are here */
26#define TWL4030_REG_OPTION 0x2 26#include <linux/mfd/twl4030-codec.h>
27#define TWL4030_REG_UNKNOWN 0x3
28#define TWL4030_REG_MICBIAS_CTL 0x4
29#define TWL4030_REG_ANAMICL 0x5
30#define TWL4030_REG_ANAMICR 0x6
31#define TWL4030_REG_AVADC_CTL 0x7
32#define TWL4030_REG_ADCMICSEL 0x8
33#define TWL4030_REG_DIGMIXING 0x9
34#define TWL4030_REG_ATXL1PGA 0xA
35#define TWL4030_REG_ATXR1PGA 0xB
36#define TWL4030_REG_AVTXL2PGA 0xC
37#define TWL4030_REG_AVTXR2PGA 0xD
38#define TWL4030_REG_AUDIO_IF 0xE
39#define TWL4030_REG_VOICE_IF 0xF
40#define TWL4030_REG_ARXR1PGA 0x10
41#define TWL4030_REG_ARXL1PGA 0x11
42#define TWL4030_REG_ARXR2PGA 0x12
43#define TWL4030_REG_ARXL2PGA 0x13
44#define TWL4030_REG_VRXPGA 0x14
45#define TWL4030_REG_VSTPGA 0x15
46#define TWL4030_REG_VRX2ARXPGA 0x16
47#define TWL4030_REG_AVDAC_CTL 0x17
48#define TWL4030_REG_ARX2VTXPGA 0x18
49#define TWL4030_REG_ARXL1_APGA_CTL 0x19
50#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
51#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
52#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
53#define TWL4030_REG_ATX2ARXPGA 0x1D
54#define TWL4030_REG_BT_IF 0x1E
55#define TWL4030_REG_BTPGA 0x1F
56#define TWL4030_REG_BTSTPGA 0x20
57#define TWL4030_REG_EAR_CTL 0x21
58#define TWL4030_REG_HS_SEL 0x22
59#define TWL4030_REG_HS_GAIN_SET 0x23
60#define TWL4030_REG_HS_POPN_SET 0x24
61#define TWL4030_REG_PREDL_CTL 0x25
62#define TWL4030_REG_PREDR_CTL 0x26
63#define TWL4030_REG_PRECKL_CTL 0x27
64#define TWL4030_REG_PRECKR_CTL 0x28
65#define TWL4030_REG_HFL_CTL 0x29
66#define TWL4030_REG_HFR_CTL 0x2A
67#define TWL4030_REG_ALC_CTL 0x2B
68#define TWL4030_REG_ALC_SET1 0x2C
69#define TWL4030_REG_ALC_SET2 0x2D
70#define TWL4030_REG_BOOST_CTL 0x2E
71#define TWL4030_REG_SOFTVOL_CTL 0x2F
72#define TWL4030_REG_DTMF_FREQSEL 0x30
73#define TWL4030_REG_DTMF_TONEXT1H 0x31
74#define TWL4030_REG_DTMF_TONEXT1L 0x32
75#define TWL4030_REG_DTMF_TONEXT2H 0x33
76#define TWL4030_REG_DTMF_TONEXT2L 0x34
77#define TWL4030_REG_DTMF_TONOFF 0x35
78#define TWL4030_REG_DTMF_WANONOFF 0x36
79#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
80#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
81#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
82#define TWL4030_REG_APLL_CTL 0x3A
83#define TWL4030_REG_DTMF_CTL 0x3B
84#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
85#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
86#define TWL4030_REG_MISC_SET_1 0x3E
87#define TWL4030_REG_PCMBTMUX 0x3F
88#define TWL4030_REG_RX_PATH_SEL 0x43
89#define TWL4030_REG_VDL_APGA_CTL 0x44
90#define TWL4030_REG_VIBRA_CTL 0x45
91#define TWL4030_REG_VIBRA_SET 0x46
92#define TWL4030_REG_VIBRA_PWM_SET 0x47
93#define TWL4030_REG_ANAMIC_GAIN 0x48
94#define TWL4030_REG_MISC_SET_2 0x49
95#define TWL4030_REG_SW_SHADOW 0x4A
96 27
28/* Sgadow register used by the audio driver */
29#define TWL4030_REG_SW_SHADOW 0x4A
97#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1) 30#define TWL4030_CACHEREGNUM (TWL4030_REG_SW_SHADOW + 1)
98 31
99/* Bitfield Definitions */
100
101/* TWL4030_CODEC_MODE (0x01) Fields */
102
103#define TWL4030_APLL_RATE 0xF0
104#define TWL4030_APLL_RATE_8000 0x00
105#define TWL4030_APLL_RATE_11025 0x10
106#define TWL4030_APLL_RATE_12000 0x20
107#define TWL4030_APLL_RATE_16000 0x40
108#define TWL4030_APLL_RATE_22050 0x50
109#define TWL4030_APLL_RATE_24000 0x60
110#define TWL4030_APLL_RATE_32000 0x80
111#define TWL4030_APLL_RATE_44100 0x90
112#define TWL4030_APLL_RATE_48000 0xA0
113#define TWL4030_APLL_RATE_96000 0xE0
114#define TWL4030_SEL_16K 0x08
115#define TWL4030_CODECPDZ 0x02
116#define TWL4030_OPT_MODE 0x01
117#define TWL4030_OPTION_1 (1 << 0)
118#define TWL4030_OPTION_2 (0 << 0)
119
120/* TWL4030_OPTION (0x02) Fields */
121
122#define TWL4030_ATXL1_EN (1 << 0)
123#define TWL4030_ATXR1_EN (1 << 1)
124#define TWL4030_ATXL2_VTXL_EN (1 << 2)
125#define TWL4030_ATXR2_VTXR_EN (1 << 3)
126#define TWL4030_ARXL1_VRX_EN (1 << 4)
127#define TWL4030_ARXR1_EN (1 << 5)
128#define TWL4030_ARXL2_EN (1 << 6)
129#define TWL4030_ARXR2_EN (1 << 7)
130
131/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
132
133#define TWL4030_MICBIAS2_CTL 0x40
134#define TWL4030_MICBIAS1_CTL 0x20
135#define TWL4030_HSMICBIAS_EN 0x04
136#define TWL4030_MICBIAS2_EN 0x02
137#define TWL4030_MICBIAS1_EN 0x01
138
139/* ANAMICL (0x05) Fields */
140
141#define TWL4030_CNCL_OFFSET_START 0x80
142#define TWL4030_OFFSET_CNCL_SEL 0x60
143#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
144#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
145#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
146#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
147#define TWL4030_MICAMPL_EN 0x10
148#define TWL4030_CKMIC_EN 0x08
149#define TWL4030_AUXL_EN 0x04
150#define TWL4030_HSMIC_EN 0x02
151#define TWL4030_MAINMIC_EN 0x01
152
153/* ANAMICR (0x06) Fields */
154
155#define TWL4030_MICAMPR_EN 0x10
156#define TWL4030_AUXR_EN 0x04
157#define TWL4030_SUBMIC_EN 0x01
158
159/* AVADC_CTL (0x07) Fields */
160
161#define TWL4030_ADCL_EN 0x08
162#define TWL4030_AVADC_CLK_PRIORITY 0x04
163#define TWL4030_ADCR_EN 0x02
164
165/* TWL4030_REG_ADCMICSEL (0x08) Fields */
166
167#define TWL4030_DIGMIC1_EN 0x08
168#define TWL4030_TX2IN_SEL 0x04
169#define TWL4030_DIGMIC0_EN 0x02
170#define TWL4030_TX1IN_SEL 0x01
171
172/* AUDIO_IF (0x0E) Fields */
173
174#define TWL4030_AIF_SLAVE_EN 0x80
175#define TWL4030_DATA_WIDTH 0x60
176#define TWL4030_DATA_WIDTH_16S_16W 0x00
177#define TWL4030_DATA_WIDTH_32S_16W 0x40
178#define TWL4030_DATA_WIDTH_32S_24W 0x60
179#define TWL4030_AIF_FORMAT 0x18
180#define TWL4030_AIF_FORMAT_CODEC 0x00
181#define TWL4030_AIF_FORMAT_LEFT 0x08
182#define TWL4030_AIF_FORMAT_RIGHT 0x10
183#define TWL4030_AIF_FORMAT_TDM 0x18
184#define TWL4030_AIF_TRI_EN 0x04
185#define TWL4030_CLK256FS_EN 0x02
186#define TWL4030_AIF_EN 0x01
187
188/* VOICE_IF (0x0F) Fields */
189
190#define TWL4030_VIF_SLAVE_EN 0x80
191#define TWL4030_VIF_DIN_EN 0x40
192#define TWL4030_VIF_DOUT_EN 0x20
193#define TWL4030_VIF_SWAP 0x10
194#define TWL4030_VIF_FORMAT 0x08
195#define TWL4030_VIF_TRI_EN 0x04
196#define TWL4030_VIF_SUB_EN 0x02
197#define TWL4030_VIF_EN 0x01
198
199/* EAR_CTL (0x21) */
200#define TWL4030_EAR_GAIN 0x30
201
202/* HS_GAIN_SET (0x23) Fields */
203
204#define TWL4030_HSR_GAIN 0x0C
205#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
206#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
207#define TWL4030_HSR_GAIN_0DB 0x08
208#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
209#define TWL4030_HSL_GAIN 0x03
210#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
211#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
212#define TWL4030_HSL_GAIN_0DB 0x02
213#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
214
215/* HS_POPN_SET (0x24) Fields */
216
217#define TWL4030_VMID_EN 0x40
218#define TWL4030_EXTMUTE 0x20
219#define TWL4030_RAMP_DELAY 0x1C
220#define TWL4030_RAMP_DELAY_20MS 0x00
221#define TWL4030_RAMP_DELAY_40MS 0x04
222#define TWL4030_RAMP_DELAY_81MS 0x08
223#define TWL4030_RAMP_DELAY_161MS 0x0C
224#define TWL4030_RAMP_DELAY_323MS 0x10
225#define TWL4030_RAMP_DELAY_645MS 0x14
226#define TWL4030_RAMP_DELAY_1291MS 0x18
227#define TWL4030_RAMP_DELAY_2581MS 0x1C
228#define TWL4030_RAMP_EN 0x02
229
230/* PREDL_CTL (0x25) */
231#define TWL4030_PREDL_GAIN 0x30
232
233/* PREDR_CTL (0x26) */
234#define TWL4030_PREDR_GAIN 0x30
235
236/* PRECKL_CTL (0x27) */
237#define TWL4030_PRECKL_GAIN 0x30
238
239/* PRECKR_CTL (0x28) */
240#define TWL4030_PRECKR_GAIN 0x30
241
242/* HFL_CTL (0x29, 0x2A) Fields */
243#define TWL4030_HF_CTL_HB_EN 0x04
244#define TWL4030_HF_CTL_LOOP_EN 0x08
245#define TWL4030_HF_CTL_RAMP_EN 0x10
246#define TWL4030_HF_CTL_REF_EN 0x20
247
248/* APLL_CTL (0x3A) Fields */
249
250#define TWL4030_APLL_EN 0x10
251#define TWL4030_APLL_INFREQ 0x0F
252#define TWL4030_APLL_INFREQ_19200KHZ 0x05
253#define TWL4030_APLL_INFREQ_26000KHZ 0x06
254#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
255
256/* REG_MISC_SET_1 (0x3E) Fields */
257
258#define TWL4030_CLK64_EN 0x80
259#define TWL4030_SCRAMBLE_EN 0x40
260#define TWL4030_FMLOOP_EN 0x20
261#define TWL4030_SMOOTH_ANAVOL_EN 0x02
262#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
263
264/* TWL4030_REG_SW_SHADOW (0x4A) Fields */ 32/* TWL4030_REG_SW_SHADOW (0x4A) Fields */
265#define TWL4030_HFL_EN 0x01 33#define TWL4030_HFL_EN 0x01
266#define TWL4030_HFR_EN 0x02 34#define TWL4030_HFR_EN 0x02
@@ -279,3 +47,5 @@ struct twl4030_setup_data {
279}; 47};
280 48
281#endif /* End of __TWL4030_AUDIO_H__ */ 49#endif /* End of __TWL4030_AUDIO_H__ */
50
51
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..a2763c2e7348 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -378,7 +378,6 @@ static int uda1380_add_widgets(struct snd_soc_codec *codec)
378 378
379 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 379 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
380 380
381 snd_soc_dapm_new_widgets(codec);
382 return 0; 381 return 0;
383} 382}
384 383
@@ -713,17 +712,9 @@ static int uda1380_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, uda1380_snd_controls, 712 snd_soc_add_controls(codec, uda1380_snd_controls,
714 ARRAY_SIZE(uda1380_snd_controls)); 713 ARRAY_SIZE(uda1380_snd_controls));
715 uda1380_add_widgets(codec); 714 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 715
722 return ret; 716 return ret;
723 717
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 718pcm_err:
728 return ret; 719 return ret;
729} 720}
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 593d5b9c9f03..f82125d9e85a 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -800,7 +800,7 @@ static int wm8350_add_widgets(struct snd_soc_codec *codec)
800 return ret; 800 return ret;
801 } 801 }
802 802
803 return snd_soc_dapm_new_widgets(codec); 803 return 0;
804} 804}
805 805
806static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai, 806static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
@@ -1101,7 +1101,7 @@ static inline int fll_factors(struct _fll_div *fll_div, unsigned int input,
1101} 1101}
1102 1102
1103static int wm8350_set_fll(struct snd_soc_dai *codec_dai, 1103static int wm8350_set_fll(struct snd_soc_dai *codec_dai,
1104 int pll_id, unsigned int freq_in, 1104 int pll_id, int source, unsigned int freq_in,
1105 unsigned int freq_out) 1105 unsigned int freq_out)
1106{ 1106{
1107 struct snd_soc_codec *codec = codec_dai->codec; 1107 struct snd_soc_codec *codec = codec_dai->codec;
@@ -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)
@@ -1680,21 +1669,6 @@ static int __devexit wm8350_codec_remove(struct platform_device *pdev)
1680 return 0; 1669 return 0;
1681} 1670}
1682 1671
1683#ifdef CONFIG_PM
1684static int wm8350_codec_suspend(struct platform_device *pdev, pm_message_t m)
1685{
1686 return snd_soc_suspend_device(&pdev->dev);
1687}
1688
1689static int wm8350_codec_resume(struct platform_device *pdev)
1690{
1691 return snd_soc_resume_device(&pdev->dev);
1692}
1693#else
1694#define wm8350_codec_suspend NULL
1695#define wm8350_codec_resume NULL
1696#endif
1697
1698static struct platform_driver wm8350_codec_driver = { 1672static struct platform_driver wm8350_codec_driver = {
1699 .driver = { 1673 .driver = {
1700 .name = "wm8350-codec", 1674 .name = "wm8350-codec",
@@ -1702,8 +1676,6 @@ static struct platform_driver wm8350_codec_driver = {
1702 }, 1676 },
1703 .probe = wm8350_codec_probe, 1677 .probe = wm8350_codec_probe,
1704 .remove = __devexit_p(wm8350_codec_remove), 1678 .remove = __devexit_p(wm8350_codec_remove),
1705 .suspend = wm8350_codec_suspend,
1706 .resume = wm8350_codec_resume,
1707}; 1679};
1708 1680
1709static __init int wm8350_init(void) 1681static __init int wm8350_init(void)
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index b9ef4d915221..b432f4d4a324 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -915,7 +915,6 @@ static int wm8400_add_widgets(struct snd_soc_codec *codec)
915 915
916 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 916 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
917 917
918 snd_soc_dapm_new_widgets(codec);
919 return 0; 918 return 0;
920} 919}
921 920
@@ -1011,7 +1010,8 @@ static int fll_factors(struct wm8400_priv *wm8400, struct fll_factors *factors,
1011} 1010}
1012 1011
1013static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id, 1012static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
1014 unsigned int freq_in, unsigned int freq_out) 1013 int source, unsigned int freq_in,
1014 unsigned int freq_out)
1015{ 1015{
1016 struct snd_soc_codec *codec = codec_dai->codec; 1016 struct snd_soc_codec *codec = codec_dai->codec;
1017 struct wm8400_priv *wm8400 = codec->private_data; 1017 struct wm8400_priv *wm8400 = codec->private_data;
@@ -1399,17 +1399,6 @@ static int wm8400_probe(struct platform_device *pdev)
1399 wm8400_add_controls(codec); 1399 wm8400_add_controls(codec);
1400 wm8400_add_widgets(codec); 1400 wm8400_add_widgets(codec);
1401 1401
1402 ret = snd_soc_init_card(socdev);
1403 if (ret < 0) {
1404 dev_err(&pdev->dev, "failed to register card\n");
1405 goto card_err;
1406 }
1407
1408 return ret;
1409
1410card_err:
1411 snd_soc_free_pcms(socdev);
1412 snd_soc_dapm_free(socdev);
1413pcm_err: 1402pcm_err:
1414 return ret; 1403 return ret;
1415} 1404}
@@ -1558,21 +1547,6 @@ static int __exit wm8400_codec_remove(struct platform_device *dev)
1558 return 0; 1547 return 0;
1559} 1548}
1560 1549
1561#ifdef CONFIG_PM
1562static int wm8400_pdev_suspend(struct platform_device *pdev, pm_message_t msg)
1563{
1564 return snd_soc_suspend_device(&pdev->dev);
1565}
1566
1567static int wm8400_pdev_resume(struct platform_device *pdev)
1568{
1569 return snd_soc_resume_device(&pdev->dev);
1570}
1571#else
1572#define wm8400_pdev_suspend NULL
1573#define wm8400_pdev_resume NULL
1574#endif
1575
1576static struct platform_driver wm8400_codec_driver = { 1550static struct platform_driver wm8400_codec_driver = {
1577 .driver = { 1551 .driver = {
1578 .name = "wm8400-codec", 1552 .name = "wm8400-codec",
@@ -1580,8 +1554,6 @@ static struct platform_driver wm8400_codec_driver = {
1580 }, 1554 },
1581 .probe = wm8400_codec_probe, 1555 .probe = wm8400_codec_probe,
1582 .remove = __exit_p(wm8400_codec_remove), 1556 .remove = __exit_p(wm8400_codec_remove),
1583 .suspend = wm8400_pdev_suspend,
1584 .resume = wm8400_pdev_resume,
1585}; 1557};
1586 1558
1587static int __init wm8400_codec_init(void) 1559static int __init wm8400_codec_init(void)
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index 060d5d06ba95..265e68c75df8 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -219,7 +219,6 @@ static int wm8510_add_widgets(struct snd_soc_codec *codec)
219 219
220 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 220 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
221 221
222 snd_soc_dapm_new_widgets(codec);
223 return 0; 222 return 0;
224} 223}
225 224
@@ -271,8 +270,8 @@ static void pll_factors(unsigned int target, unsigned int source)
271 pll_div.k = K; 270 pll_div.k = K;
272} 271}
273 272
274static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, 273static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
275 int pll_id, unsigned int freq_in, unsigned int freq_out) 274 int source, unsigned int freq_in, unsigned int freq_out)
276{ 275{
277 struct snd_soc_codec *codec = codec_dai->codec; 276 struct snd_soc_codec *codec = codec_dai->codec;
278 u16 reg; 277 u16 reg;
@@ -604,16 +603,9 @@ static int wm8510_init(struct snd_soc_device *socdev,
604 snd_soc_add_controls(codec, wm8510_snd_controls, 603 snd_soc_add_controls(codec, wm8510_snd_controls,
605 ARRAY_SIZE(wm8510_snd_controls)); 604 ARRAY_SIZE(wm8510_snd_controls));
606 wm8510_add_widgets(codec); 605 wm8510_add_widgets(codec);
607 ret = snd_soc_init_card(socdev); 606
608 if (ret < 0) {
609 printk(KERN_ERR "wm8510: failed to register card\n");
610 goto card_err;
611 }
612 return ret; 607 return ret;
613 608
614card_err:
615 snd_soc_free_pcms(socdev);
616 snd_soc_dapm_free(socdev);
617err: 609err:
618 kfree(codec->reg_cache); 610 kfree(codec->reg_cache);
619 return ret; 611 return ret;
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 25870a4652fb..d3a61d7ea0c5 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -117,7 +117,6 @@ static int wm8523_add_widgets(struct snd_soc_codec *codec)
117 117
118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 118 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
119 119
120 snd_soc_dapm_new_widgets(codec);
121 return 0; 120 return 0;
122} 121}
123 122
@@ -448,17 +447,9 @@ static int wm8523_probe(struct platform_device *pdev)
448 snd_soc_add_controls(codec, wm8523_snd_controls, 447 snd_soc_add_controls(codec, wm8523_snd_controls,
449 ARRAY_SIZE(wm8523_snd_controls)); 448 ARRAY_SIZE(wm8523_snd_controls));
450 wm8523_add_widgets(codec); 449 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 450
457 return ret; 451 return ret;
458 452
459card_err:
460 snd_soc_free_pcms(socdev);
461 snd_soc_dapm_free(socdev);
462pcm_err: 453pcm_err:
463 return ret; 454 return ret;
464} 455}
@@ -638,21 +629,6 @@ static __devexit int wm8523_i2c_remove(struct i2c_client *client)
638 return 0; 629 return 0;
639} 630}
640 631
641#ifdef CONFIG_PM
642static int wm8523_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
643{
644 return snd_soc_suspend_device(&i2c->dev);
645}
646
647static int wm8523_i2c_resume(struct i2c_client *i2c)
648{
649 return snd_soc_resume_device(&i2c->dev);
650}
651#else
652#define wm8523_i2c_suspend NULL
653#define wm8523_i2c_resume NULL
654#endif
655
656static const struct i2c_device_id wm8523_i2c_id[] = { 632static const struct i2c_device_id wm8523_i2c_id[] = {
657 { "wm8523", 0 }, 633 { "wm8523", 0 },
658 { } 634 { }
@@ -666,8 +642,6 @@ static struct i2c_driver wm8523_i2c_driver = {
666 }, 642 },
667 .probe = wm8523_i2c_probe, 643 .probe = wm8523_i2c_probe,
668 .remove = __devexit_p(wm8523_i2c_remove), 644 .remove = __devexit_p(wm8523_i2c_remove),
669 .suspend = wm8523_i2c_suspend,
670 .resume = wm8523_i2c_resume,
671 .id_table = wm8523_i2c_id, 645 .id_table = wm8523_i2c_id,
672}; 646};
673#endif 647#endif
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 6bded8c78150..d077df6f5e75 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -315,7 +315,6 @@ static int wm8580_add_widgets(struct snd_soc_codec *codec)
315 315
316 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 316 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
317 317
318 snd_soc_dapm_new_widgets(codec);
319 return 0; 318 return 0;
320} 319}
321 320
@@ -407,8 +406,8 @@ static int pll_factors(struct _pll_div *pll_div, unsigned int target,
407 return 0; 406 return 0;
408} 407}
409 408
410static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, 409static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
411 int pll_id, unsigned int freq_in, unsigned int freq_out) 410 int source, unsigned int freq_in, unsigned int freq_out)
412{ 411{
413 int offset; 412 int offset;
414 struct snd_soc_codec *codec = codec_dai->codec; 413 struct snd_soc_codec *codec = codec_dai->codec;
@@ -800,17 +799,9 @@ static int wm8580_probe(struct platform_device *pdev)
800 snd_soc_add_controls(codec, wm8580_snd_controls, 799 snd_soc_add_controls(codec, wm8580_snd_controls,
801 ARRAY_SIZE(wm8580_snd_controls)); 800 ARRAY_SIZE(wm8580_snd_controls));
802 wm8580_add_widgets(codec); 801 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 802
809 return ret; 803 return ret;
810 804
811card_err:
812 snd_soc_free_pcms(socdev);
813 snd_soc_dapm_free(socdev);
814pcm_err: 805pcm_err:
815 return ret; 806 return ret;
816} 807}
@@ -961,21 +952,6 @@ static int wm8580_i2c_remove(struct i2c_client *client)
961 return 0; 952 return 0;
962} 953}
963 954
964#ifdef CONFIG_PM
965static int wm8580_i2c_suspend(struct i2c_client *client, pm_message_t msg)
966{
967 return snd_soc_suspend_device(&client->dev);
968}
969
970static int wm8580_i2c_resume(struct i2c_client *client)
971{
972 return snd_soc_resume_device(&client->dev);
973}
974#else
975#define wm8580_i2c_suspend NULL
976#define wm8580_i2c_resume NULL
977#endif
978
979static const struct i2c_device_id wm8580_i2c_id[] = { 955static const struct i2c_device_id wm8580_i2c_id[] = {
980 { "wm8580", 0 }, 956 { "wm8580", 0 },
981 { } 957 { }
@@ -989,8 +965,6 @@ static struct i2c_driver wm8580_i2c_driver = {
989 }, 965 },
990 .probe = wm8580_i2c_probe, 966 .probe = wm8580_i2c_probe,
991 .remove = wm8580_i2c_remove, 967 .remove = wm8580_i2c_remove,
992 .suspend = wm8580_i2c_suspend,
993 .resume = wm8580_i2c_resume,
994 .id_table = wm8580_i2c_id, 968 .id_table = wm8580_i2c_id,
995}; 969};
996#endif 970#endif
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
new file mode 100644
index 000000000000..24a35603bcf7
--- /dev/null
+++ b/sound/soc/codecs/wm8711.c
@@ -0,0 +1,633 @@
1/*
2 * wm8711.c -- WM8711 ALSA SoC Audio driver
3 *
4 * Copyright 2006 Wolfson Microelectronics
5 *
6 * Author: Mike Arthur <linux@wolfsonmicro.com>
7 *
8 * Based on wm8731.c by Richard Purdie
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <linux/spi/spi.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/tlv.h>
29#include <sound/initval.h>
30
31#include "wm8711.h"
32
33static struct snd_soc_codec *wm8711_codec;
34
35/* codec private data */
36struct wm8711_priv {
37 struct snd_soc_codec codec;
38 u16 reg_cache[WM8711_CACHEREGNUM];
39 unsigned int sysclk;
40};
41
42/*
43 * wm8711 register cache
44 * We can't read the WM8711 register space when we are
45 * using 2 wire for device control, so we cache them instead.
46 * There is no point in caching the reset register
47 */
48static const u16 wm8711_reg[WM8711_CACHEREGNUM] = {
49 0x0079, 0x0079, 0x000a, 0x0008,
50 0x009f, 0x000a, 0x0000, 0x0000
51};
52
53#define wm8711_reset(c) snd_soc_write(c, WM8711_RESET, 0)
54
55static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
56
57static const struct snd_kcontrol_new wm8711_snd_controls[] = {
58
59SOC_DOUBLE_R_TLV("Master Playback Volume", WM8711_LOUT1V, WM8711_ROUT1V,
60 0, 127, 0, out_tlv),
61SOC_DOUBLE_R("Master Playback ZC Switch", WM8711_LOUT1V, WM8711_ROUT1V,
62 7, 1, 0),
63
64};
65
66/* Output Mixer */
67static const struct snd_kcontrol_new wm8711_output_mixer_controls[] = {
68SOC_DAPM_SINGLE("Line Bypass Switch", WM8711_APANA, 3, 1, 0),
69SOC_DAPM_SINGLE("HiFi Playback Switch", WM8711_APANA, 4, 1, 0),
70};
71
72static const struct snd_soc_dapm_widget wm8711_dapm_widgets[] = {
73SND_SOC_DAPM_MIXER("Output Mixer", WM8711_PWR, 4, 1,
74 &wm8711_output_mixer_controls[0],
75 ARRAY_SIZE(wm8711_output_mixer_controls)),
76SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8711_PWR, 3, 1),
77SND_SOC_DAPM_OUTPUT("LOUT"),
78SND_SOC_DAPM_OUTPUT("LHPOUT"),
79SND_SOC_DAPM_OUTPUT("ROUT"),
80SND_SOC_DAPM_OUTPUT("RHPOUT"),
81};
82
83static const struct snd_soc_dapm_route intercon[] = {
84 /* output mixer */
85 {"Output Mixer", "Line Bypass Switch", "Line Input"},
86 {"Output Mixer", "HiFi Playback Switch", "DAC"},
87
88 /* outputs */
89 {"RHPOUT", NULL, "Output Mixer"},
90 {"ROUT", NULL, "Output Mixer"},
91 {"LHPOUT", NULL, "Output Mixer"},
92 {"LOUT", NULL, "Output Mixer"},
93};
94
95static int wm8711_add_widgets(struct snd_soc_codec *codec)
96{
97 snd_soc_dapm_new_controls(codec, wm8711_dapm_widgets,
98 ARRAY_SIZE(wm8711_dapm_widgets));
99
100 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
101
102 return 0;
103}
104
105struct _coeff_div {
106 u32 mclk;
107 u32 rate;
108 u16 fs;
109 u8 sr:4;
110 u8 bosr:1;
111 u8 usb:1;
112};
113
114/* codec mclk clock divider coefficients */
115static const struct _coeff_div coeff_div[] = {
116 /* 48k */
117 {12288000, 48000, 256, 0x0, 0x0, 0x0},
118 {18432000, 48000, 384, 0x0, 0x1, 0x0},
119 {12000000, 48000, 250, 0x0, 0x0, 0x1},
120
121 /* 32k */
122 {12288000, 32000, 384, 0x6, 0x0, 0x0},
123 {18432000, 32000, 576, 0x6, 0x1, 0x0},
124 {12000000, 32000, 375, 0x6, 0x0, 0x1},
125
126 /* 8k */
127 {12288000, 8000, 1536, 0x3, 0x0, 0x0},
128 {18432000, 8000, 2304, 0x3, 0x1, 0x0},
129 {11289600, 8000, 1408, 0xb, 0x0, 0x0},
130 {16934400, 8000, 2112, 0xb, 0x1, 0x0},
131 {12000000, 8000, 1500, 0x3, 0x0, 0x1},
132
133 /* 96k */
134 {12288000, 96000, 128, 0x7, 0x0, 0x0},
135 {18432000, 96000, 192, 0x7, 0x1, 0x0},
136 {12000000, 96000, 125, 0x7, 0x0, 0x1},
137
138 /* 44.1k */
139 {11289600, 44100, 256, 0x8, 0x0, 0x0},
140 {16934400, 44100, 384, 0x8, 0x1, 0x0},
141 {12000000, 44100, 272, 0x8, 0x1, 0x1},
142
143 /* 88.2k */
144 {11289600, 88200, 128, 0xf, 0x0, 0x0},
145 {16934400, 88200, 192, 0xf, 0x1, 0x0},
146 {12000000, 88200, 136, 0xf, 0x1, 0x1},
147};
148
149static inline int get_coeff(int mclk, int rate)
150{
151 int i;
152
153 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
154 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
155 return i;
156 }
157 return 0;
158}
159
160static int wm8711_hw_params(struct snd_pcm_substream *substream,
161 struct snd_pcm_hw_params *params,
162 struct snd_soc_dai *dai)
163{
164 struct snd_soc_codec *codec = dai->codec;
165 struct wm8711_priv *wm8711 = codec->private_data;
166 u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
167 int i = get_coeff(wm8711->sysclk, params_rate(params));
168 u16 srate = (coeff_div[i].sr << 2) |
169 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
170
171 snd_soc_write(codec, WM8711_SRATE, srate);
172
173 /* bit size */
174 switch (params_format(params)) {
175 case SNDRV_PCM_FORMAT_S16_LE:
176 break;
177 case SNDRV_PCM_FORMAT_S20_3LE:
178 iface |= 0x0004;
179 break;
180 case SNDRV_PCM_FORMAT_S24_LE:
181 iface |= 0x0008;
182 break;
183 }
184
185 snd_soc_write(codec, WM8711_IFACE, iface);
186 return 0;
187}
188
189static int wm8711_pcm_prepare(struct snd_pcm_substream *substream,
190 struct snd_soc_dai *dai)
191{
192 struct snd_soc_codec *codec = dai->codec;
193
194 /* set active */
195 snd_soc_write(codec, WM8711_ACTIVE, 0x0001);
196
197 return 0;
198}
199
200static void wm8711_shutdown(struct snd_pcm_substream *substream,
201 struct snd_soc_dai *dai)
202{
203 struct snd_soc_codec *codec = dai->codec;
204
205 /* deactivate */
206 if (!codec->active) {
207 udelay(50);
208 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
209 }
210}
211
212static int wm8711_mute(struct snd_soc_dai *dai, int mute)
213{
214 struct snd_soc_codec *codec = dai->codec;
215 u16 mute_reg = snd_soc_read(codec, WM8711_APDIGI) & 0xfff7;
216
217 if (mute)
218 snd_soc_write(codec, WM8711_APDIGI, mute_reg | 0x8);
219 else
220 snd_soc_write(codec, WM8711_APDIGI, mute_reg);
221
222 return 0;
223}
224
225static int wm8711_set_dai_sysclk(struct snd_soc_dai *codec_dai,
226 int clk_id, unsigned int freq, int dir)
227{
228 struct snd_soc_codec *codec = codec_dai->codec;
229 struct wm8711_priv *wm8711 = codec->private_data;
230
231 switch (freq) {
232 case 11289600:
233 case 12000000:
234 case 12288000:
235 case 16934400:
236 case 18432000:
237 wm8711->sysclk = freq;
238 return 0;
239 }
240 return -EINVAL;
241}
242
243static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
244 unsigned int fmt)
245{
246 struct snd_soc_codec *codec = codec_dai->codec;
247 u16 iface = 0;
248
249 /* set master/slave audio interface */
250 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
251 case SND_SOC_DAIFMT_CBM_CFM:
252 iface |= 0x0040;
253 break;
254 case SND_SOC_DAIFMT_CBS_CFS:
255 break;
256 default:
257 return -EINVAL;
258 }
259
260 /* interface format */
261 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
262 case SND_SOC_DAIFMT_I2S:
263 iface |= 0x0002;
264 break;
265 case SND_SOC_DAIFMT_RIGHT_J:
266 break;
267 case SND_SOC_DAIFMT_LEFT_J:
268 iface |= 0x0001;
269 break;
270 case SND_SOC_DAIFMT_DSP_A:
271 iface |= 0x0003;
272 break;
273 case SND_SOC_DAIFMT_DSP_B:
274 iface |= 0x0013;
275 break;
276 default:
277 return -EINVAL;
278 }
279
280 /* clock inversion */
281 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
282 case SND_SOC_DAIFMT_NB_NF:
283 break;
284 case SND_SOC_DAIFMT_IB_IF:
285 iface |= 0x0090;
286 break;
287 case SND_SOC_DAIFMT_IB_NF:
288 iface |= 0x0080;
289 break;
290 case SND_SOC_DAIFMT_NB_IF:
291 iface |= 0x0010;
292 break;
293 default:
294 return -EINVAL;
295 }
296
297 /* set iface */
298 snd_soc_write(codec, WM8711_IFACE, iface);
299 return 0;
300}
301
302
303static int wm8711_set_bias_level(struct snd_soc_codec *codec,
304 enum snd_soc_bias_level level)
305{
306 u16 reg = snd_soc_read(codec, WM8711_PWR) & 0xff7f;
307
308 switch (level) {
309 case SND_SOC_BIAS_ON:
310 snd_soc_write(codec, WM8711_PWR, reg);
311 break;
312 case SND_SOC_BIAS_PREPARE:
313 break;
314 case SND_SOC_BIAS_STANDBY:
315 snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
316 break;
317 case SND_SOC_BIAS_OFF:
318 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
319 snd_soc_write(codec, WM8711_PWR, 0xffff);
320 break;
321 }
322 codec->bias_level = level;
323 return 0;
324}
325
326#define WM8711_RATES SNDRV_PCM_RATE_8000_96000
327
328#define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
329 SNDRV_PCM_FMTBIT_S24_LE)
330
331static struct snd_soc_dai_ops wm8711_ops = {
332 .prepare = wm8711_pcm_prepare,
333 .hw_params = wm8711_hw_params,
334 .shutdown = wm8711_shutdown,
335 .digital_mute = wm8711_mute,
336 .set_sysclk = wm8711_set_dai_sysclk,
337 .set_fmt = wm8711_set_dai_fmt,
338};
339
340struct snd_soc_dai wm8711_dai = {
341 .name = "WM8711",
342 .playback = {
343 .stream_name = "Playback",
344 .channels_min = 1,
345 .channels_max = 2,
346 .rates = WM8711_RATES,
347 .formats = WM8711_FORMATS,
348 },
349 .ops = &wm8711_ops,
350};
351EXPORT_SYMBOL_GPL(wm8711_dai);
352
353static int wm8711_suspend(struct platform_device *pdev, pm_message_t state)
354{
355 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
356 struct snd_soc_codec *codec = socdev->card->codec;
357
358 snd_soc_write(codec, WM8711_ACTIVE, 0x0);
359 wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
360 return 0;
361}
362
363static int wm8711_resume(struct platform_device *pdev)
364{
365 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
366 struct snd_soc_codec *codec = socdev->card->codec;
367 int i;
368 u8 data[2];
369 u16 *cache = codec->reg_cache;
370
371 /* Sync reg_cache with the hardware */
372 for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
373 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
374 data[1] = cache[i] & 0x00ff;
375 codec->hw_write(codec->control_data, data, 2);
376 }
377 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
378 wm8711_set_bias_level(codec, codec->suspend_bias_level);
379 return 0;
380}
381
382static int wm8711_probe(struct platform_device *pdev)
383{
384 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
385 struct snd_soc_codec *codec;
386 int ret = 0;
387
388 if (wm8711_codec == NULL) {
389 dev_err(&pdev->dev, "Codec device not registered\n");
390 return -ENODEV;
391 }
392
393 socdev->card->codec = wm8711_codec;
394 codec = wm8711_codec;
395
396 /* register pcms */
397 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
398 if (ret < 0) {
399 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
400 goto pcm_err;
401 }
402
403 snd_soc_add_controls(codec, wm8711_snd_controls,
404 ARRAY_SIZE(wm8711_snd_controls));
405 wm8711_add_widgets(codec);
406
407 return ret;
408
409pcm_err:
410 return ret;
411}
412
413/* power down chip */
414static int wm8711_remove(struct platform_device *pdev)
415{
416 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
417
418 snd_soc_free_pcms(socdev);
419 snd_soc_dapm_free(socdev);
420
421 return 0;
422}
423
424struct snd_soc_codec_device soc_codec_dev_wm8711 = {
425 .probe = wm8711_probe,
426 .remove = wm8711_remove,
427 .suspend = wm8711_suspend,
428 .resume = wm8711_resume,
429};
430EXPORT_SYMBOL_GPL(soc_codec_dev_wm8711);
431
432static int wm8711_register(struct wm8711_priv *wm8711,
433 enum snd_soc_control_type control)
434{
435 int ret;
436 struct snd_soc_codec *codec = &wm8711->codec;
437 u16 reg;
438
439 if (wm8711_codec) {
440 dev_err(codec->dev, "Another WM8711 is registered\n");
441 return -EINVAL;
442 }
443
444 mutex_init(&codec->mutex);
445 INIT_LIST_HEAD(&codec->dapm_widgets);
446 INIT_LIST_HEAD(&codec->dapm_paths);
447
448 codec->private_data = wm8711;
449 codec->name = "WM8711";
450 codec->owner = THIS_MODULE;
451 codec->bias_level = SND_SOC_BIAS_OFF;
452 codec->set_bias_level = wm8711_set_bias_level;
453 codec->dai = &wm8711_dai;
454 codec->num_dai = 1;
455 codec->reg_cache_size = WM8711_CACHEREGNUM;
456 codec->reg_cache = &wm8711->reg_cache;
457
458 memcpy(codec->reg_cache, wm8711_reg, sizeof(wm8711_reg));
459
460 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control);
461 if (ret < 0) {
462 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
463 goto err;
464 }
465
466 ret = wm8711_reset(codec);
467 if (ret < 0) {
468 dev_err(codec->dev, "Failed to issue reset\n");
469 goto err;
470 }
471
472 wm8711_dai.dev = codec->dev;
473
474 wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
475
476 /* Latch the update bits */
477 reg = snd_soc_read(codec, WM8711_LOUT1V);
478 snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
479 reg = snd_soc_read(codec, WM8711_ROUT1V);
480 snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
481
482 wm8711_codec = codec;
483
484 ret = snd_soc_register_codec(codec);
485 if (ret != 0) {
486 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
487 goto err;
488 }
489
490 ret = snd_soc_register_dai(&wm8711_dai);
491 if (ret != 0) {
492 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
493 goto err_codec;
494 }
495
496 return 0;
497
498err_codec:
499 snd_soc_unregister_codec(codec);
500err:
501 kfree(wm8711);
502 return ret;
503}
504
505static void wm8711_unregister(struct wm8711_priv *wm8711)
506{
507 wm8711_set_bias_level(&wm8711->codec, SND_SOC_BIAS_OFF);
508 snd_soc_unregister_dai(&wm8711_dai);
509 snd_soc_unregister_codec(&wm8711->codec);
510 kfree(wm8711);
511 wm8711_codec = NULL;
512}
513
514#if defined(CONFIG_SPI_MASTER)
515static int __devinit wm8711_spi_probe(struct spi_device *spi)
516{
517 struct snd_soc_codec *codec;
518 struct wm8711_priv *wm8711;
519
520 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
521 if (wm8711 == NULL)
522 return -ENOMEM;
523
524 codec = &wm8711->codec;
525 codec->control_data = spi;
526 codec->dev = &spi->dev;
527
528 dev_set_drvdata(&spi->dev, wm8711);
529
530 return wm8711_register(wm8711, SND_SOC_SPI);
531}
532
533static int __devexit wm8711_spi_remove(struct spi_device *spi)
534{
535 struct wm8711_priv *wm8711 = dev_get_drvdata(&spi->dev);
536
537 wm8711_unregister(wm8711);
538
539 return 0;
540}
541
542static struct spi_driver wm8711_spi_driver = {
543 .driver = {
544 .name = "wm8711",
545 .bus = &spi_bus_type,
546 .owner = THIS_MODULE,
547 },
548 .probe = wm8711_spi_probe,
549 .remove = __devexit_p(wm8711_spi_remove),
550};
551#endif /* CONFIG_SPI_MASTER */
552
553#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
554static __devinit int wm8711_i2c_probe(struct i2c_client *i2c,
555 const struct i2c_device_id *id)
556{
557 struct wm8711_priv *wm8711;
558 struct snd_soc_codec *codec;
559
560 wm8711 = kzalloc(sizeof(struct wm8711_priv), GFP_KERNEL);
561 if (wm8711 == NULL)
562 return -ENOMEM;
563
564 codec = &wm8711->codec;
565 codec->hw_write = (hw_write_t)i2c_master_send;
566
567 i2c_set_clientdata(i2c, wm8711);
568 codec->control_data = i2c;
569
570 codec->dev = &i2c->dev;
571
572 return wm8711_register(wm8711, SND_SOC_I2C);
573}
574
575static __devexit int wm8711_i2c_remove(struct i2c_client *client)
576{
577 struct wm8711_priv *wm8711 = i2c_get_clientdata(client);
578 wm8711_unregister(wm8711);
579 return 0;
580}
581
582static const struct i2c_device_id wm8711_i2c_id[] = {
583 { "wm8711", 0 },
584 { }
585};
586MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
587
588static struct i2c_driver wm8711_i2c_driver = {
589 .driver = {
590 .name = "WM8711 I2C Codec",
591 .owner = THIS_MODULE,
592 },
593 .probe = wm8711_i2c_probe,
594 .remove = __devexit_p(wm8711_i2c_remove),
595 .id_table = wm8711_i2c_id,
596};
597#endif
598
599static int __init wm8711_modinit(void)
600{
601 int ret;
602#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
603 ret = i2c_add_driver(&wm8711_i2c_driver);
604 if (ret != 0) {
605 printk(KERN_ERR "Failed to register WM8711 I2C driver: %d\n",
606 ret);
607 }
608#endif
609#if defined(CONFIG_SPI_MASTER)
610 ret = spi_register_driver(&wm8711_spi_driver);
611 if (ret != 0) {
612 printk(KERN_ERR "Failed to register WM8711 SPI driver: %d\n",
613 ret);
614 }
615#endif
616 return 0;
617}
618module_init(wm8711_modinit);
619
620static void __exit wm8711_exit(void)
621{
622#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
623 i2c_del_driver(&wm8711_i2c_driver);
624#endif
625#if defined(CONFIG_SPI_MASTER)
626 spi_unregister_driver(&wm8711_spi_driver);
627#endif
628}
629module_exit(wm8711_exit);
630
631MODULE_DESCRIPTION("ASoC WM8711 driver");
632MODULE_AUTHOR("Mike Arthur");
633MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8711.h b/sound/soc/codecs/wm8711.h
new file mode 100644
index 000000000000..381e84a43816
--- /dev/null
+++ b/sound/soc/codecs/wm8711.h
@@ -0,0 +1,42 @@
1/*
2 * wm8711.h -- WM8711 Soc Audio driver
3 *
4 * Copyright 2006 Wolfson Microelectronics
5 *
6 * Author: Mike Arthur <linux@wolfsonmicro.com>
7 *
8 * Based on wm8731.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _WM8711_H
16#define _WM8711_H
17
18/* WM8711 register space */
19
20#define WM8711_LOUT1V 0x02
21#define WM8711_ROUT1V 0x03
22#define WM8711_APANA 0x04
23#define WM8711_APDIGI 0x05
24#define WM8711_PWR 0x06
25#define WM8711_IFACE 0x07
26#define WM8711_SRATE 0x08
27#define WM8711_ACTIVE 0x09
28#define WM8711_RESET 0x0f
29
30#define WM8711_CACHEREGNUM 8
31
32#define WM8711_SYSCLK 0
33#define WM8711_DAI 0
34
35struct wm8711_setup_data {
36 unsigned short i2c_address;
37};
38
39extern struct snd_soc_dai wm8711_dai;
40extern struct snd_soc_codec_device soc_codec_dev_wm8711;
41
42#endif
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..3fb653ba363a 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -74,8 +74,6 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
74 74
75 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 75 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
76 76
77 snd_soc_dapm_new_widgets(codec);
78
79 return 0; 77 return 0;
80} 78}
81 79
@@ -287,17 +285,9 @@ static int wm8728_init(struct snd_soc_device *socdev,
287 snd_soc_add_controls(codec, wm8728_snd_controls, 285 snd_soc_add_controls(codec, wm8728_snd_controls,
288 ARRAY_SIZE(wm8728_snd_controls)); 286 ARRAY_SIZE(wm8728_snd_controls));
289 wm8728_add_widgets(codec); 287 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 288
296 return ret; 289 return ret;
297 290
298card_err:
299 snd_soc_free_pcms(socdev);
300 snd_soc_dapm_free(socdev);
301err: 291err:
302 kfree(codec->reg_cache); 292 kfree(codec->reg_cache);
303 return ret; 293 return ret;
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index d3fd4f28d96e..3a497810f939 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};
@@ -149,7 +159,6 @@ static int wm8731_add_widgets(struct snd_soc_codec *codec)
149 159
150 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 160 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
151 161
152 snd_soc_dapm_new_widgets(codec);
153 return 0; 162 return 0;
154} 163}
155 164
@@ -422,9 +431,12 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
422{ 431{
423 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 432 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
424 struct snd_soc_codec *codec = socdev->card->codec; 433 struct snd_soc_codec *codec = socdev->card->codec;
434 struct wm8731_priv *wm8731 = codec->private_data;
425 435
426 snd_soc_write(codec, WM8731_ACTIVE, 0x0); 436 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
427 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 437 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
438 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
439 wm8731->supplies);
428 return 0; 440 return 0;
429} 441}
430 442
@@ -432,10 +444,16 @@ static int wm8731_resume(struct platform_device *pdev)
432{ 444{
433 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 445 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
434 struct snd_soc_codec *codec = socdev->card->codec; 446 struct snd_soc_codec *codec = socdev->card->codec;
435 int i; 447 struct wm8731_priv *wm8731 = codec->private_data;
448 int i, ret;
436 u8 data[2]; 449 u8 data[2];
437 u16 *cache = codec->reg_cache; 450 u16 *cache = codec->reg_cache;
438 451
452 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
453 wm8731->supplies);
454 if (ret != 0)
455 return ret;
456
439 /* Sync reg_cache with the hardware */ 457 /* Sync reg_cache with the hardware */
440 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) { 458 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
441 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001); 459 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
@@ -444,6 +462,7 @@ static int wm8731_resume(struct platform_device *pdev)
444 } 462 }
445 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 463 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
446 wm8731_set_bias_level(codec, codec->suspend_bias_level); 464 wm8731_set_bias_level(codec, codec->suspend_bias_level);
465
447 return 0; 466 return 0;
448} 467}
449#else 468#else
@@ -475,17 +494,9 @@ static int wm8731_probe(struct platform_device *pdev)
475 snd_soc_add_controls(codec, wm8731_snd_controls, 494 snd_soc_add_controls(codec, wm8731_snd_controls,
476 ARRAY_SIZE(wm8731_snd_controls)); 495 ARRAY_SIZE(wm8731_snd_controls));
477 wm8731_add_widgets(codec); 496 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 497
484 return ret; 498 return ret;
485 499
486card_err:
487 snd_soc_free_pcms(socdev);
488 snd_soc_dapm_free(socdev);
489pcm_err: 500pcm_err:
490 return ret; 501 return ret;
491} 502}
@@ -512,7 +523,7 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
512static int wm8731_register(struct wm8731_priv *wm8731, 523static int wm8731_register(struct wm8731_priv *wm8731,
513 enum snd_soc_control_type control) 524 enum snd_soc_control_type control)
514{ 525{
515 int ret; 526 int ret, i;
516 struct snd_soc_codec *codec = &wm8731->codec; 527 struct snd_soc_codec *codec = &wm8731->codec;
517 528
518 if (wm8731_codec) { 529 if (wm8731_codec) {
@@ -543,10 +554,27 @@ static int wm8731_register(struct wm8731_priv *wm8731,
543 goto err; 554 goto err;
544 } 555 }
545 556
557 for (i = 0; i < ARRAY_SIZE(wm8731->supplies); i++)
558 wm8731->supplies[i].supply = wm8731_supply_names[i];
559
560 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8731->supplies),
561 wm8731->supplies);
562 if (ret != 0) {
563 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
564 goto err;
565 }
566
567 ret = regulator_bulk_enable(ARRAY_SIZE(wm8731->supplies),
568 wm8731->supplies);
569 if (ret != 0) {
570 dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
571 goto err_regulator_get;
572 }
573
546 ret = wm8731_reset(codec); 574 ret = wm8731_reset(codec);
547 if (ret < 0) { 575 if (ret < 0) {
548 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 576 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
549 goto err; 577 goto err_regulator_enable;
550 } 578 }
551 579
552 wm8731_dai.dev = codec->dev; 580 wm8731_dai.dev = codec->dev;
@@ -567,7 +595,7 @@ static int wm8731_register(struct wm8731_priv *wm8731,
567 ret = snd_soc_register_codec(codec); 595 ret = snd_soc_register_codec(codec);
568 if (ret != 0) { 596 if (ret != 0) {
569 dev_err(codec->dev, "Failed to register codec: %d\n", ret); 597 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
570 goto err; 598 goto err_regulator_enable;
571 } 599 }
572 600
573 ret = snd_soc_register_dai(&wm8731_dai); 601 ret = snd_soc_register_dai(&wm8731_dai);
@@ -581,6 +609,10 @@ static int wm8731_register(struct wm8731_priv *wm8731,
581 609
582err_codec: 610err_codec:
583 snd_soc_unregister_codec(codec); 611 snd_soc_unregister_codec(codec);
612err_regulator_enable:
613 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
614err_regulator_get:
615 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
584err: 616err:
585 kfree(wm8731); 617 kfree(wm8731);
586 return ret; 618 return ret;
@@ -591,6 +623,8 @@ static void wm8731_unregister(struct wm8731_priv *wm8731)
591 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF); 623 wm8731_set_bias_level(&wm8731->codec, SND_SOC_BIAS_OFF);
592 snd_soc_unregister_dai(&wm8731_dai); 624 snd_soc_unregister_dai(&wm8731_dai);
593 snd_soc_unregister_codec(&wm8731->codec); 625 snd_soc_unregister_codec(&wm8731->codec);
626 regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
627 regulator_bulk_free(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
594 kfree(wm8731); 628 kfree(wm8731);
595 wm8731_codec = NULL; 629 wm8731_codec = NULL;
596} 630}
@@ -623,21 +657,6 @@ static int __devexit wm8731_spi_remove(struct spi_device *spi)
623 return 0; 657 return 0;
624} 658}
625 659
626#ifdef CONFIG_PM
627static int wm8731_spi_suspend(struct spi_device *spi, pm_message_t msg)
628{
629 return snd_soc_suspend_device(&spi->dev);
630}
631
632static int wm8731_spi_resume(struct spi_device *spi)
633{
634 return snd_soc_resume_device(&spi->dev);
635}
636#else
637#define wm8731_spi_suspend NULL
638#define wm8731_spi_resume NULL
639#endif
640
641static struct spi_driver wm8731_spi_driver = { 660static struct spi_driver wm8731_spi_driver = {
642 .driver = { 661 .driver = {
643 .name = "wm8731", 662 .name = "wm8731",
@@ -645,8 +664,6 @@ static struct spi_driver wm8731_spi_driver = {
645 .owner = THIS_MODULE, 664 .owner = THIS_MODULE,
646 }, 665 },
647 .probe = wm8731_spi_probe, 666 .probe = wm8731_spi_probe,
648 .suspend = wm8731_spi_suspend,
649 .resume = wm8731_spi_resume,
650 .remove = __devexit_p(wm8731_spi_remove), 667 .remove = __devexit_p(wm8731_spi_remove),
651}; 668};
652#endif /* CONFIG_SPI_MASTER */ 669#endif /* CONFIG_SPI_MASTER */
@@ -679,21 +696,6 @@ static __devexit int wm8731_i2c_remove(struct i2c_client *client)
679 return 0; 696 return 0;
680} 697}
681 698
682#ifdef CONFIG_PM
683static int wm8731_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
684{
685 return snd_soc_suspend_device(&i2c->dev);
686}
687
688static int wm8731_i2c_resume(struct i2c_client *i2c)
689{
690 return snd_soc_resume_device(&i2c->dev);
691}
692#else
693#define wm8731_i2c_suspend NULL
694#define wm8731_i2c_resume NULL
695#endif
696
697static const struct i2c_device_id wm8731_i2c_id[] = { 699static const struct i2c_device_id wm8731_i2c_id[] = {
698 { "wm8731", 0 }, 700 { "wm8731", 0 },
699 { } 701 { }
@@ -707,8 +709,6 @@ static struct i2c_driver wm8731_i2c_driver = {
707 }, 709 },
708 .probe = wm8731_i2c_probe, 710 .probe = wm8731_i2c_probe,
709 .remove = __devexit_p(wm8731_i2c_remove), 711 .remove = __devexit_p(wm8731_i2c_remove),
710 .suspend = wm8731_i2c_suspend,
711 .resume = wm8731_i2c_resume,
712 .id_table = wm8731_i2c_id, 712 .id_table = wm8731_i2c_id,
713}; 713};
714#endif 714#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 4ba1e7e93fb4..475c67ac7818 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -403,7 +403,6 @@ static int wm8750_add_widgets(struct snd_soc_codec *codec)
403 403
404 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 404 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
405 405
406 snd_soc_dapm_new_widgets(codec);
407 return 0; 406 return 0;
408} 407}
409 408
@@ -772,16 +771,8 @@ static int wm8750_init(struct snd_soc_device *socdev,
772 snd_soc_add_controls(codec, wm8750_snd_controls, 771 snd_soc_add_controls(codec, wm8750_snd_controls,
773 ARRAY_SIZE(wm8750_snd_controls)); 772 ARRAY_SIZE(wm8750_snd_controls));
774 wm8750_add_widgets(codec); 773 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; 774 return ret;
781 775
782card_err:
783 snd_soc_free_pcms(socdev);
784 snd_soc_dapm_free(socdev);
785err: 776err:
786 kfree(codec->reg_cache); 777 kfree(codec->reg_cache);
787 return ret; 778 return ret;
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 5ad677ce80da..d6850dacda29 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -673,7 +673,6 @@ static int wm8753_add_widgets(struct snd_soc_codec *codec)
673 673
674 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 674 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
675 675
676 snd_soc_dapm_new_widgets(codec);
677 return 0; 676 return 0;
678} 677}
679 678
@@ -724,8 +723,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
724 pll_div->k = K; 723 pll_div->k = K;
725} 724}
726 725
727static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, 726static int wm8753_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
728 int pll_id, unsigned int freq_in, unsigned int freq_out) 727 int source, unsigned int freq_in, unsigned int freq_out)
729{ 728{
730 u16 reg, enable; 729 u16 reg, enable;
731 int offset; 730 int offset;
@@ -1583,18 +1582,9 @@ static int wm8753_probe(struct platform_device *pdev)
1583 snd_soc_add_controls(codec, wm8753_snd_controls, 1582 snd_soc_add_controls(codec, wm8753_snd_controls,
1584 ARRAY_SIZE(wm8753_snd_controls)); 1583 ARRAY_SIZE(wm8753_snd_controls));
1585 wm8753_add_widgets(codec); 1584 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 1585
1592 return 0; 1586 return 0;
1593 1587
1594card_err:
1595 snd_soc_free_pcms(socdev);
1596 snd_soc_dapm_free(socdev);
1597
1598pcm_err: 1588pcm_err:
1599 return ret; 1589 return ret;
1600} 1590}
@@ -1767,21 +1757,6 @@ static int wm8753_i2c_remove(struct i2c_client *client)
1767 return 0; 1757 return 0;
1768} 1758}
1769 1759
1770#ifdef CONFIG_PM
1771static int wm8753_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1772{
1773 return snd_soc_suspend_device(&client->dev);
1774}
1775
1776static int wm8753_i2c_resume(struct i2c_client *client)
1777{
1778 return snd_soc_resume_device(&client->dev);
1779}
1780#else
1781#define wm8753_i2c_suspend NULL
1782#define wm8753_i2c_resume NULL
1783#endif
1784
1785static const struct i2c_device_id wm8753_i2c_id[] = { 1760static const struct i2c_device_id wm8753_i2c_id[] = {
1786 { "wm8753", 0 }, 1761 { "wm8753", 0 },
1787 { } 1762 { }
@@ -1795,8 +1770,6 @@ static struct i2c_driver wm8753_i2c_driver = {
1795 }, 1770 },
1796 .probe = wm8753_i2c_probe, 1771 .probe = wm8753_i2c_probe,
1797 .remove = wm8753_i2c_remove, 1772 .remove = wm8753_i2c_remove,
1798 .suspend = wm8753_i2c_suspend,
1799 .resume = wm8753_i2c_resume,
1800 .id_table = wm8753_i2c_id, 1773 .id_table = wm8753_i2c_id,
1801}; 1774};
1802#endif 1775#endif
@@ -1852,22 +1825,6 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi)
1852 return 0; 1825 return 0;
1853} 1826}
1854 1827
1855#ifdef CONFIG_PM
1856static int wm8753_spi_suspend(struct spi_device *spi, pm_message_t msg)
1857{
1858 return snd_soc_suspend_device(&spi->dev);
1859}
1860
1861static int wm8753_spi_resume(struct spi_device *spi)
1862{
1863 return snd_soc_resume_device(&spi->dev);
1864}
1865
1866#else
1867#define wm8753_spi_suspend NULL
1868#define wm8753_spi_resume NULL
1869#endif
1870
1871static struct spi_driver wm8753_spi_driver = { 1828static struct spi_driver wm8753_spi_driver = {
1872 .driver = { 1829 .driver = {
1873 .name = "wm8753", 1830 .name = "wm8753",
@@ -1876,8 +1833,6 @@ static struct spi_driver wm8753_spi_driver = {
1876 }, 1833 },
1877 .probe = wm8753_spi_probe, 1834 .probe = wm8753_spi_probe,
1878 .remove = __devexit_p(wm8753_spi_remove), 1835 .remove = __devexit_p(wm8753_spi_remove),
1879 .suspend = wm8753_spi_suspend,
1880 .resume = wm8753_spi_resume,
1881}; 1836};
1882#endif 1837#endif
1883 1838
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index a9829aa26e53..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}
@@ -616,21 +607,6 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi)
616 return 0; 607 return 0;
617} 608}
618 609
619#ifdef CONFIG_PM
620static int wm8776_spi_suspend(struct spi_device *spi, pm_message_t msg)
621{
622 return snd_soc_suspend_device(&spi->dev);
623}
624
625static int wm8776_spi_resume(struct spi_device *spi)
626{
627 return snd_soc_resume_device(&spi->dev);
628}
629#else
630#define wm8776_spi_suspend NULL
631#define wm8776_spi_resume NULL
632#endif
633
634static struct spi_driver wm8776_spi_driver = { 610static struct spi_driver wm8776_spi_driver = {
635 .driver = { 611 .driver = {
636 .name = "wm8776", 612 .name = "wm8776",
@@ -638,8 +614,6 @@ static struct spi_driver wm8776_spi_driver = {
638 .owner = THIS_MODULE, 614 .owner = THIS_MODULE,
639 }, 615 },
640 .probe = wm8776_spi_probe, 616 .probe = wm8776_spi_probe,
641 .suspend = wm8776_spi_suspend,
642 .resume = wm8776_spi_resume,
643 .remove = __devexit_p(wm8776_spi_remove), 617 .remove = __devexit_p(wm8776_spi_remove),
644}; 618};
645#endif /* CONFIG_SPI_MASTER */ 619#endif /* CONFIG_SPI_MASTER */
@@ -673,21 +647,6 @@ static __devexit int wm8776_i2c_remove(struct i2c_client *client)
673 return 0; 647 return 0;
674} 648}
675 649
676#ifdef CONFIG_PM
677static int wm8776_i2c_suspend(struct i2c_client *i2c, pm_message_t msg)
678{
679 return snd_soc_suspend_device(&i2c->dev);
680}
681
682static int wm8776_i2c_resume(struct i2c_client *i2c)
683{
684 return snd_soc_resume_device(&i2c->dev);
685}
686#else
687#define wm8776_i2c_suspend NULL
688#define wm8776_i2c_resume NULL
689#endif
690
691static const struct i2c_device_id wm8776_i2c_id[] = { 650static const struct i2c_device_id wm8776_i2c_id[] = {
692 { "wm8776", 0 }, 651 { "wm8776", 0 },
693 { } 652 { }
@@ -701,8 +660,6 @@ static struct i2c_driver wm8776_i2c_driver = {
701 }, 660 },
702 .probe = wm8776_i2c_probe, 661 .probe = wm8776_i2c_probe,
703 .remove = __devexit_p(wm8776_i2c_remove), 662 .remove = __devexit_p(wm8776_i2c_remove),
704 .suspend = wm8776_i2c_suspend,
705 .resume = wm8776_i2c_resume,
706 .id_table = wm8776_i2c_id, 663 .id_table = wm8776_i2c_id,
707}; 664};
708#endif 665#endif
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 5e9c855c0036..c9438dd62df3 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -618,8 +618,6 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
618 618
619 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 619 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
620 620
621 snd_soc_dapm_new_widgets(codec);
622
623 return 0; 621 return 0;
624} 622}
625 623
@@ -814,8 +812,8 @@ reenable:
814 return 0; 812 return 0;
815} 813}
816 814
817static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, 815static int wm8900_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
818 int pll_id, unsigned int freq_in, unsigned int freq_out) 816 int source, unsigned int freq_in, unsigned int freq_out)
819{ 817{
820 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out); 818 return wm8900_set_fll(codec_dai->codec, pll_id, freq_in, freq_out);
821} 819}
@@ -1312,21 +1310,6 @@ static __devexit int wm8900_i2c_remove(struct i2c_client *client)
1312 return 0; 1310 return 0;
1313} 1311}
1314 1312
1315#ifdef CONFIG_PM
1316static int wm8900_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1317{
1318 return snd_soc_suspend_device(&client->dev);
1319}
1320
1321static int wm8900_i2c_resume(struct i2c_client *client)
1322{
1323 return snd_soc_resume_device(&client->dev);
1324}
1325#else
1326#define wm8900_i2c_suspend NULL
1327#define wm8900_i2c_resume NULL
1328#endif
1329
1330static const struct i2c_device_id wm8900_i2c_id[] = { 1313static const struct i2c_device_id wm8900_i2c_id[] = {
1331 { "wm8900", 0 }, 1314 { "wm8900", 0 },
1332 { } 1315 { }
@@ -1340,8 +1323,6 @@ static struct i2c_driver wm8900_i2c_driver = {
1340 }, 1323 },
1341 .probe = wm8900_i2c_probe, 1324 .probe = wm8900_i2c_probe,
1342 .remove = __devexit_p(wm8900_i2c_remove), 1325 .remove = __devexit_p(wm8900_i2c_remove),
1343 .suspend = wm8900_i2c_suspend,
1344 .resume = wm8900_i2c_resume,
1345 .id_table = wm8900_i2c_id, 1326 .id_table = wm8900_i2c_id,
1346}; 1327};
1347 1328
@@ -1370,17 +1351,6 @@ static int wm8900_probe(struct platform_device *pdev)
1370 ARRAY_SIZE(wm8900_snd_controls)); 1351 ARRAY_SIZE(wm8900_snd_controls));
1371 wm8900_add_widgets(codec); 1352 wm8900_add_widgets(codec);
1372 1353
1373 ret = snd_soc_init_card(socdev);
1374 if (ret < 0) {
1375 dev_err(&pdev->dev, "Failed to register card\n");
1376 goto card_err;
1377 }
1378
1379 return ret;
1380
1381card_err:
1382 snd_soc_free_pcms(socdev);
1383 snd_soc_dapm_free(socdev);
1384pcm_err: 1354pcm_err:
1385 return ret; 1355 return ret;
1386} 1356}
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index fe1307b500cf..b8cae1758642 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -919,8 +919,6 @@ static int wm8903_add_widgets(struct snd_soc_codec *codec)
919 919
920 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); 920 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
921 921
922 snd_soc_dapm_new_widgets(codec);
923
924 return 0; 922 return 0;
925} 923}
926 924
@@ -1655,21 +1653,6 @@ static __devexit int wm8903_i2c_remove(struct i2c_client *client)
1655 return 0; 1653 return 0;
1656} 1654}
1657 1655
1658#ifdef CONFIG_PM
1659static int wm8903_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1660{
1661 return snd_soc_suspend_device(&client->dev);
1662}
1663
1664static int wm8903_i2c_resume(struct i2c_client *client)
1665{
1666 return snd_soc_resume_device(&client->dev);
1667}
1668#else
1669#define wm8903_i2c_suspend NULL
1670#define wm8903_i2c_resume NULL
1671#endif
1672
1673/* i2c codec control layer */ 1656/* i2c codec control layer */
1674static const struct i2c_device_id wm8903_i2c_id[] = { 1657static const struct i2c_device_id wm8903_i2c_id[] = {
1675 { "wm8903", 0 }, 1658 { "wm8903", 0 },
@@ -1684,8 +1667,6 @@ static struct i2c_driver wm8903_i2c_driver = {
1684 }, 1667 },
1685 .probe = wm8903_i2c_probe, 1668 .probe = wm8903_i2c_probe,
1686 .remove = __devexit_p(wm8903_i2c_remove), 1669 .remove = __devexit_p(wm8903_i2c_remove),
1687 .suspend = wm8903_i2c_suspend,
1688 .resume = wm8903_i2c_resume,
1689 .id_table = wm8903_i2c_id, 1670 .id_table = wm8903_i2c_id,
1690}; 1671};
1691 1672
@@ -1712,17 +1693,8 @@ static int wm8903_probe(struct platform_device *pdev)
1712 ARRAY_SIZE(wm8903_snd_controls)); 1693 ARRAY_SIZE(wm8903_snd_controls));
1713 wm8903_add_widgets(socdev->card->codec); 1694 wm8903_add_widgets(socdev->card->codec);
1714 1695
1715 ret = snd_soc_init_card(socdev);
1716 if (ret < 0) {
1717 dev_err(&pdev->dev, "wm8903: failed to register card\n");
1718 goto card_err;
1719 }
1720
1721 return ret; 1696 return ret;
1722 1697
1723card_err:
1724 snd_soc_free_pcms(socdev);
1725 snd_soc_dapm_free(socdev);
1726err: 1698err:
1727 return ret; 1699 return ret;
1728} 1700}
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 1ef2454c5205..3d850b97037a 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -298,7 +298,6 @@ static int wm8940_add_widgets(struct snd_soc_codec *codec)
298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 298 ret = snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
299 if (ret) 299 if (ret)
300 goto error_ret; 300 goto error_ret;
301 ret = snd_soc_dapm_new_widgets(codec);
302 301
303error_ret: 302error_ret:
304 return ret; 303 return ret;
@@ -536,8 +535,8 @@ static void pll_factors(unsigned int target, unsigned int source)
536} 535}
537 536
538/* Untested at the moment */ 537/* Untested at the moment */
539static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, 538static int wm8940_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
540 int pll_id, unsigned int freq_in, unsigned int freq_out) 539 int source, unsigned int freq_in, unsigned int freq_out)
541{ 540{
542 struct snd_soc_codec *codec = codec_dai->codec; 541 struct snd_soc_codec *codec = codec_dai->codec;
543 u16 reg; 542 u16 reg;
@@ -731,12 +730,6 @@ static int wm8940_probe(struct platform_device *pdev)
731 if (ret) 730 if (ret)
732 goto error_free_pcms; 731 goto error_free_pcms;
733 732
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; 733 return ret;
741 734
742error_free_pcms: 735error_free_pcms:
@@ -877,21 +870,6 @@ static int __devexit wm8940_i2c_remove(struct i2c_client *client)
877 return 0; 870 return 0;
878} 871}
879 872
880#ifdef CONFIG_PM
881static int wm8940_i2c_suspend(struct i2c_client *client, pm_message_t msg)
882{
883 return snd_soc_suspend_device(&client->dev);
884}
885
886static int wm8940_i2c_resume(struct i2c_client *client)
887{
888 return snd_soc_resume_device(&client->dev);
889}
890#else
891#define wm8940_i2c_suspend NULL
892#define wm8940_i2c_resume NULL
893#endif
894
895static const struct i2c_device_id wm8940_i2c_id[] = { 873static const struct i2c_device_id wm8940_i2c_id[] = {
896 { "wm8940", 0 }, 874 { "wm8940", 0 },
897 { } 875 { }
@@ -905,8 +883,6 @@ static struct i2c_driver wm8940_i2c_driver = {
905 }, 883 },
906 .probe = wm8940_i2c_probe, 884 .probe = wm8940_i2c_probe,
907 .remove = __devexit_p(wm8940_i2c_remove), 885 .remove = __devexit_p(wm8940_i2c_remove),
908 .suspend = wm8940_i2c_suspend,
909 .resume = wm8940_i2c_resume,
910 .id_table = wm8940_i2c_id, 886 .id_table = wm8940_i2c_id,
911}; 887};
912 888
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index f59703be61c8..d07bcc1e1c60 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -307,7 +307,6 @@ static int wm8960_add_widgets(struct snd_soc_codec *codec)
307 307
308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); 308 snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths));
309 309
310 snd_soc_dapm_new_widgets(codec);
311 return 0; 310 return 0;
312} 311}
313 312
@@ -540,8 +539,8 @@ static int pll_factors(unsigned int source, unsigned int target,
540 return 0; 539 return 0;
541} 540}
542 541
543static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, 542static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
544 int pll_id, unsigned int freq_in, unsigned int freq_out) 543 int source, unsigned int freq_in, unsigned int freq_out)
545{ 544{
546 struct snd_soc_codec *codec = codec_dai->codec; 545 struct snd_soc_codec *codec = codec_dai->codec;
547 u16 reg; 546 u16 reg;
@@ -713,17 +712,9 @@ static int wm8960_probe(struct platform_device *pdev)
713 snd_soc_add_controls(codec, wm8960_snd_controls, 712 snd_soc_add_controls(codec, wm8960_snd_controls,
714 ARRAY_SIZE(wm8960_snd_controls)); 713 ARRAY_SIZE(wm8960_snd_controls));
715 wm8960_add_widgets(codec); 714 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 715
722 return ret; 716 return ret;
723 717
724card_err:
725 snd_soc_free_pcms(socdev);
726 snd_soc_dapm_free(socdev);
727pcm_err: 718pcm_err:
728 return ret; 719 return ret;
729} 720}
@@ -883,21 +874,6 @@ static __devexit int wm8960_i2c_remove(struct i2c_client *client)
883 return 0; 874 return 0;
884} 875}
885 876
886#ifdef CONFIG_PM
887static int wm8960_i2c_suspend(struct i2c_client *client, pm_message_t msg)
888{
889 return snd_soc_suspend_device(&client->dev);
890}
891
892static int wm8960_i2c_resume(struct i2c_client *client)
893{
894 return snd_soc_resume_device(&client->dev);
895}
896#else
897#define wm8960_i2c_suspend NULL
898#define wm8960_i2c_resume NULL
899#endif
900
901static const struct i2c_device_id wm8960_i2c_id[] = { 877static const struct i2c_device_id wm8960_i2c_id[] = {
902 { "wm8960", 0 }, 878 { "wm8960", 0 },
903 { } 879 { }
@@ -911,8 +887,6 @@ static struct i2c_driver wm8960_i2c_driver = {
911 }, 887 },
912 .probe = wm8960_i2c_probe, 888 .probe = wm8960_i2c_probe,
913 .remove = __devexit_p(wm8960_i2c_remove), 889 .remove = __devexit_p(wm8960_i2c_remove),
914 .suspend = wm8960_i2c_suspend,
915 .resume = wm8960_i2c_resume,
916 .id_table = wm8960_i2c_id, 890 .id_table = wm8960_i2c_id,
917}; 891};
918 892
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index 503032085899..a8007d58813f 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -986,19 +986,9 @@ static int wm8961_probe(struct platform_device *pdev)
986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets, 986 snd_soc_dapm_new_controls(codec, wm8961_dapm_widgets,
987 ARRAY_SIZE(wm8961_dapm_widgets)); 987 ARRAY_SIZE(wm8961_dapm_widgets));
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);
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 989
997 return ret; 990 return ret;
998 991
999card_err:
1000 snd_soc_free_pcms(socdev);
1001 snd_soc_dapm_free(socdev);
1002pcm_err: 992pcm_err:
1003 return ret; 993 return ret;
1004} 994}
@@ -1206,21 +1196,6 @@ static __devexit int wm8961_i2c_remove(struct i2c_client *client)
1206 return 0; 1196 return 0;
1207} 1197}
1208 1198
1209#ifdef CONFIG_PM
1210static int wm8961_i2c_suspend(struct i2c_client *client, pm_message_t state)
1211{
1212 return snd_soc_suspend_device(&client->dev);
1213}
1214
1215static int wm8961_i2c_resume(struct i2c_client *client)
1216{
1217 return snd_soc_resume_device(&client->dev);
1218}
1219#else
1220#define wm8961_i2c_suspend NULL
1221#define wm8961_i2c_resume NULL
1222#endif
1223
1224static const struct i2c_device_id wm8961_i2c_id[] = { 1199static const struct i2c_device_id wm8961_i2c_id[] = {
1225 { "wm8961", 0 }, 1200 { "wm8961", 0 },
1226 { } 1201 { }
@@ -1234,8 +1209,6 @@ static struct i2c_driver wm8961_i2c_driver = {
1234 }, 1209 },
1235 .probe = wm8961_i2c_probe, 1210 .probe = wm8961_i2c_probe,
1236 .remove = __devexit_p(wm8961_i2c_remove), 1211 .remove = __devexit_p(wm8961_i2c_remove),
1237 .suspend = wm8961_i2c_suspend,
1238 .resume = wm8961_i2c_resume,
1239 .id_table = wm8961_i2c_id, 1212 .id_table = wm8961_i2c_id,
1240}; 1213};
1241 1214
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index d66efb0546ea..d9540d55fc89 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -338,8 +338,6 @@ static int wm8971_add_widgets(struct snd_soc_codec *codec)
338 338
339 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 339 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
340 340
341 snd_soc_dapm_new_widgets(codec);
342
343 return 0; 341 return 0;
344} 342}
345 343
@@ -703,16 +701,9 @@ static int wm8971_init(struct snd_soc_device *socdev,
703 snd_soc_add_controls(codec, wm8971_snd_controls, 701 snd_soc_add_controls(codec, wm8971_snd_controls,
704 ARRAY_SIZE(wm8971_snd_controls)); 702 ARRAY_SIZE(wm8971_snd_controls));
705 wm8971_add_widgets(codec); 703 wm8971_add_widgets(codec);
706 ret = snd_soc_init_card(socdev); 704
707 if (ret < 0) {
708 printk(KERN_ERR "wm8971: failed to register card\n");
709 goto card_err;
710 }
711 return ret; 705 return ret;
712 706
713card_err:
714 snd_soc_free_pcms(socdev);
715 snd_soc_dapm_free(socdev);
716err: 707err:
717 kfree(codec->reg_cache); 708 kfree(codec->reg_cache);
718 return ret; 709 return ret;
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 98d663afc97d..81c57b5c591c 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -276,41 +276,42 @@ static int wm8974_add_widgets(struct snd_soc_codec *codec)
276 276
277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 277 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
278 278
279 snd_soc_dapm_new_widgets(codec);
280 return 0; 279 return 0;
281} 280}
282 281
283struct pll_ { 282struct pll_ {
284 unsigned int pre_div:4; /* prescale - 1 */ 283 unsigned int pre_div:1;
285 unsigned int n:4; 284 unsigned int n:4;
286 unsigned int k; 285 unsigned int k;
287}; 286};
288 287
289static struct pll_ pll_div;
290
291/* The size in bits of the pll divide multiplied by 10 288/* The size in bits of the pll divide multiplied by 10
292 * to allow rounding later */ 289 * to allow rounding later */
293#define FIXED_PLL_SIZE ((1 << 24) * 10) 290#define FIXED_PLL_SIZE ((1 << 24) * 10)
294 291
295static void pll_factors(unsigned int target, unsigned int source) 292static void pll_factors(struct pll_ *pll_div,
293 unsigned int target, unsigned int source)
296{ 294{
297 unsigned long long Kpart; 295 unsigned long long Kpart;
298 unsigned int K, Ndiv, Nmod; 296 unsigned int K, Ndiv, Nmod;
299 297
298 /* There is a fixed divide by 4 in the output path */
299 target *= 4;
300
300 Ndiv = target / source; 301 Ndiv = target / source;
301 if (Ndiv < 6) { 302 if (Ndiv < 6) {
302 source >>= 1; 303 source /= 2;
303 pll_div.pre_div = 1; 304 pll_div->pre_div = 1;
304 Ndiv = target / source; 305 Ndiv = target / source;
305 } else 306 } else
306 pll_div.pre_div = 0; 307 pll_div->pre_div = 0;
307 308
308 if ((Ndiv < 6) || (Ndiv > 12)) 309 if ((Ndiv < 6) || (Ndiv > 12))
309 printk(KERN_WARNING 310 printk(KERN_WARNING
310 "WM8974 N value %u outwith recommended range!\n", 311 "WM8974 N value %u outwith recommended range!\n",
311 Ndiv); 312 Ndiv);
312 313
313 pll_div.n = Ndiv; 314 pll_div->n = Ndiv;
314 Nmod = target % source; 315 Nmod = target % source;
315 Kpart = FIXED_PLL_SIZE * (long long)Nmod; 316 Kpart = FIXED_PLL_SIZE * (long long)Nmod;
316 317
@@ -325,13 +326,14 @@ static void pll_factors(unsigned int target, unsigned int source)
325 /* Move down to proper range now rounding is done */ 326 /* Move down to proper range now rounding is done */
326 K /= 10; 327 K /= 10;
327 328
328 pll_div.k = K; 329 pll_div->k = K;
329} 330}
330 331
331static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, 332static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
332 int pll_id, unsigned int freq_in, unsigned int freq_out) 333 int source, unsigned int freq_in, unsigned int freq_out)
333{ 334{
334 struct snd_soc_codec *codec = codec_dai->codec; 335 struct snd_soc_codec *codec = codec_dai->codec;
336 struct pll_ pll_div;
335 u16 reg; 337 u16 reg;
336 338
337 if (freq_in == 0 || freq_out == 0) { 339 if (freq_in == 0 || freq_out == 0) {
@@ -345,7 +347,7 @@ static int wm8974_set_dai_pll(struct snd_soc_dai *codec_dai,
345 return 0; 347 return 0;
346 } 348 }
347 349
348 pll_factors(freq_out*4, freq_in); 350 pll_factors(&pll_div, freq_out, freq_in);
349 351
350 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n); 352 snd_soc_write(codec, WM8974_PLLN, (pll_div.pre_div << 4) | pll_div.n);
351 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18); 353 snd_soc_write(codec, WM8974_PLLK1, pll_div.k >> 18);
@@ -638,17 +640,9 @@ static int wm8974_probe(struct platform_device *pdev)
638 snd_soc_add_controls(codec, wm8974_snd_controls, 640 snd_soc_add_controls(codec, wm8974_snd_controls,
639 ARRAY_SIZE(wm8974_snd_controls)); 641 ARRAY_SIZE(wm8974_snd_controls));
640 wm8974_add_widgets(codec); 642 wm8974_add_widgets(codec);
641 ret = snd_soc_init_card(socdev);
642 if (ret < 0) {
643 dev_err(codec->dev, "failed to register card: %d\n", ret);
644 goto card_err;
645 }
646 643
647 return ret; 644 return ret;
648 645
649card_err:
650 snd_soc_free_pcms(socdev);
651 snd_soc_dapm_free(socdev);
652pcm_err: 646pcm_err:
653 return ret; 647 return ret;
654} 648}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 3f530f8a972a..2862e4dced27 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -790,19 +790,9 @@ static int wm8988_probe(struct platform_device *pdev)
790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets, 790 snd_soc_dapm_new_controls(codec, wm8988_dapm_widgets,
791 ARRAY_SIZE(wm8988_dapm_widgets)); 791 ARRAY_SIZE(wm8988_dapm_widgets));
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);
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 793
801 return ret; 794 return ret;
802 795
803card_err:
804 snd_soc_free_pcms(socdev);
805 snd_soc_dapm_free(socdev);
806pcm_err: 796pcm_err:
807 return ret; 797 return ret;
808} 798}
@@ -944,21 +934,6 @@ static int wm8988_i2c_remove(struct i2c_client *client)
944 return 0; 934 return 0;
945} 935}
946 936
947#ifdef CONFIG_PM
948static int wm8988_i2c_suspend(struct i2c_client *client, pm_message_t msg)
949{
950 return snd_soc_suspend_device(&client->dev);
951}
952
953static int wm8988_i2c_resume(struct i2c_client *client)
954{
955 return snd_soc_resume_device(&client->dev);
956}
957#else
958#define wm8988_i2c_suspend NULL
959#define wm8988_i2c_resume NULL
960#endif
961
962static const struct i2c_device_id wm8988_i2c_id[] = { 937static const struct i2c_device_id wm8988_i2c_id[] = {
963 { "wm8988", 0 }, 938 { "wm8988", 0 },
964 { } 939 { }
@@ -972,8 +947,6 @@ static struct i2c_driver wm8988_i2c_driver = {
972 }, 947 },
973 .probe = wm8988_i2c_probe, 948 .probe = wm8988_i2c_probe,
974 .remove = wm8988_i2c_remove, 949 .remove = wm8988_i2c_remove,
975 .suspend = wm8988_i2c_suspend,
976 .resume = wm8988_i2c_resume,
977 .id_table = wm8988_i2c_id, 950 .id_table = wm8988_i2c_id,
978}; 951};
979#endif 952#endif
@@ -1006,21 +979,6 @@ static int __devexit wm8988_spi_remove(struct spi_device *spi)
1006 return 0; 979 return 0;
1007} 980}
1008 981
1009#ifdef CONFIG_PM
1010static int wm8988_spi_suspend(struct spi_device *spi, pm_message_t msg)
1011{
1012 return snd_soc_suspend_device(&spi->dev);
1013}
1014
1015static int wm8988_spi_resume(struct spi_device *spi)
1016{
1017 return snd_soc_resume_device(&spi->dev);
1018}
1019#else
1020#define wm8988_spi_suspend NULL
1021#define wm8988_spi_resume NULL
1022#endif
1023
1024static struct spi_driver wm8988_spi_driver = { 982static struct spi_driver wm8988_spi_driver = {
1025 .driver = { 983 .driver = {
1026 .name = "wm8988", 984 .name = "wm8988",
@@ -1029,8 +987,6 @@ static struct spi_driver wm8988_spi_driver = {
1029 }, 987 },
1030 .probe = wm8988_spi_probe, 988 .probe = wm8988_spi_probe,
1031 .remove = __devexit_p(wm8988_spi_remove), 989 .remove = __devexit_p(wm8988_spi_remove),
1032 .suspend = wm8988_spi_suspend,
1033 .resume = wm8988_spi_resume,
1034}; 990};
1035#endif 991#endif
1036 992
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 2d702db4131d..341481e0e830 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -920,7 +920,6 @@ static int wm8990_add_widgets(struct snd_soc_codec *codec)
920 /* set up the WM8990 audio map */ 920 /* set up the WM8990 audio map */
921 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 921 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
922 922
923 snd_soc_dapm_new_widgets(codec);
924 return 0; 923 return 0;
925} 924}
926 925
@@ -972,8 +971,8 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
972 pll_div->k = K; 971 pll_div->k = K;
973} 972}
974 973
975static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, 974static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
976 int pll_id, unsigned int freq_in, unsigned int freq_out) 975 int source, unsigned int freq_in, unsigned int freq_out)
977{ 976{
978 u16 reg; 977 u16 reg;
979 struct snd_soc_codec *codec = codec_dai->codec; 978 struct snd_soc_codec *codec = codec_dai->codec;
@@ -1409,16 +1408,9 @@ static int wm8990_init(struct snd_soc_device *socdev)
1409 snd_soc_add_controls(codec, wm8990_snd_controls, 1408 snd_soc_add_controls(codec, wm8990_snd_controls,
1410 ARRAY_SIZE(wm8990_snd_controls)); 1409 ARRAY_SIZE(wm8990_snd_controls));
1411 wm8990_add_widgets(codec); 1410 wm8990_add_widgets(codec);
1412 ret = snd_soc_init_card(socdev); 1411
1413 if (ret < 0) {
1414 printk(KERN_ERR "wm8990: failed to register card\n");
1415 goto card_err;
1416 }
1417 return ret; 1412 return ret;
1418 1413
1419card_err:
1420 snd_soc_free_pcms(socdev);
1421 snd_soc_dapm_free(socdev);
1422pcm_err: 1414pcm_err:
1423 kfree(codec->reg_cache); 1415 kfree(codec->reg_cache);
1424 return ret; 1416 return ret;
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index d9987999e92c..5e32f2ed5fc2 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -422,7 +422,7 @@ static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
422 return 0; 422 return 0;
423} 423}
424 424
425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, 425static int wm8993_set_fll(struct snd_soc_dai *dai, int fll_id, int source,
426 unsigned int Fref, unsigned int Fout) 426 unsigned int Fref, unsigned int Fout)
427{ 427{
428 struct snd_soc_codec *codec = dai->codec; 428 struct snd_soc_codec *codec = dai->codec;
@@ -1464,19 +1464,8 @@ static int wm8993_probe(struct platform_device *pdev)
1464 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff, 1464 wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
1465 wm8993->pdata.lineout2_diff); 1465 wm8993->pdata.lineout2_diff);
1466 1466
1467 snd_soc_dapm_new_widgets(codec);
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; 1467 return ret;
1476 1468
1477card_err:
1478 snd_soc_free_pcms(socdev);
1479 snd_soc_dapm_free(socdev);
1480err: 1469err:
1481 return ret; 1470 return ret;
1482} 1471}
@@ -1572,33 +1561,15 @@ static int wm8993_i2c_probe(struct i2c_client *i2c,
1572 /* Use automatic clock configuration */ 1561 /* Use automatic clock configuration */
1573 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0); 1562 snd_soc_update_bits(codec, WM8993_CLOCKING_4, WM8993_SR_MODE, 0);
1574 1563
1575 if (!wm8993->pdata.lineout1_diff) 1564 wm_hubs_handle_analogue_pdata(codec, wm8993->pdata.lineout1_diff,
1576 snd_soc_update_bits(codec, WM8993_LINE_MIXER1, 1565 wm8993->pdata.lineout2_diff,
1577 WM8993_LINEOUT1_MODE, 1566 wm8993->pdata.lineout1fb,
1578 WM8993_LINEOUT1_MODE); 1567 wm8993->pdata.lineout2fb,
1579 if (!wm8993->pdata.lineout2_diff) 1568 wm8993->pdata.jd_scthr,
1580 snd_soc_update_bits(codec, WM8993_LINE_MIXER2, 1569 wm8993->pdata.jd_thr,
1581 WM8993_LINEOUT2_MODE, 1570 wm8993->pdata.micbias1_lvl,
1582 WM8993_LINEOUT2_MODE); 1571 wm8993->pdata.micbias2_lvl);
1583 1572
1584 if (wm8993->pdata.lineout1fb)
1585 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1586 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
1587
1588 if (wm8993->pdata.lineout2fb)
1589 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
1590 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
1591
1592 /* Apply the microphone bias/detection configuration - the
1593 * platform data is directly applicable to the register. */
1594 snd_soc_update_bits(codec, WM8993_MICBIAS,
1595 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
1596 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
1597 wm8993->pdata.jd_scthr << WM8993_JD_SCTHR_SHIFT |
1598 wm8993->pdata.jd_thr << WM8993_JD_THR_SHIFT |
1599 wm8993->pdata.micbias1_lvl |
1600 wm8993->pdata.micbias1_lvl << 1);
1601
1602 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 1573 ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
1603 if (ret != 0) 1574 if (ret != 0)
1604 goto err; 1575 goto err;
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 686e5aa97206..c468497314ba 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1262,19 +1262,9 @@ static int wm9081_probe(struct platform_device *pdev)
1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets, 1262 snd_soc_dapm_new_controls(codec, wm9081_dapm_widgets,
1263 ARRAY_SIZE(wm9081_dapm_widgets)); 1263 ARRAY_SIZE(wm9081_dapm_widgets));
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);
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 1265
1273 return ret; 1266 return ret;
1274 1267
1275card_err:
1276 snd_soc_free_pcms(socdev);
1277 snd_soc_dapm_free(socdev);
1278pcm_err: 1268pcm_err:
1279 return ret; 1269 return ret;
1280} 1270}
@@ -1452,21 +1442,6 @@ static __devexit int wm9081_i2c_remove(struct i2c_client *client)
1452 return 0; 1442 return 0;
1453} 1443}
1454 1444
1455#ifdef CONFIG_PM
1456static int wm9081_i2c_suspend(struct i2c_client *client, pm_message_t msg)
1457{
1458 return snd_soc_suspend_device(&client->dev);
1459}
1460
1461static int wm9081_i2c_resume(struct i2c_client *client)
1462{
1463 return snd_soc_resume_device(&client->dev);
1464}
1465#else
1466#define wm9081_i2c_suspend NULL
1467#define wm9081_i2c_resume NULL
1468#endif
1469
1470static const struct i2c_device_id wm9081_i2c_id[] = { 1445static const struct i2c_device_id wm9081_i2c_id[] = {
1471 { "wm9081", 0 }, 1446 { "wm9081", 0 },
1472 { } 1447 { }
@@ -1480,8 +1455,6 @@ static struct i2c_driver wm9081_i2c_driver = {
1480 }, 1455 },
1481 .probe = wm9081_i2c_probe, 1456 .probe = wm9081_i2c_probe,
1482 .remove = __devexit_p(wm9081_i2c_remove), 1457 .remove = __devexit_p(wm9081_i2c_remove),
1483 .suspend = wm9081_i2c_suspend,
1484 .resume = wm9081_i2c_resume,
1485 .id_table = wm9081_i2c_id, 1458 .id_table = wm9081_i2c_id,
1486}; 1459};
1487 1460
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index e7d2840d9e59..ec54c6da9856 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -205,7 +205,6 @@ static int wm9705_add_widgets(struct snd_soc_codec *codec)
205 snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets, 205 snd_soc_dapm_new_controls(codec, wm9705_dapm_widgets,
206 ARRAY_SIZE(wm9705_dapm_widgets)); 206 ARRAY_SIZE(wm9705_dapm_widgets));
207 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 207 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
208 snd_soc_dapm_new_widgets(codec);
209 208
210 return 0; 209 return 0;
211} 210}
@@ -403,12 +402,6 @@ static int wm9705_soc_probe(struct platform_device *pdev)
403 ARRAY_SIZE(wm9705_snd_ac97_controls)); 402 ARRAY_SIZE(wm9705_snd_ac97_controls));
404 wm9705_add_widgets(codec); 403 wm9705_add_widgets(codec);
405 404
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; 405 return 0;
413 406
414reset_err: 407reset_err:
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 1fd4e88f50cf..0ac1215dcd9b 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -436,7 +436,6 @@ static int wm9712_add_widgets(struct snd_soc_codec *codec)
436 436
437 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 437 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
438 438
439 snd_soc_dapm_new_widgets(codec);
440 return 0; 439 return 0;
441} 440}
442 441
@@ -695,17 +694,11 @@ static int wm9712_soc_probe(struct platform_device *pdev)
695 snd_soc_add_controls(codec, wm9712_snd_ac97_controls, 694 snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
696 ARRAY_SIZE(wm9712_snd_ac97_controls)); 695 ARRAY_SIZE(wm9712_snd_ac97_controls));
697 wm9712_add_widgets(codec); 696 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 697
704 return 0; 698 return 0;
705 699
706reset_err: 700reset_err:
707 snd_soc_free_pcms(socdev); 701 snd_soc_free_pcms(socdev);
708
709pcm_err: 702pcm_err:
710 snd_soc_free_ac97_codec(codec); 703 snd_soc_free_ac97_codec(codec);
711 704
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 60e360b10468..c58aab375edb 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -625,7 +625,6 @@ static int wm9713_add_widgets(struct snd_soc_codec *codec)
625 625
626 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 626 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
627 627
628 snd_soc_dapm_new_widgets(codec);
629 return 0; 628 return 0;
630} 629}
631 630
@@ -800,8 +799,8 @@ static int wm9713_set_pll(struct snd_soc_codec *codec,
800 return 0; 799 return 0;
801} 800}
802 801
803static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, 802static int wm9713_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
804 int pll_id, unsigned int freq_in, unsigned int freq_out) 803 int source, unsigned int freq_in, unsigned int freq_out)
805{ 804{
806 struct snd_soc_codec *codec = codec_dai->codec; 805 struct snd_soc_codec *codec = codec_dai->codec;
807 return wm9713_set_pll(codec, pll_id, freq_in, freq_out); 806 return wm9713_set_pll(codec, pll_id, freq_in, freq_out);
@@ -1247,14 +1246,11 @@ static int wm9713_soc_probe(struct platform_device *pdev)
1247 snd_soc_add_controls(codec, wm9713_snd_ac97_controls, 1246 snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
1248 ARRAY_SIZE(wm9713_snd_ac97_controls)); 1247 ARRAY_SIZE(wm9713_snd_ac97_controls));
1249 wm9713_add_widgets(codec); 1248 wm9713_add_widgets(codec);
1250 ret = snd_soc_init_card(socdev); 1249
1251 if (ret < 0)
1252 goto reset_err;
1253 return 0; 1250 return 0;
1254 1251
1255reset_err: 1252reset_err:
1256 snd_soc_free_pcms(socdev); 1253 snd_soc_free_pcms(socdev);
1257
1258pcm_err: 1254pcm_err:
1259 snd_soc_free_ac97_codec(codec); 1255 snd_soc_free_ac97_codec(codec);
1260 1256
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index e542027eea89..d73c30536a2c 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -438,11 +438,11 @@ static const struct snd_soc_dapm_widget analogue_dapm_widgets[] = {
438SND_SOC_DAPM_INPUT("IN1LN"), 438SND_SOC_DAPM_INPUT("IN1LN"),
439SND_SOC_DAPM_INPUT("IN1LP"), 439SND_SOC_DAPM_INPUT("IN1LP"),
440SND_SOC_DAPM_INPUT("IN2LN"), 440SND_SOC_DAPM_INPUT("IN2LN"),
441SND_SOC_DAPM_INPUT("IN2LP/VXRN"), 441SND_SOC_DAPM_INPUT("IN2LP:VXRN"),
442SND_SOC_DAPM_INPUT("IN1RN"), 442SND_SOC_DAPM_INPUT("IN1RN"),
443SND_SOC_DAPM_INPUT("IN1RP"), 443SND_SOC_DAPM_INPUT("IN1RP"),
444SND_SOC_DAPM_INPUT("IN2RN"), 444SND_SOC_DAPM_INPUT("IN2RN"),
445SND_SOC_DAPM_INPUT("IN2RP/VXRP"), 445SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
446 446
447SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0), 447SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
448SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0), 448SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
@@ -537,14 +537,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
537 { "IN1R PGA", "IN1RP Switch", "IN1RP" }, 537 { "IN1R PGA", "IN1RP Switch", "IN1RP" },
538 { "IN1R PGA", "IN1RN Switch", "IN1RN" }, 538 { "IN1R PGA", "IN1RN Switch", "IN1RN" },
539 539
540 { "IN2L PGA", "IN2LP Switch", "IN2LP/VXRN" }, 540 { "IN2L PGA", "IN2LP Switch", "IN2LP:VXRN" },
541 { "IN2L PGA", "IN2LN Switch", "IN2LN" }, 541 { "IN2L PGA", "IN2LN Switch", "IN2LN" },
542 542
543 { "IN2R PGA", "IN2RP Switch", "IN2RP/VXRP" }, 543 { "IN2R PGA", "IN2RP Switch", "IN2RP:VXRP" },
544 { "IN2R PGA", "IN2RN Switch", "IN2RN" }, 544 { "IN2R PGA", "IN2RN Switch", "IN2RN" },
545 545
546 { "Direct Voice", NULL, "IN2LP/VXRN" }, 546 { "Direct Voice", NULL, "IN2LP:VXRN" },
547 { "Direct Voice", NULL, "IN2RP/VXRP" }, 547 { "Direct Voice", NULL, "IN2RP:VXRP" },
548 548
549 { "MIXINL", "IN1L Switch", "IN1L PGA" }, 549 { "MIXINL", "IN1L Switch", "IN1L PGA" },
550 { "MIXINL", "IN2L Switch", "IN2L PGA" }, 550 { "MIXINL", "IN2L Switch", "IN2L PGA" },
@@ -565,7 +565,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
565 { "Left Output Mixer", "Right Input Switch", "MIXINR" }, 565 { "Left Output Mixer", "Right Input Switch", "MIXINR" },
566 { "Left Output Mixer", "IN2RN Switch", "IN2RN" }, 566 { "Left Output Mixer", "IN2RN Switch", "IN2RN" },
567 { "Left Output Mixer", "IN2LN Switch", "IN2LN" }, 567 { "Left Output Mixer", "IN2LN Switch", "IN2LN" },
568 { "Left Output Mixer", "IN2LP Switch", "IN2LP/VXRN" }, 568 { "Left Output Mixer", "IN2LP Switch", "IN2LP:VXRN" },
569 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" }, 569 { "Left Output Mixer", "IN1L Switch", "IN1L PGA" },
570 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" }, 570 { "Left Output Mixer", "IN1R Switch", "IN1R PGA" },
571 571
@@ -573,7 +573,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
573 { "Right Output Mixer", "Right Input Switch", "MIXINR" }, 573 { "Right Output Mixer", "Right Input Switch", "MIXINR" },
574 { "Right Output Mixer", "IN2LN Switch", "IN2LN" }, 574 { "Right Output Mixer", "IN2LN Switch", "IN2LN" },
575 { "Right Output Mixer", "IN2RN Switch", "IN2RN" }, 575 { "Right Output Mixer", "IN2RN Switch", "IN2RN" },
576 { "Right Output Mixer", "IN2RP Switch", "IN2RP/VXRP" }, 576 { "Right Output Mixer", "IN2RP Switch", "IN2RP:VXRP" },
577 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" }, 577 { "Right Output Mixer", "IN1L Switch", "IN1L PGA" },
578 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" }, 578 { "Right Output Mixer", "IN1R Switch", "IN1R PGA" },
579 579
@@ -738,6 +738,41 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
738} 738}
739EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); 739EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes);
740 740
741int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
742 int lineout1_diff, int lineout2_diff,
743 int lineout1fb, int lineout2fb,
744 int jd_scthr, int jd_thr, int micbias1_lvl,
745 int micbias2_lvl)
746{
747 if (!lineout1_diff)
748 snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
749 WM8993_LINEOUT1_MODE,
750 WM8993_LINEOUT1_MODE);
751 if (!lineout2_diff)
752 snd_soc_update_bits(codec, WM8993_LINE_MIXER2,
753 WM8993_LINEOUT2_MODE,
754 WM8993_LINEOUT2_MODE);
755
756 if (lineout1fb)
757 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
758 WM8993_LINEOUT1_FB, WM8993_LINEOUT1_FB);
759
760 if (lineout2fb)
761 snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
762 WM8993_LINEOUT2_FB, WM8993_LINEOUT2_FB);
763
764 snd_soc_update_bits(codec, WM8993_MICBIAS,
765 WM8993_JD_SCTHR_MASK | WM8993_JD_THR_MASK |
766 WM8993_MICB1_LVL | WM8993_MICB2_LVL,
767 jd_scthr << WM8993_JD_SCTHR_SHIFT |
768 jd_thr << WM8993_JD_THR_SHIFT |
769 micbias1_lvl |
770 micbias2_lvl << WM8993_MICB2_LVL_SHIFT);
771
772 return 0;
773}
774EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
775
741MODULE_DESCRIPTION("Shared support for Wolfson hubs products"); 776MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
742MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); 777MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
743MODULE_LICENSE("GPL"); 778MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index ec09cb6a2939..36d3fba1de8b 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -20,5 +20,10 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
20 20
21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); 21extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int); 22extern int wm_hubs_add_analogue_routes(struct snd_soc_codec *, int, int);
23extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
24 int lineout1_diff, int lineout2_diff,
25 int lineout1fb, int lineout2fb,
26 int jd_scthr, int jd_thr,
27 int micbias1_lvl, int micbias2_lvl);
23 28
24#endif 29#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 4dfd4ad9d90e..047ee39418c0 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -13,9 +13,9 @@ config SND_DAVINCI_SOC_MCASP
13 tristate 13 tristate
14 14
15config SND_DAVINCI_SOC_EVM 15config SND_DAVINCI_SOC_EVM
16 tristate "SoC Audio support for DaVinci DM6446 or DM355 EVM" 16 tristate "SoC Audio support for DaVinci DM6446, DM355 or DM365 EVM"
17 depends on SND_DAVINCI_SOC 17 depends on SND_DAVINCI_SOC
18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM 18 depends on MACH_DAVINCI_EVM || MACH_DAVINCI_DM355_EVM || MACH_DAVINCI_DM365_EVM
19 select SND_DAVINCI_SOC_I2S 19 select SND_DAVINCI_SOC_I2S
20 select SND_SOC_TLV320AIC3X 20 select SND_SOC_TLV320AIC3X
21 help 21 help
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index 67414f659405..7ccbe6684fc2 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -45,7 +45,8 @@ static int evm_hw_params(struct snd_pcm_substream *substream,
45 unsigned sysclk; 45 unsigned sysclk;
46 46
47 /* ASP1 on DM355 EVM is clocked by an external oscillator */ 47 /* ASP1 on DM355 EVM is clocked by an external oscillator */
48 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm()) 48 if (machine_is_davinci_dm355_evm() || machine_is_davinci_dm6467_evm() ||
49 machine_is_davinci_dm365_evm())
49 sysclk = 27000000; 50 sysclk = 27000000;
50 51
51 /* ASP0 in DM6446 EVM is clocked by U55, as configured by 52 /* ASP0 in DM6446 EVM is clocked by U55, as configured by
@@ -176,7 +177,7 @@ static struct snd_soc_dai_link da8xx_evm_dai = {
176 .ops = &evm_ops, 177 .ops = &evm_ops,
177}; 178};
178 179
179/* davinci-evm audio machine driver */ 180/* davinci dm6446, dm355 or dm365 evm audio machine driver */
180static struct snd_soc_card snd_soc_card_evm = { 181static struct snd_soc_card snd_soc_card_evm = {
181 .name = "DaVinci EVM", 182 .name = "DaVinci EVM",
182 .platform = &davinci_soc_platform, 183 .platform = &davinci_soc_platform,
@@ -243,7 +244,7 @@ static int __init evm_init(void)
243 int index; 244 int index;
244 int ret; 245 int ret;
245 246
246 if (machine_is_davinci_evm()) { 247 if (machine_is_davinci_evm() || machine_is_davinci_dm365_evm()) {
247 evm_snd_dev_data = &evm_snd_devdata; 248 evm_snd_dev_data = &evm_snd_devdata;
248 index = 0; 249 index = 0;
249 } else if (machine_is_davinci_dm355_evm()) { 250 } else if (machine_is_davinci_dm355_evm()) {
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 4ae707048021..6362ca05506e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -97,12 +97,24 @@ enum {
97 DAVINCI_MCBSP_WORD_32, 97 DAVINCI_MCBSP_WORD_32,
98}; 98};
99 99
100static const unsigned char data_type[SNDRV_PCM_FORMAT_S32_LE + 1] = {
101 [SNDRV_PCM_FORMAT_S8] = 1,
102 [SNDRV_PCM_FORMAT_S16_LE] = 2,
103 [SNDRV_PCM_FORMAT_S32_LE] = 4,
104};
105
106static const unsigned char asp_word_length[SNDRV_PCM_FORMAT_S32_LE + 1] = {
107 [SNDRV_PCM_FORMAT_S8] = DAVINCI_MCBSP_WORD_8,
108 [SNDRV_PCM_FORMAT_S16_LE] = DAVINCI_MCBSP_WORD_16,
109 [SNDRV_PCM_FORMAT_S32_LE] = DAVINCI_MCBSP_WORD_32,
110};
111
112static const unsigned char double_fmt[SNDRV_PCM_FORMAT_S32_LE + 1] = {
113 [SNDRV_PCM_FORMAT_S8] = SNDRV_PCM_FORMAT_S16_LE,
114 [SNDRV_PCM_FORMAT_S16_LE] = SNDRV_PCM_FORMAT_S32_LE,
115};
116
100struct davinci_mcbsp_dev { 117struct davinci_mcbsp_dev {
101 /*
102 * dma_params must be first because rtd->dai->cpu_dai->private_data
103 * is cast to a pointer of an array of struct davinci_pcm_dma_params in
104 * davinci_pcm_open.
105 */
106 struct davinci_pcm_dma_params dma_params[2]; 118 struct davinci_pcm_dma_params dma_params[2];
107 void __iomem *base; 119 void __iomem *base;
108#define MOD_DSP_A 0 120#define MOD_DSP_A 0
@@ -110,6 +122,27 @@ struct davinci_mcbsp_dev {
110 int mode; 122 int mode;
111 u32 pcr; 123 u32 pcr;
112 struct clk *clk; 124 struct clk *clk;
125 /*
126 * Combining both channels into 1 element will at least double the
127 * amount of time between servicing the dma channel, increase
128 * effiency, and reduce the chance of overrun/underrun. But,
129 * it will result in the left & right channels being swapped.
130 *
131 * If relabeling the left and right channels is not possible,
132 * you may want to let the codec know to swap them back.
133 *
134 * It may allow x10 the amount of time to service dma requests,
135 * if the codec is master and is using an unnecessarily fast bit clock
136 * (ie. tlvaic23b), independent of the sample rate. So, having an
137 * entire frame at once means it can be serviced at the sample rate
138 * instead of the bit clock rate.
139 *
140 * In the now unlikely case that an underrun still
141 * occurs, both the left and right samples will be repeated
142 * so that no pops are heard, and the left and right channels
143 * won't end up being swapped because of the underrun.
144 */
145 unsigned enable_channel_combine:1;
113}; 146};
114 147
115static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev, 148static inline void davinci_mcbsp_write_reg(struct davinci_mcbsp_dev *dev,
@@ -349,6 +382,8 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
349 int mcbsp_word_length; 382 int mcbsp_word_length;
350 unsigned int rcr, xcr, srgr; 383 unsigned int rcr, xcr, srgr;
351 u32 spcr; 384 u32 spcr;
385 snd_pcm_format_t fmt;
386 unsigned element_cnt = 1;
352 387
353 /* general line settings */ 388 /* general line settings */
354 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 389 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -378,27 +413,24 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
378 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1); 413 xcr |= DAVINCI_MCBSP_XCR_XDATDLY(1);
379 } 414 }
380 /* Determine xfer data type */ 415 /* Determine xfer data type */
381 switch (params_format(params)) { 416 fmt = params_format(params);
382 case SNDRV_PCM_FORMAT_S8: 417 if ((fmt > SNDRV_PCM_FORMAT_S32_LE) || !data_type[fmt]) {
383 dma_params->data_type = 1;
384 mcbsp_word_length = DAVINCI_MCBSP_WORD_8;
385 break;
386 case SNDRV_PCM_FORMAT_S16_LE:
387 dma_params->data_type = 2;
388 mcbsp_word_length = DAVINCI_MCBSP_WORD_16;
389 break;
390 case SNDRV_PCM_FORMAT_S32_LE:
391 dma_params->data_type = 4;
392 mcbsp_word_length = DAVINCI_MCBSP_WORD_32;
393 break;
394 default:
395 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n"); 418 printk(KERN_WARNING "davinci-i2s: unsupported PCM format\n");
396 return -EINVAL; 419 return -EINVAL;
397 } 420 }
398 421
399 dma_params->acnt = dma_params->data_type; 422 if (params_channels(params) == 2) {
400 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(1); 423 element_cnt = 2;
401 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(1); 424 if (double_fmt[fmt] && dev->enable_channel_combine) {
425 element_cnt = 1;
426 fmt = double_fmt[fmt];
427 }
428 }
429 dma_params->acnt = dma_params->data_type = data_type[fmt];
430 dma_params->fifo_level = 0;
431 mcbsp_word_length = asp_word_length[fmt];
432 rcr |= DAVINCI_MCBSP_RCR_RFRLEN1(element_cnt - 1);
433 xcr |= DAVINCI_MCBSP_XCR_XFRLEN1(element_cnt - 1);
402 434
403 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) | 435 rcr |= DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
404 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length); 436 DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length);
@@ -513,7 +545,13 @@ static int davinci_i2s_probe(struct platform_device *pdev)
513 ret = -ENOMEM; 545 ret = -ENOMEM;
514 goto err_release_region; 546 goto err_release_region;
515 } 547 }
516 548 if (pdata) {
549 dev->enable_channel_combine = pdata->enable_channel_combine;
550 dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size =
551 pdata->sram_size_playback;
552 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].sram_size =
553 pdata->sram_size_capture;
554 }
517 dev->clk = clk_get(&pdev->dev, NULL); 555 dev->clk = clk_get(&pdev->dev, NULL);
518 if (IS_ERR(dev->clk)) { 556 if (IS_ERR(dev->clk)) {
519 ret = -ENODEV; 557 ret = -ENODEV;
@@ -547,6 +585,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
547 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 585 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
548 586
549 davinci_i2s_dai.private_data = dev; 587 davinci_i2s_dai.private_data = dev;
588 davinci_i2s_dai.dma_data = dev->dma_params;
550 ret = snd_soc_register_dai(&davinci_i2s_dai); 589 ret = snd_soc_register_dai(&davinci_i2s_dai);
551 if (ret != 0) 590 if (ret != 0)
552 goto err_free_mem; 591 goto err_free_mem;
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 5d1f98a4c978..0a302e1080d9 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -714,16 +714,13 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
714 struct davinci_pcm_dma_params *dma_params = 714 struct davinci_pcm_dma_params *dma_params =
715 &dev->dma_params[substream->stream]; 715 &dev->dma_params[substream->stream];
716 int word_length; 716 int word_length;
717 u8 numevt; 717 u8 fifo_level;
718 718
719 davinci_hw_common_param(dev, substream->stream); 719 davinci_hw_common_param(dev, substream->stream);
720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 720 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
721 numevt = dev->txnumevt; 721 fifo_level = dev->txnumevt;
722 else 722 else
723 numevt = dev->rxnumevt; 723 fifo_level = dev->rxnumevt;
724
725 if (!numevt)
726 numevt = 1;
727 724
728 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE) 725 if (dev->op_mode == DAVINCI_MCASP_DIT_MODE)
729 davinci_hw_dit_param(dev); 726 davinci_hw_dit_param(dev);
@@ -751,12 +748,12 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
751 return -EINVAL; 748 return -EINVAL;
752 } 749 }
753 750
754 if (dev->version == MCASP_VERSION_2) { 751 if (dev->version == MCASP_VERSION_2 && !fifo_level)
755 dma_params->data_type *= numevt; 752 dma_params->acnt = 4;
756 dma_params->acnt = 4 * numevt; 753 else
757 } else
758 dma_params->acnt = dma_params->data_type; 754 dma_params->acnt = dma_params->data_type;
759 755
756 dma_params->fifo_level = fifo_level;
760 davinci_config_channel_size(dev, word_length); 757 davinci_config_channel_size(dev, word_length);
761 758
762 return 0; 759 return 0;
@@ -907,6 +904,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
907 904
908 dma_data->channel = res->start; 905 dma_data->channel = res->start;
909 davinci_mcasp_dai[pdata->op_mode].private_data = dev; 906 davinci_mcasp_dai[pdata->op_mode].private_data = dev;
907 davinci_mcasp_dai[pdata->op_mode].dma_data = dev->dma_params;
910 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev; 908 davinci_mcasp_dai[pdata->op_mode].dev = &pdev->dev;
911 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]); 909 ret = snd_soc_register_dai(&davinci_mcasp_dai[pdata->op_mode]);
912 910
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h
index 9d179cc88f7b..582c9249ef09 100644
--- a/sound/soc/davinci/davinci-mcasp.h
+++ b/sound/soc/davinci/davinci-mcasp.h
@@ -39,11 +39,6 @@ enum {
39}; 39};
40 40
41struct davinci_audio_dev { 41struct davinci_audio_dev {
42 /*
43 * dma_params must be first because rtd->dai->cpu_dai->private_data
44 * is cast to a pointer of an array of struct davinci_pcm_dma_params in
45 * davinci_pcm_open.
46 */
47 struct davinci_pcm_dma_params dma_params[2]; 42 struct davinci_pcm_dma_params dma_params[2];
48 void __iomem *base; 43 void __iomem *base;
49 int sample_rate; 44 int sample_rate;
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index c73a915f233f..ad4d7f47a86b 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -3,6 +3,7 @@
3 * 3 *
4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com> 4 * Author: Vladimir Barinov, <vbarinov@embeddedalley.com>
5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com> 5 * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
6 * added SRAM ping/pong (C) 2008 Troy Kisky <troy.kisky@boundarydevices.com>
6 * 7 *
7 * This program is free software; you can redistribute it and/or modify 8 * 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 9 * it under the terms of the GNU General Public License version 2 as
@@ -23,10 +24,29 @@
23 24
24#include <asm/dma.h> 25#include <asm/dma.h>
25#include <mach/edma.h> 26#include <mach/edma.h>
27#include <mach/sram.h>
26 28
27#include "davinci-pcm.h" 29#include "davinci-pcm.h"
28 30
29static struct snd_pcm_hardware davinci_pcm_hardware = { 31#ifdef DEBUG
32static void print_buf_info(int slot, char *name)
33{
34 struct edmacc_param p;
35 if (slot < 0)
36 return;
37 edma_read_slot(slot, &p);
38 printk(KERN_DEBUG "%s: 0x%x, opt=%x, src=%x, a_b_cnt=%x dst=%x\n",
39 name, slot, p.opt, p.src, p.a_b_cnt, p.dst);
40 printk(KERN_DEBUG " src_dst_bidx=%x link_bcntrld=%x src_dst_cidx=%x ccnt=%x\n",
41 p.src_dst_bidx, p.link_bcntrld, p.src_dst_cidx, p.ccnt);
42}
43#else
44static void print_buf_info(int slot, char *name)
45{
46}
47#endif
48
49static struct snd_pcm_hardware pcm_hardware_playback = {
30 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER | 50 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
31 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 51 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
32 SNDRV_PCM_INFO_PAUSE), 52 SNDRV_PCM_INFO_PAUSE),
@@ -48,102 +68,432 @@ static struct snd_pcm_hardware davinci_pcm_hardware = {
48 .fifo_size = 0, 68 .fifo_size = 0,
49}; 69};
50 70
71static struct snd_pcm_hardware pcm_hardware_capture = {
72 .info = (SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BLOCK_TRANSFER |
73 SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
74 SNDRV_PCM_INFO_PAUSE),
75 .formats = (SNDRV_PCM_FMTBIT_S16_LE),
76 .rates = (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |
77 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 |
78 SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
79 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
80 SNDRV_PCM_RATE_KNOT),
81 .rate_min = 8000,
82 .rate_max = 96000,
83 .channels_min = 2,
84 .channels_max = 2,
85 .buffer_bytes_max = 128 * 1024,
86 .period_bytes_min = 32,
87 .period_bytes_max = 8 * 1024,
88 .periods_min = 16,
89 .periods_max = 255,
90 .fifo_size = 0,
91};
92
93/*
94 * How ping/pong works....
95 *
96 * Playback:
97 * ram_params - copys 2*ping_size from start of SDRAM to iram,
98 * links to ram_link2
99 * ram_link2 - copys rest of SDRAM to iram in ping_size units,
100 * links to ram_link
101 * ram_link - copys entire SDRAM to iram in ping_size uints,
102 * links to self
103 *
104 * asp_params - same as asp_link[0]
105 * asp_link[0] - copys from lower half of iram to asp port
106 * links to asp_link[1], triggers iram copy event on completion
107 * asp_link[1] - copys from upper half of iram to asp port
108 * links to asp_link[0], triggers iram copy event on completion
109 * triggers interrupt only needed to let upper SOC levels update position
110 * in stream on completion
111 *
112 * When playback is started:
113 * ram_params started
114 * asp_params started
115 *
116 * Capture:
117 * ram_params - same as ram_link,
118 * links to ram_link
119 * ram_link - same as playback
120 * links to self
121 *
122 * asp_params - same as playback
123 * asp_link[0] - same as playback
124 * asp_link[1] - same as playback
125 *
126 * When capture is started:
127 * asp_params started
128 */
51struct davinci_runtime_data { 129struct davinci_runtime_data {
52 spinlock_t lock; 130 spinlock_t lock;
53 int period; /* current DMA period */ 131 int period; /* current DMA period */
54 int master_lch; /* Master DMA channel */ 132 int asp_channel; /* Master DMA channel */
55 int slave_lch; /* linked parameter RAM reload slot */ 133 int asp_link[2]; /* asp parameter link channel, ping/pong */
56 struct davinci_pcm_dma_params *params; /* DMA params */ 134 struct davinci_pcm_dma_params *params; /* DMA params */
135 int ram_channel;
136 int ram_link;
137 int ram_link2;
138 struct edmacc_param asp_params;
139 struct edmacc_param ram_params;
57}; 140};
58 141
142/*
143 * Not used with ping/pong
144 */
59static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream) 145static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
60{ 146{
61 struct davinci_runtime_data *prtd = substream->runtime->private_data; 147 struct davinci_runtime_data *prtd = substream->runtime->private_data;
62 struct snd_pcm_runtime *runtime = substream->runtime; 148 struct snd_pcm_runtime *runtime = substream->runtime;
63 int lch = prtd->slave_lch; 149 int link = prtd->asp_link[0];
64 unsigned int period_size; 150 unsigned int period_size;
65 unsigned int dma_offset; 151 unsigned int dma_offset;
66 dma_addr_t dma_pos; 152 dma_addr_t dma_pos;
67 dma_addr_t src, dst; 153 dma_addr_t src, dst;
68 unsigned short src_bidx, dst_bidx; 154 unsigned short src_bidx, dst_bidx;
155 unsigned short src_cidx, dst_cidx;
69 unsigned int data_type; 156 unsigned int data_type;
70 unsigned short acnt; 157 unsigned short acnt;
71 unsigned int count; 158 unsigned int count;
159 unsigned int fifo_level;
72 160
73 period_size = snd_pcm_lib_period_bytes(substream); 161 period_size = snd_pcm_lib_period_bytes(substream);
74 dma_offset = prtd->period * period_size; 162 dma_offset = prtd->period * period_size;
75 dma_pos = runtime->dma_addr + dma_offset; 163 dma_pos = runtime->dma_addr + dma_offset;
164 fifo_level = prtd->params->fifo_level;
76 165
77 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d " 166 pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
78 "dma_ptr = %x period_size=%x\n", lch, dma_pos, period_size); 167 "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);
79 168
80 data_type = prtd->params->data_type; 169 data_type = prtd->params->data_type;
81 count = period_size / data_type; 170 count = period_size / data_type;
171 if (fifo_level)
172 count /= fifo_level;
82 173
83 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 174 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
84 src = dma_pos; 175 src = dma_pos;
85 dst = prtd->params->dma_addr; 176 dst = prtd->params->dma_addr;
86 src_bidx = data_type; 177 src_bidx = data_type;
87 dst_bidx = 0; 178 dst_bidx = 0;
179 src_cidx = data_type * fifo_level;
180 dst_cidx = 0;
88 } else { 181 } else {
89 src = prtd->params->dma_addr; 182 src = prtd->params->dma_addr;
90 dst = dma_pos; 183 dst = dma_pos;
91 src_bidx = 0; 184 src_bidx = 0;
92 dst_bidx = data_type; 185 dst_bidx = data_type;
186 src_cidx = 0;
187 dst_cidx = data_type * fifo_level;
93 } 188 }
94 189
95 acnt = prtd->params->acnt; 190 acnt = prtd->params->acnt;
96 edma_set_src(lch, src, INCR, W8BIT); 191 edma_set_src(link, src, INCR, W8BIT);
97 edma_set_dest(lch, dst, INCR, W8BIT); 192 edma_set_dest(link, dst, INCR, W8BIT);
98 edma_set_src_index(lch, src_bidx, 0); 193
99 edma_set_dest_index(lch, dst_bidx, 0); 194 edma_set_src_index(link, src_bidx, src_cidx);
100 edma_set_transfer_params(lch, acnt, count, 1, 0, ASYNC); 195 edma_set_dest_index(link, dst_bidx, dst_cidx);
196
197 if (!fifo_level)
198 edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
199 else
200 edma_set_transfer_params(link, acnt, fifo_level, count,
201 fifo_level, ABSYNC);
101 202
102 prtd->period++; 203 prtd->period++;
103 if (unlikely(prtd->period >= runtime->periods)) 204 if (unlikely(prtd->period >= runtime->periods))
104 prtd->period = 0; 205 prtd->period = 0;
105} 206}
106 207
107static void davinci_pcm_dma_irq(unsigned lch, u16 ch_status, void *data) 208static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
108{ 209{
109 struct snd_pcm_substream *substream = data; 210 struct snd_pcm_substream *substream = data;
110 struct davinci_runtime_data *prtd = substream->runtime->private_data; 211 struct davinci_runtime_data *prtd = substream->runtime->private_data;
111 212
112 pr_debug("davinci_pcm: lch=%d, status=0x%x\n", lch, ch_status); 213 print_buf_info(prtd->ram_channel, "i ram_channel");
214 pr_debug("davinci_pcm: link=%d, status=0x%x\n", link, ch_status);
113 215
114 if (unlikely(ch_status != DMA_COMPLETE)) 216 if (unlikely(ch_status != DMA_COMPLETE))
115 return; 217 return;
116 218
117 if (snd_pcm_running(substream)) { 219 if (snd_pcm_running(substream)) {
220 if (prtd->ram_channel < 0) {
221 /* No ping/pong must fix up link dma data*/
222 spin_lock(&prtd->lock);
223 davinci_pcm_enqueue_dma(substream);
224 spin_unlock(&prtd->lock);
225 }
118 snd_pcm_period_elapsed(substream); 226 snd_pcm_period_elapsed(substream);
227 }
228}
229
230static int allocate_sram(struct snd_pcm_substream *substream, unsigned size,
231 struct snd_pcm_hardware *ppcm)
232{
233 struct snd_dma_buffer *buf = &substream->dma_buffer;
234 struct snd_dma_buffer *iram_dma = NULL;
235 dma_addr_t iram_phys = 0;
236 void *iram_virt = NULL;
237
238 if (buf->private_data || !size)
239 return 0;
240
241 ppcm->period_bytes_max = size;
242 iram_virt = sram_alloc(size, &iram_phys);
243 if (!iram_virt)
244 goto exit1;
245 iram_dma = kzalloc(sizeof(*iram_dma), GFP_KERNEL);
246 if (!iram_dma)
247 goto exit2;
248 iram_dma->area = iram_virt;
249 iram_dma->addr = iram_phys;
250 memset(iram_dma->area, 0, size);
251 iram_dma->bytes = size;
252 buf->private_data = iram_dma;
253 return 0;
254exit2:
255 if (iram_virt)
256 sram_free(iram_virt, size);
257exit1:
258 return -ENOMEM;
259}
260
261/*
262 * Only used with ping/pong.
263 * This is called after runtime->dma_addr, period_bytes and data_type are valid
264 */
265static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
266{
267 unsigned short ram_src_cidx, ram_dst_cidx;
268 struct snd_pcm_runtime *runtime = substream->runtime;
269 struct davinci_runtime_data *prtd = runtime->private_data;
270 struct snd_dma_buffer *iram_dma =
271 (struct snd_dma_buffer *)substream->dma_buffer.private_data;
272 struct davinci_pcm_dma_params *params = prtd->params;
273 unsigned int data_type = params->data_type;
274 unsigned int acnt = params->acnt;
275 /* divide by 2 for ping/pong */
276 unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
277 int link = prtd->asp_link[1];
278 unsigned int fifo_level = prtd->params->fifo_level;
279 unsigned int count;
280 if ((data_type == 0) || (data_type > 4)) {
281 printk(KERN_ERR "%s: data_type=%i\n", __func__, data_type);
282 return -EINVAL;
283 }
284 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
285 dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
286 ram_src_cidx = ping_size;
287 ram_dst_cidx = -ping_size;
288 edma_set_src(link, asp_src_pong, INCR, W8BIT);
289
290 link = prtd->asp_link[0];
291 edma_set_src_index(link, data_type, data_type * fifo_level);
292 link = prtd->asp_link[1];
293 edma_set_src_index(link, data_type, data_type * fifo_level);
294
295 link = prtd->ram_link;
296 edma_set_src(link, runtime->dma_addr, INCR, W32BIT);
297 } else {
298 dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
299 ram_src_cidx = -ping_size;
300 ram_dst_cidx = ping_size;
301 edma_set_dest(link, asp_dst_pong, INCR, W8BIT);
302
303 link = prtd->asp_link[0];
304 edma_set_dest_index(link, data_type, data_type * fifo_level);
305 link = prtd->asp_link[1];
306 edma_set_dest_index(link, data_type, data_type * fifo_level);
307
308 link = prtd->ram_link;
309 edma_set_dest(link, runtime->dma_addr, INCR, W32BIT);
310 }
119 311
120 spin_lock(&prtd->lock); 312 if (!fifo_level) {
121 davinci_pcm_enqueue_dma(substream); 313 count = ping_size / data_type;
122 spin_unlock(&prtd->lock); 314 edma_set_transfer_params(prtd->asp_link[0], acnt, count,
315 1, 0, ASYNC);
316 edma_set_transfer_params(prtd->asp_link[1], acnt, count,
317 1, 0, ASYNC);
318 } else {
319 count = ping_size / (data_type * fifo_level);
320 edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
321 count, fifo_level, ABSYNC);
322 edma_set_transfer_params(prtd->asp_link[1], acnt, fifo_level,
323 count, fifo_level, ABSYNC);
123 } 324 }
325
326 link = prtd->ram_link;
327 edma_set_src_index(link, ping_size, ram_src_cidx);
328 edma_set_dest_index(link, ping_size, ram_dst_cidx);
329 edma_set_transfer_params(link, ping_size, 2,
330 runtime->periods, 2, ASYNC);
331
332 /* init master params */
333 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
334 edma_read_slot(prtd->ram_link, &prtd->ram_params);
335 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
336 struct edmacc_param p_ram;
337 /* Copy entire iram buffer before playback started */
338 prtd->ram_params.a_b_cnt = (1 << 16) | (ping_size << 1);
339 /* 0 dst_bidx */
340 prtd->ram_params.src_dst_bidx = (ping_size << 1);
341 /* 0 dst_cidx */
342 prtd->ram_params.src_dst_cidx = (ping_size << 1);
343 prtd->ram_params.ccnt = 1;
344
345 /* Skip 1st period */
346 edma_read_slot(prtd->ram_link, &p_ram);
347 p_ram.src += (ping_size << 1);
348 p_ram.ccnt -= 1;
349 edma_write_slot(prtd->ram_link2, &p_ram);
350 /*
351 * When 1st started, ram -> iram dma channel will fill the
352 * entire iram. Then, whenever a ping/pong asp buffer finishes,
353 * 1/2 iram will be filled.
354 */
355 prtd->ram_params.link_bcntrld =
356 EDMA_CHAN_SLOT(prtd->ram_link2) << 5;
357 }
358 return 0;
359}
360
361/* 1 asp tx or rx channel using 2 parameter channels
362 * 1 ram to/from iram channel using 1 parameter channel
363 *
364 * Playback
365 * ram copy channel kicks off first,
366 * 1st ram copy of entire iram buffer completion kicks off asp channel
367 * asp tcc always kicks off ram copy of 1/2 iram buffer
368 *
369 * Record
370 * asp channel starts, tcc kicks off ram copy
371 */
372static int request_ping_pong(struct snd_pcm_substream *substream,
373 struct davinci_runtime_data *prtd,
374 struct snd_dma_buffer *iram_dma)
375{
376 dma_addr_t asp_src_ping;
377 dma_addr_t asp_dst_ping;
378 int link;
379 struct davinci_pcm_dma_params *params = prtd->params;
380
381 /* Request ram master channel */
382 link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
383 davinci_pcm_dma_irq, substream,
384 EVENTQ_1);
385 if (link < 0)
386 goto exit1;
387
388 /* Request ram link channel */
389 link = prtd->ram_link = edma_alloc_slot(
390 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
391 if (link < 0)
392 goto exit2;
393
394 link = prtd->asp_link[1] = edma_alloc_slot(
395 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
396 if (link < 0)
397 goto exit3;
398
399 prtd->ram_link2 = -1;
400 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
401 link = prtd->ram_link2 = edma_alloc_slot(
402 EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
403 if (link < 0)
404 goto exit4;
405 }
406 /* circle ping-pong buffers */
407 edma_link(prtd->asp_link[0], prtd->asp_link[1]);
408 edma_link(prtd->asp_link[1], prtd->asp_link[0]);
409 /* circle ram buffers */
410 edma_link(prtd->ram_link, prtd->ram_link);
411
412 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
413 asp_src_ping = iram_dma->addr;
414 asp_dst_ping = params->dma_addr; /* fifo */
415 } else {
416 asp_src_ping = params->dma_addr; /* fifo */
417 asp_dst_ping = iram_dma->addr;
418 }
419 /* ping */
420 link = prtd->asp_link[0];
421 edma_set_src(link, asp_src_ping, INCR, W16BIT);
422 edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
423 edma_set_src_index(link, 0, 0);
424 edma_set_dest_index(link, 0, 0);
425
426 edma_read_slot(link, &prtd->asp_params);
427 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
428 prtd->asp_params.opt |= TCCHEN | EDMA_TCC(prtd->ram_channel & 0x3f);
429 edma_write_slot(link, &prtd->asp_params);
430
431 /* pong */
432 link = prtd->asp_link[1];
433 edma_set_src(link, asp_src_ping, INCR, W16BIT);
434 edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
435 edma_set_src_index(link, 0, 0);
436 edma_set_dest_index(link, 0, 0);
437
438 edma_read_slot(link, &prtd->asp_params);
439 prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
440 /* interrupt after every pong completion */
441 prtd->asp_params.opt |= TCINTEN | TCCHEN |
442 EDMA_TCC(EDMA_CHAN_SLOT(prtd->ram_channel));
443 edma_write_slot(link, &prtd->asp_params);
444
445 /* ram */
446 link = prtd->ram_link;
447 edma_set_src(link, iram_dma->addr, INCR, W32BIT);
448 edma_set_dest(link, iram_dma->addr, INCR, W32BIT);
449 pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
450 "for asp:%u %u %u\n", __func__,
451 prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
452 prtd->asp_channel, prtd->asp_link[0],
453 prtd->asp_link[1]);
454 return 0;
455exit4:
456 edma_free_channel(prtd->asp_link[1]);
457 prtd->asp_link[1] = -1;
458exit3:
459 edma_free_channel(prtd->ram_link);
460 prtd->ram_link = -1;
461exit2:
462 edma_free_channel(prtd->ram_channel);
463 prtd->ram_channel = -1;
464exit1:
465 return link;
124} 466}
125 467
126static int davinci_pcm_dma_request(struct snd_pcm_substream *substream) 468static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
127{ 469{
470 struct snd_dma_buffer *iram_dma;
128 struct davinci_runtime_data *prtd = substream->runtime->private_data; 471 struct davinci_runtime_data *prtd = substream->runtime->private_data;
129 struct edmacc_param p_ram; 472 struct davinci_pcm_dma_params *params = prtd->params;
130 int ret; 473 int link;
131 474
132 /* Request master DMA channel */ 475 if (!params)
133 ret = edma_alloc_channel(prtd->params->channel, 476 return -ENODEV;
134 davinci_pcm_dma_irq, substream,
135 EVENTQ_0);
136 if (ret < 0)
137 return ret;
138 prtd->master_lch = ret;
139 477
140 /* Request parameter RAM reload slot */ 478 /* Request asp master DMA channel */
141 ret = edma_alloc_slot(EDMA_CTLR(prtd->master_lch), EDMA_SLOT_ANY); 479 link = prtd->asp_channel = edma_alloc_channel(params->channel,
142 if (ret < 0) { 480 davinci_pcm_dma_irq, substream, EVENTQ_0);
143 edma_free_channel(prtd->master_lch); 481 if (link < 0)
144 return ret; 482 goto exit1;
483
484 /* Request asp link channels */
485 link = prtd->asp_link[0] = edma_alloc_slot(
486 EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
487 if (link < 0)
488 goto exit2;
489
490 iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
491 if (iram_dma) {
492 if (request_ping_pong(substream, prtd, iram_dma) == 0)
493 return 0;
494 printk(KERN_WARNING "%s: dma channel allocation failed,"
495 "not using sram\n", __func__);
145 } 496 }
146 prtd->slave_lch = ret;
147 497
148 /* Issue transfer completion IRQ when the channel completes a 498 /* Issue transfer completion IRQ when the channel completes a
149 * transfer, then always reload from the same slot (by a kind 499 * transfer, then always reload from the same slot (by a kind
@@ -154,12 +504,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
154 * the buffer and its length (ccnt) ... use it as a template 504 * the buffer and its length (ccnt) ... use it as a template
155 * so davinci_pcm_enqueue_dma() takes less time in IRQ. 505 * so davinci_pcm_enqueue_dma() takes less time in IRQ.
156 */ 506 */
157 edma_read_slot(prtd->slave_lch, &p_ram); 507 edma_read_slot(link, &prtd->asp_params);
158 p_ram.opt |= TCINTEN | EDMA_TCC(EDMA_CHAN_SLOT(prtd->master_lch)); 508 prtd->asp_params.opt |= TCINTEN |
159 p_ram.link_bcntrld = EDMA_CHAN_SLOT(prtd->slave_lch) << 5; 509 EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
160 edma_write_slot(prtd->slave_lch, &p_ram); 510 prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5;
161 511 edma_write_slot(link, &prtd->asp_params);
162 return 0; 512 return 0;
513exit2:
514 edma_free_channel(prtd->asp_channel);
515 prtd->asp_channel = -1;
516exit1:
517 return link;
163} 518}
164 519
165static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 520static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -173,12 +528,12 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
173 case SNDRV_PCM_TRIGGER_START: 528 case SNDRV_PCM_TRIGGER_START:
174 case SNDRV_PCM_TRIGGER_RESUME: 529 case SNDRV_PCM_TRIGGER_RESUME:
175 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 530 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
176 edma_start(prtd->master_lch); 531 edma_resume(prtd->asp_channel);
177 break; 532 break;
178 case SNDRV_PCM_TRIGGER_STOP: 533 case SNDRV_PCM_TRIGGER_STOP:
179 case SNDRV_PCM_TRIGGER_SUSPEND: 534 case SNDRV_PCM_TRIGGER_SUSPEND:
180 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 535 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
181 edma_stop(prtd->master_lch); 536 edma_pause(prtd->asp_channel);
182 break; 537 break;
183 default: 538 default:
184 ret = -EINVAL; 539 ret = -EINVAL;
@@ -193,15 +548,37 @@ static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
193static int davinci_pcm_prepare(struct snd_pcm_substream *substream) 548static int davinci_pcm_prepare(struct snd_pcm_substream *substream)
194{ 549{
195 struct davinci_runtime_data *prtd = substream->runtime->private_data; 550 struct davinci_runtime_data *prtd = substream->runtime->private_data;
196 struct edmacc_param temp;
197 551
552 if (prtd->ram_channel >= 0) {
553 int ret = ping_pong_dma_setup(substream);
554 if (ret < 0)
555 return ret;
556
557 edma_write_slot(prtd->ram_channel, &prtd->ram_params);
558 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
559
560 print_buf_info(prtd->ram_channel, "ram_channel");
561 print_buf_info(prtd->ram_link, "ram_link");
562 print_buf_info(prtd->ram_link2, "ram_link2");
563 print_buf_info(prtd->asp_channel, "asp_channel");
564 print_buf_info(prtd->asp_link[0], "asp_link[0]");
565 print_buf_info(prtd->asp_link[1], "asp_link[1]");
566
567 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
568 /* copy 1st iram buffer */
569 edma_start(prtd->ram_channel);
570 }
571 edma_start(prtd->asp_channel);
572 return 0;
573 }
198 prtd->period = 0; 574 prtd->period = 0;
199 davinci_pcm_enqueue_dma(substream); 575 davinci_pcm_enqueue_dma(substream);
200 576
201 /* Copy self-linked parameter RAM entry into master channel */ 577 /* Copy self-linked parameter RAM entry into master channel */
202 edma_read_slot(prtd->slave_lch, &temp); 578 edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
203 edma_write_slot(prtd->master_lch, &temp); 579 edma_write_slot(prtd->asp_channel, &prtd->asp_params);
204 davinci_pcm_enqueue_dma(substream); 580 davinci_pcm_enqueue_dma(substream);
581 edma_start(prtd->asp_channel);
205 582
206 return 0; 583 return 0;
207} 584}
@@ -212,20 +589,53 @@ davinci_pcm_pointer(struct snd_pcm_substream *substream)
212 struct snd_pcm_runtime *runtime = substream->runtime; 589 struct snd_pcm_runtime *runtime = substream->runtime;
213 struct davinci_runtime_data *prtd = runtime->private_data; 590 struct davinci_runtime_data *prtd = runtime->private_data;
214 unsigned int offset; 591 unsigned int offset;
215 dma_addr_t count; 592 int asp_count;
216 dma_addr_t src, dst; 593 dma_addr_t asp_src, asp_dst;
217 594
218 spin_lock(&prtd->lock); 595 spin_lock(&prtd->lock);
219 596 if (prtd->ram_channel >= 0) {
220 edma_get_position(prtd->master_lch, &src, &dst); 597 int ram_count;
221 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) 598 int mod_ram;
222 count = src - runtime->dma_addr; 599 dma_addr_t ram_src, ram_dst;
223 else 600 unsigned int period_size = snd_pcm_lib_period_bytes(substream);
224 count = dst - runtime->dma_addr; 601 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
225 602 /* reading ram before asp should be safe
603 * as long as the asp transfers less than a ping size
604 * of bytes between the 2 reads
605 */
606 edma_get_position(prtd->ram_channel,
607 &ram_src, &ram_dst);
608 edma_get_position(prtd->asp_channel,
609 &asp_src, &asp_dst);
610 asp_count = asp_src - prtd->asp_params.src;
611 ram_count = ram_src - prtd->ram_params.src;
612 mod_ram = ram_count % period_size;
613 mod_ram -= asp_count;
614 if (mod_ram < 0)
615 mod_ram += period_size;
616 else if (mod_ram == 0) {
617 if (snd_pcm_running(substream))
618 mod_ram += period_size;
619 }
620 ram_count -= mod_ram;
621 if (ram_count < 0)
622 ram_count += period_size * runtime->periods;
623 } else {
624 edma_get_position(prtd->ram_channel,
625 &ram_src, &ram_dst);
626 ram_count = ram_dst - prtd->ram_params.dst;
627 }
628 asp_count = ram_count;
629 } else {
630 edma_get_position(prtd->asp_channel, &asp_src, &asp_dst);
631 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
632 asp_count = asp_src - runtime->dma_addr;
633 else
634 asp_count = asp_dst - runtime->dma_addr;
635 }
226 spin_unlock(&prtd->lock); 636 spin_unlock(&prtd->lock);
227 637
228 offset = bytes_to_frames(runtime, count); 638 offset = bytes_to_frames(runtime, asp_count);
229 if (offset >= runtime->buffer_size) 639 if (offset >= runtime->buffer_size)
230 offset = 0; 640 offset = 0;
231 641
@@ -236,14 +646,19 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
236{ 646{
237 struct snd_pcm_runtime *runtime = substream->runtime; 647 struct snd_pcm_runtime *runtime = substream->runtime;
238 struct davinci_runtime_data *prtd; 648 struct davinci_runtime_data *prtd;
649 struct snd_pcm_hardware *ppcm;
239 int ret = 0; 650 int ret = 0;
240 struct snd_soc_pcm_runtime *rtd = substream->private_data; 651 struct snd_soc_pcm_runtime *rtd = substream->private_data;
241 struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->private_data; 652 struct davinci_pcm_dma_params *pa = rtd->dai->cpu_dai->dma_data;
242 struct davinci_pcm_dma_params *params = &pa[substream->stream]; 653 struct davinci_pcm_dma_params *params;
243 if (!params) 654 if (!pa)
244 return -ENODEV; 655 return -ENODEV;
656 params = &pa[substream->stream];
245 657
246 snd_soc_set_runtime_hwparams(substream, &davinci_pcm_hardware); 658 ppcm = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
659 &pcm_hardware_playback : &pcm_hardware_capture;
660 allocate_sram(substream, params->sram_size, ppcm);
661 snd_soc_set_runtime_hwparams(substream, ppcm);
247 /* ensure that buffer size is a multiple of period size */ 662 /* ensure that buffer size is a multiple of period size */
248 ret = snd_pcm_hw_constraint_integer(runtime, 663 ret = snd_pcm_hw_constraint_integer(runtime,
249 SNDRV_PCM_HW_PARAM_PERIODS); 664 SNDRV_PCM_HW_PARAM_PERIODS);
@@ -256,6 +671,11 @@ static int davinci_pcm_open(struct snd_pcm_substream *substream)
256 671
257 spin_lock_init(&prtd->lock); 672 spin_lock_init(&prtd->lock);
258 prtd->params = params; 673 prtd->params = params;
674 prtd->asp_channel = -1;
675 prtd->asp_link[0] = prtd->asp_link[1] = -1;
676 prtd->ram_channel = -1;
677 prtd->ram_link = -1;
678 prtd->ram_link2 = -1;
259 679
260 runtime->private_data = prtd; 680 runtime->private_data = prtd;
261 681
@@ -273,10 +693,29 @@ static int davinci_pcm_close(struct snd_pcm_substream *substream)
273 struct snd_pcm_runtime *runtime = substream->runtime; 693 struct snd_pcm_runtime *runtime = substream->runtime;
274 struct davinci_runtime_data *prtd = runtime->private_data; 694 struct davinci_runtime_data *prtd = runtime->private_data;
275 695
276 edma_unlink(prtd->slave_lch); 696 if (prtd->ram_channel >= 0)
277 697 edma_stop(prtd->ram_channel);
278 edma_free_slot(prtd->slave_lch); 698 if (prtd->asp_channel >= 0)
279 edma_free_channel(prtd->master_lch); 699 edma_stop(prtd->asp_channel);
700 if (prtd->asp_link[0] >= 0)
701 edma_unlink(prtd->asp_link[0]);
702 if (prtd->asp_link[1] >= 0)
703 edma_unlink(prtd->asp_link[1]);
704 if (prtd->ram_link >= 0)
705 edma_unlink(prtd->ram_link);
706
707 if (prtd->asp_link[0] >= 0)
708 edma_free_slot(prtd->asp_link[0]);
709 if (prtd->asp_link[1] >= 0)
710 edma_free_slot(prtd->asp_link[1]);
711 if (prtd->asp_channel >= 0)
712 edma_free_channel(prtd->asp_channel);
713 if (prtd->ram_link >= 0)
714 edma_free_slot(prtd->ram_link);
715 if (prtd->ram_link2 >= 0)
716 edma_free_slot(prtd->ram_link2);
717 if (prtd->ram_channel >= 0)
718 edma_free_channel(prtd->ram_channel);
280 719
281 kfree(prtd); 720 kfree(prtd);
282 721
@@ -318,11 +757,11 @@ static struct snd_pcm_ops davinci_pcm_ops = {
318 .mmap = davinci_pcm_mmap, 757 .mmap = davinci_pcm_mmap,
319}; 758};
320 759
321static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 760static int davinci_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream,
761 size_t size)
322{ 762{
323 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 763 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
324 struct snd_dma_buffer *buf = &substream->dma_buffer; 764 struct snd_dma_buffer *buf = &substream->dma_buffer;
325 size_t size = davinci_pcm_hardware.buffer_bytes_max;
326 765
327 buf->dev.type = SNDRV_DMA_TYPE_DEV; 766 buf->dev.type = SNDRV_DMA_TYPE_DEV;
328 buf->dev.dev = pcm->card->dev; 767 buf->dev.dev = pcm->card->dev;
@@ -347,6 +786,7 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
347 int stream; 786 int stream;
348 787
349 for (stream = 0; stream < 2; stream++) { 788 for (stream = 0; stream < 2; stream++) {
789 struct snd_dma_buffer *iram_dma;
350 substream = pcm->streams[stream].substream; 790 substream = pcm->streams[stream].substream;
351 if (!substream) 791 if (!substream)
352 continue; 792 continue;
@@ -358,6 +798,11 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
358 dma_free_writecombine(pcm->card->dev, buf->bytes, 798 dma_free_writecombine(pcm->card->dev, buf->bytes,
359 buf->area, buf->addr); 799 buf->area, buf->addr);
360 buf->area = NULL; 800 buf->area = NULL;
801 iram_dma = (struct snd_dma_buffer *)buf->private_data;
802 if (iram_dma) {
803 sram_free(iram_dma->area, iram_dma->bytes);
804 kfree(iram_dma);
805 }
361 } 806 }
362} 807}
363 808
@@ -375,14 +820,16 @@ static int davinci_pcm_new(struct snd_card *card,
375 820
376 if (dai->playback.channels_min) { 821 if (dai->playback.channels_min) {
377 ret = davinci_pcm_preallocate_dma_buffer(pcm, 822 ret = davinci_pcm_preallocate_dma_buffer(pcm,
378 SNDRV_PCM_STREAM_PLAYBACK); 823 SNDRV_PCM_STREAM_PLAYBACK,
824 pcm_hardware_playback.buffer_bytes_max);
379 if (ret) 825 if (ret)
380 return ret; 826 return ret;
381 } 827 }
382 828
383 if (dai->capture.channels_min) { 829 if (dai->capture.channels_min) {
384 ret = davinci_pcm_preallocate_dma_buffer(pcm, 830 ret = davinci_pcm_preallocate_dma_buffer(pcm,
385 SNDRV_PCM_STREAM_CAPTURE); 831 SNDRV_PCM_STREAM_CAPTURE,
832 pcm_hardware_capture.buffer_bytes_max);
386 if (ret) 833 if (ret)
387 return ret; 834 return ret;
388 } 835 }
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h
index 8746606efc89..0764944cf10f 100644
--- a/sound/soc/davinci/davinci-pcm.h
+++ b/sound/soc/davinci/davinci-pcm.h
@@ -20,9 +20,11 @@ struct davinci_pcm_dma_params {
20 int channel; /* sync dma channel ID */ 20 int channel; /* sync dma channel ID */
21 unsigned short acnt; 21 unsigned short acnt;
22 dma_addr_t dma_addr; /* device physical address for DMA */ 22 dma_addr_t dma_addr; /* device physical address for DMA */
23 unsigned sram_size;
23 enum dma_event_q eventq_no; /* event queue number */ 24 enum dma_event_q eventq_no; /* event queue number */
24 unsigned char data_type; /* xfer data type */ 25 unsigned char data_type; /* xfer data type */
25 unsigned char convert_mono_stereo; 26 unsigned char convert_mono_stereo;
27 unsigned int fifo_level;
26}; 28};
27 29
28 30
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index 6096d22283e6..30ed568afb2e 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -58,47 +58,15 @@ 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 */
101static irqreturn_t psc_dma_bcom_irq_tx(int irq, void *_psc_dma_stream) 69static irqreturn_t psc_dma_bcom_irq(int irq, void *_psc_dma_stream)
102{ 70{
103 struct psc_dma_stream *s = _psc_dma_stream; 71 struct psc_dma_stream *s = _psc_dma_stream;
104 72
@@ -108,34 +76,8 @@ 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;
114 }
115 psc_dma_bcom_enqueue_tx(s);
116 spin_unlock(&s->psc_dma->lock);
117
118 /* If the stream is active, then also inform the PCM middle layer
119 * of the period finished event. */
120 if (s->active)
121 snd_pcm_period_elapsed(s->stream);
122
123 return IRQ_HANDLED;
124}
125
126static irqreturn_t psc_dma_bcom_irq_rx(int irq, void *_psc_dma_stream)
127{
128 struct psc_dma_stream *s = _psc_dma_stream;
129
130 spin_lock(&s->psc_dma->lock);
131 /* For each finished period, dequeue the completed period buffer
132 * and enqueue a new one in it's place. */
133 while (bcom_buffer_done(s->bcom_task)) {
134 bcom_retrieve_buffer(s->bcom_task, NULL, NULL);
135
136 s->period_current_pt += s->period_bytes;
137 if (s->period_current_pt >= s->period_end)
138 s->period_current_pt = s->period_start;
139 81
140 psc_dma_bcom_enqueue_next_buffer(s); 82 psc_dma_bcom_enqueue_next_buffer(s);
141 } 83 }
@@ -166,54 +108,38 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
166 struct snd_soc_pcm_runtime *rtd = substream->private_data; 108 struct snd_soc_pcm_runtime *rtd = substream->private_data;
167 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data; 109 struct psc_dma *psc_dma = rtd->dai->cpu_dai->private_data;
168 struct snd_pcm_runtime *runtime = substream->runtime; 110 struct snd_pcm_runtime *runtime = substream->runtime;
169 struct psc_dma_stream *s; 111 struct psc_dma_stream *s = to_psc_dma_stream(substream, psc_dma);
170 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs; 112 struct mpc52xx_psc __iomem *regs = psc_dma->psc_regs;
171 u16 imr; 113 u16 imr;
172 unsigned long flags; 114 unsigned long flags;
173 int i; 115 int i;
174 116
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) { 117 switch (cmd) {
185 case SNDRV_PCM_TRIGGER_START: 118 case SNDRV_PCM_TRIGGER_START:
119 dev_dbg(psc_dma->dev, "START: stream=%i fbits=%u ps=%u #p=%u\n",
120 substream->pstr->stream, runtime->frame_bits,
121 (int)runtime->period_size, runtime->periods);
186 s->period_bytes = frames_to_bytes(runtime, 122 s->period_bytes = frames_to_bytes(runtime,
187 runtime->period_size); 123 runtime->period_size);
188 s->period_start = virt_to_phys(runtime->dma_area); 124 s->period_next = 0;
189 s->period_end = s->period_start + 125 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; 126 s->active = 1;
195 127 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; 128 s->runtime = runtime;
200 s->appl_ptr = s->runtime->control->appl_ptr -
201 (runtime->period_size * runtime->periods);
202 129
203 /* Fill up the bestcomm bd queue and enable DMA. 130 /* Fill up the bestcomm bd queue and enable DMA.
204 * This will begin filling the PSC's fifo. 131 * This will begin filling the PSC's fifo.
205 */ 132 */
206 spin_lock_irqsave(&psc_dma->lock, flags); 133 spin_lock_irqsave(&psc_dma->lock, flags);
207 134
208 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE) { 135 if (substream->pstr->stream == SNDRV_PCM_STREAM_CAPTURE)
209 bcom_gen_bd_rx_reset(s->bcom_task); 136 bcom_gen_bd_rx_reset(s->bcom_task);
210 for (i = 0; i < runtime->periods; i++) 137 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); 138 bcom_gen_bd_tx_reset(s->bcom_task);
215 psc_dma_bcom_enqueue_tx(s); 139
216 } 140 for (i = 0; i < runtime->periods; i++)
141 if (!bcom_queue_full(s->bcom_task))
142 psc_dma_bcom_enqueue_next_buffer(s);
217 143
218 bcom_enable(s->bcom_task); 144 bcom_enable(s->bcom_task);
219 spin_unlock_irqrestore(&psc_dma->lock, flags); 145 spin_unlock_irqrestore(&psc_dma->lock, flags);
@@ -223,6 +149,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
223 break; 149 break;
224 150
225 case SNDRV_PCM_TRIGGER_STOP: 151 case SNDRV_PCM_TRIGGER_STOP:
152 dev_dbg(psc_dma->dev, "STOP: stream=%i periods_count=%i\n",
153 substream->pstr->stream, s->period_count);
226 s->active = 0; 154 s->active = 0;
227 155
228 spin_lock_irqsave(&psc_dma->lock, flags); 156 spin_lock_irqsave(&psc_dma->lock, flags);
@@ -236,7 +164,8 @@ static int psc_dma_trigger(struct snd_pcm_substream *substream, int cmd)
236 break; 164 break;
237 165
238 default: 166 default:
239 dev_dbg(psc_dma->dev, "invalid command\n"); 167 dev_dbg(psc_dma->dev, "unhandled trigger: stream=%i cmd=%i\n",
168 substream->pstr->stream, cmd);
240 return -EINVAL; 169 return -EINVAL;
241 } 170 }
242 171
@@ -343,7 +272,7 @@ psc_dma_pointer(struct snd_pcm_substream *substream)
343 else 272 else
344 s = &psc_dma->playback; 273 s = &psc_dma->playback;
345 274
346 count = s->period_current_pt - s->period_start; 275 count = s->period_current * s->period_bytes;
347 276
348 return bytes_to_frames(substream->runtime, count); 277 return bytes_to_frames(substream->runtime, count);
349} 278}
@@ -532,11 +461,9 @@ int mpc5200_audio_dma_create(struct of_device *op)
532 461
533 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED, 462 rc = request_irq(psc_dma->irq, &psc_dma_status_irq, IRQF_SHARED,
534 "psc-dma-status", psc_dma); 463 "psc-dma-status", psc_dma);
535 rc |= request_irq(psc_dma->capture.irq, 464 rc |= request_irq(psc_dma->capture.irq, &psc_dma_bcom_irq, IRQF_SHARED,
536 &psc_dma_bcom_irq_rx, IRQF_SHARED,
537 "psc-dma-capture", &psc_dma->capture); 465 "psc-dma-capture", &psc_dma->capture);
538 rc |= request_irq(psc_dma->playback.irq, 466 rc |= request_irq(psc_dma->playback.irq, &psc_dma_bcom_irq, IRQF_SHARED,
539 &psc_dma_bcom_irq_tx, IRQF_SHARED,
540 "psc-dma-playback", &psc_dma->playback); 467 "psc-dma-playback", &psc_dma->playback);
541 if (rc) { 468 if (rc) {
542 ret = -ENODEV; 469 ret = -ENODEV;
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/imx/mx1_mx2-pcm.c b/sound/soc/imx/mx1_mx2-pcm.c
index b83866529397..bffffcd5ff34 100644
--- a/sound/soc/imx/mx1_mx2-pcm.c
+++ b/sound/soc/imx/mx1_mx2-pcm.c
@@ -322,12 +322,12 @@ static int mx1_mx2_pcm_open(struct snd_pcm_substream *substream)
322 322
323 pr_debug("%s: Requesting dma channel (%s)\n", __func__, 323 pr_debug("%s: Requesting dma channel (%s)\n", __func__,
324 prtd->dma_params->name); 324 prtd->dma_params->name);
325 prtd->dma_ch = imx_dma_request_by_prio(prtd->dma_params->name, 325 ret = imx_dma_request_by_prio(prtd->dma_params->name, DMA_PRIO_HIGH);
326 DMA_PRIO_HIGH); 326 if (ret < 0) {
327 if (prtd->dma_ch < 0) {
328 printk(KERN_ERR "Error %d requesting dma channel\n", ret); 327 printk(KERN_ERR "Error %d requesting dma channel\n", ret);
329 return ret; 328 return ret;
330 } 329 }
330 prtd->dma_ch = ret;
331 imx_dma_config_burstlen(prtd->dma_ch, 331 imx_dma_config_burstlen(prtd->dma_ch,
332 prtd->dma_params->watermark_level); 332 prtd->dma_params->watermark_level);
333 333
diff --git a/sound/soc/imx/mx27vis_wm8974.c b/sound/soc/imx/mx27vis_wm8974.c
index e4dcb539108a..0267d2d91685 100644
--- a/sound/soc/imx/mx27vis_wm8974.c
+++ b/sound/soc/imx/mx27vis_wm8974.c
@@ -157,7 +157,7 @@ static int mx27vis_hifi_hw_params(struct snd_pcm_substream *substream,
157 157
158 158
159 /* codec PLL input is 25 MHz */ 159 /* codec PLL input is 25 MHz */
160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, 160 ret = codec_dai->ops->set_pll(codec_dai, IGNORED_ARG, IGNORED_ARG,
161 25000000, pll_out); 161 25000000, pll_out);
162 if (ret < 0) { 162 if (ret < 0) {
163 printk(KERN_ERR "Error when setting PLL input\n"); 163 printk(KERN_ERR "Error when setting PLL input\n");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 2dee9839be86..61952aa6cd5a 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"
@@ -32,12 +43,13 @@ config SND_OMAP_SOC_OSK5912
32 Say Y if you want to add support for SoC audio on osk5912. 43 Say Y if you want to add support for SoC audio on osk5912.
33 44
34config SND_OMAP_SOC_OVERO 45config SND_OMAP_SOC_OVERO
35 tristate "SoC Audio support for Gumstix Overo" 46 tristate "SoC Audio support for Gumstix Overo and CompuLab CM-T35"
36 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO 47 depends on TWL4030_CORE && SND_OMAP_SOC && (MACH_OVERO || MACH_CM_T35)
37 select SND_OMAP_SOC_MCBSP 48 select SND_OMAP_SOC_MCBSP
38 select SND_SOC_TWL4030 49 select SND_SOC_TWL4030
39 help 50 help
40 Say Y if you want to add support for SoC audio on the Gumstix Overo. 51 Say Y if you want to add support for SoC audio on the
52 Gumstix Overo or CompuLab CM-T35
41 53
42config SND_OMAP_SOC_OMAP2EVM 54config SND_OMAP_SOC_OMAP2EVM
43 tristate "SoC Audio support for OMAP2EVM board" 55 tristate "SoC Audio support for OMAP2EVM board"
@@ -55,6 +67,15 @@ config SND_OMAP_SOC_OMAP3EVM
55 help 67 help
56 Say Y if you want to add support for SoC audio on the omap3evm board. 68 Say Y if you want to add support for SoC audio on the omap3evm board.
57 69
70config SND_OMAP_SOC_AM3517EVM
71 tristate "SoC Audio support for OMAP3517 / AM3517 EVM"
72 depends on SND_OMAP_SOC && MACH_OMAP3517EVM && I2C
73 select SND_OMAP_SOC_MCBSP
74 select SND_SOC_TLV320AIC23
75 help
76 Say Y if you want to add support for SoC audio on the OMAP3517 / AM3517
77 EVM.
78
58config SND_OMAP_SOC_SDP3430 79config SND_OMAP_SOC_SDP3430
59 tristate "SoC Audio support for Texas Instruments SDP3430" 80 tristate "SoC Audio support for Texas Instruments SDP3430"
60 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP 81 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
@@ -88,3 +109,10 @@ config SND_OMAP_SOC_ZOOM2
88 help 109 help
89 Say Y if you want to add support for Soc audio on Zoom2 board. 110 Say Y if you want to add support for Soc audio on Zoom2 board.
90 111
112config SND_OMAP_SOC_IGEP0020
113 tristate "SoC Audio support for IGEP v2"
114 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_IGEP0020
115 select SND_OMAP_SOC_MCBSP
116 select SND_SOC_TWL4030
117 help
118 Say Y if you want to add support for Soc audio on IGEP v2 board.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 02d69471dcb5..3db8a6c523f4 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -12,18 +12,22 @@ 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
18snd-soc-zoom2-objs := zoom2.o 19snd-soc-zoom2-objs := zoom2.o
20snd-soc-igep0020-objs := igep0020.o
19 21
20obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o 22obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
21obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o 23obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o
22obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o 24obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
23obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o 25obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
24obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o 26obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
25obj-$(CONFIG_MACH_OMAP3EVM) += snd-soc-omap3evm.o 27obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
28obj-$(CONFIG_SND_OMAP_SOC_OMAP3517EVM) += snd-soc-am3517evm.o
26obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 29obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
27obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 30obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
28obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 31obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
29obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o 32obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
33obj-$(CONFIG_SND_OMAP_SOC_IGEP0020) += snd-soc-igep0020.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/ams-delta.c b/sound/soc/omap/ams-delta.c
index 5a5166ac7279..ae0fc9b135d4 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -40,7 +40,7 @@
40 40
41 41
42/* Board specific DAPM widgets */ 42/* Board specific DAPM widgets */
43 const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = { 43static const struct snd_soc_dapm_widget ams_delta_dapm_widgets[] = {
44 /* Handset */ 44 /* Handset */
45 SND_SOC_DAPM_MIC("Mouthpiece", NULL), 45 SND_SOC_DAPM_MIC("Mouthpiece", NULL),
46 SND_SOC_DAPM_HP("Earpiece", NULL), 46 SND_SOC_DAPM_HP("Earpiece", NULL),
@@ -81,7 +81,7 @@ static const char *ams_delta_audio_mode[] =
81 (1 << AMS_DELTA_SPEAKER)) 81 (1 << AMS_DELTA_SPEAKER))
82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC)) 82#define AMS_DELTA_SPEAKERPHONE (AMS_DELTA_HANDSFREE | (1 << AMS_DELTA_AGC))
83 83
84unsigned short ams_delta_audio_mode_pins[] = { 84static const unsigned short ams_delta_audio_mode_pins[] = {
85 AMS_DELTA_MIXED, 85 AMS_DELTA_MIXED,
86 AMS_DELTA_HANDSET, 86 AMS_DELTA_HANDSET,
87 AMS_DELTA_HANDSFREE, 87 AMS_DELTA_HANDSFREE,
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
new file mode 100644
index 000000000000..3583c429f9be
--- /dev/null
+++ b/sound/soc/omap/igep0020.c
@@ -0,0 +1,148 @@
1/*
2 * igep0020.c -- SoC audio for IGEP v2
3 *
4 * Based on sound/soc/omap/overo.c by Steve Sakoman
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <mach/hardware.h>
31#include <mach/gpio.h>
32#include <plat/mcbsp.h>
33
34#include "omap-mcbsp.h"
35#include "omap-pcm.h"
36#include "../codecs/twl4030.h"
37
38static int igep2_hw_params(struct snd_pcm_substream *substream,
39 struct snd_pcm_hw_params *params)
40{
41 struct snd_soc_pcm_runtime *rtd = substream->private_data;
42 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
43 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
44 int ret;
45
46 /* Set codec DAI configuration */
47 ret = snd_soc_dai_set_fmt(codec_dai,
48 SND_SOC_DAIFMT_I2S |
49 SND_SOC_DAIFMT_NB_NF |
50 SND_SOC_DAIFMT_CBM_CFM);
51 if (ret < 0) {
52 printk(KERN_ERR "can't set codec DAI configuration\n");
53 return ret;
54 }
55
56 /* Set cpu DAI configuration */
57 ret = snd_soc_dai_set_fmt(cpu_dai,
58 SND_SOC_DAIFMT_I2S |
59 SND_SOC_DAIFMT_NB_NF |
60 SND_SOC_DAIFMT_CBM_CFM);
61 if (ret < 0) {
62 printk(KERN_ERR "can't set cpu DAI configuration\n");
63 return ret;
64 }
65
66 /* Set the codec system clock for DAC and ADC */
67 ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
68 SND_SOC_CLOCK_IN);
69 if (ret < 0) {
70 printk(KERN_ERR "can't set codec system clock\n");
71 return ret;
72 }
73
74 return 0;
75}
76
77static struct snd_soc_ops igep2_ops = {
78 .hw_params = igep2_hw_params,
79};
80
81/* Digital audio interface glue - connects codec <--> CPU */
82static struct snd_soc_dai_link igep2_dai = {
83 .name = "TWL4030",
84 .stream_name = "TWL4030",
85 .cpu_dai = &omap_mcbsp_dai[0],
86 .codec_dai = &twl4030_dai[TWL4030_DAI_HIFI],
87 .ops = &igep2_ops,
88};
89
90/* Audio machine driver */
91static struct snd_soc_card snd_soc_card_igep2 = {
92 .name = "igep2",
93 .platform = &omap_soc_platform,
94 .dai_link = &igep2_dai,
95 .num_links = 1,
96};
97
98/* Audio subsystem */
99static struct snd_soc_device igep2_snd_devdata = {
100 .card = &snd_soc_card_igep2,
101 .codec_dev = &soc_codec_dev_twl4030,
102};
103
104static struct platform_device *igep2_snd_device;
105
106static int __init igep2_soc_init(void)
107{
108 int ret;
109
110 if (!machine_is_igep0020()) {
111 pr_debug("Not IGEP v2!\n");
112 return -ENODEV;
113 }
114 printk(KERN_INFO "IGEP v2 SoC init\n");
115
116 igep2_snd_device = platform_device_alloc("soc-audio", -1);
117 if (!igep2_snd_device) {
118 printk(KERN_ERR "Platform device allocation failed\n");
119 return -ENOMEM;
120 }
121
122 platform_set_drvdata(igep2_snd_device, &igep2_snd_devdata);
123 igep2_snd_devdata.dev = &igep2_snd_device->dev;
124 *(unsigned int *)igep2_dai.cpu_dai->private_data = 1; /* McBSP2 */
125
126 ret = platform_device_add(igep2_snd_device);
127 if (ret)
128 goto err1;
129
130 return 0;
131
132err1:
133 printk(KERN_ERR "Unable to add platform device\n");
134 platform_device_put(igep2_snd_device);
135
136 return ret;
137}
138module_init(igep2_soc_init);
139
140static void __exit igep2_soc_exit(void)
141{
142 platform_device_unregister(igep2_snd_device);
143}
144module_exit(igep2_soc_exit);
145
146MODULE_AUTHOR("Enric Balletbo i Serra <eballetbo@iseebcn.com>");
147MODULE_DESCRIPTION("ALSA SoC IGEP v2");
148MODULE_LICENSE("GPL");
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/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 5735945788bf..6a829eef2a4f 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -195,8 +195,12 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
195 else 195 else
196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ); 196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
197 197
198 omap_set_dma_src_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); 198 if (!(cpu_class_is_omap1())) {
199 omap_set_dma_dest_burst_mode(prtd->dma_ch, OMAP_DMA_DATA_BURST_16); 199 omap_set_dma_src_burst_mode(prtd->dma_ch,
200 OMAP_DMA_DATA_BURST_16);
201 omap_set_dma_dest_burst_mode(prtd->dma_ch,
202 OMAP_DMA_DATA_BURST_16);
203 }
200 204
201 return 0; 205 return 0;
202} 206}
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 9114c263077b..f484dcd63408 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;
@@ -144,4 +151,4 @@ module_exit(omap3evm_soc_exit);
144 151
145MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>"); 152MODULE_AUTHOR("Anuj Aggarwal <anuj.aggarwal@ti.com>");
146MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM"); 153MODULE_DESCRIPTION("ALSA SoC OMAP3 EVM");
147MODULE_LICENSE("GPLv2"); 154MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index ad219aaf7cb8..71b2c161158d 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);
@@ -134,7 +130,7 @@ static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
134 * |P| <--- TWL4030 <--------- Line In and MICs 130 * |P| <--- TWL4030 <--------- Line In and MICs
135 */ 131 */
136static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = { 132static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
137 SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0), 133 SND_SOC_DAPM_DAC("PCM DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0),
138 SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM, 134 SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
139 0, 0, NULL, 0, omap3pandora_hp_event, 135 0, 0, NULL, 0, omap3pandora_hp_event,
140 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), 136 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -181,6 +177,7 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec)
181 snd_soc_dapm_nc_pin(codec, "CARKITR"); 177 snd_soc_dapm_nc_pin(codec, "CARKITR");
182 snd_soc_dapm_nc_pin(codec, "HFL"); 178 snd_soc_dapm_nc_pin(codec, "HFL");
183 snd_soc_dapm_nc_pin(codec, "HFR"); 179 snd_soc_dapm_nc_pin(codec, "HFR");
180 snd_soc_dapm_nc_pin(codec, "VIBRA");
184 181
185 ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets, 182 ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
186 ARRAY_SIZE(omap3pandora_out_dapm_widgets)); 183 ARRAY_SIZE(omap3pandora_out_dapm_widgets));
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index ec4f8fd8b3a2..97a4d6308bd6 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -107,8 +107,8 @@ static int __init overo_soc_init(void)
107{ 107{
108 int ret; 108 int ret;
109 109
110 if (!machine_is_overo()) { 110 if (!(machine_is_overo() || machine_is_cm_t35())) {
111 pr_debug("Not Overo!\n"); 111 pr_debug("Incomatible machine!\n");
112 return -ENODEV; 112 return -ENODEV;
113 } 113 }
114 printk(KERN_INFO "overo SoC init\n"); 114 printk(KERN_INFO "overo SoC init\n");
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index dcb3181bb340..376e14a9c273 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -90,7 +90,8 @@ config SND_PXA2XX_SOC_E800
90 90
91config SND_PXA2XX_SOC_EM_X270 91config SND_PXA2XX_SOC_EM_X270
92 tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300" 92 tristate "SoC Audio support for CompuLab EM-x270, eXeda and CM-X300"
93 depends on SND_PXA2XX_SOC && MACH_EM_X270 93 depends on SND_PXA2XX_SOC && (MACH_EM_X270 || MACH_EXEDA || \
94 MACH_CM_X300)
94 select SND_PXA2XX_SOC_AC97 95 select SND_PXA2XX_SOC_AC97
95 select SND_SOC_WM9712 96 select SND_SOC_WM9712
96 help 97 help
@@ -117,6 +118,15 @@ config SND_SOC_ZYLONITE
117 Say Y if you want to add support for SoC audio on the 118 Say Y if you want to add support for SoC audio on the
118 Marvell Zylonite reference platform. 119 Marvell Zylonite reference platform.
119 120
121config SND_SOC_RAUMFELD
122 tristate "SoC Audio support Raumfeld audio adapter"
123 depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR)
124 select SND_PXA_SOC_SSP
125 select SND_SOC_CS4270
126 select SND_SOC_AK4104
127 help
128 Say Y if you want to add support for SoC audio on Raumfeld devices
129
120config SND_PXA2XX_SOC_MAGICIAN 130config SND_PXA2XX_SOC_MAGICIAN
121 tristate "SoC Audio support for HTC Magician" 131 tristate "SoC Audio support for HTC Magician"
122 depends on SND_PXA2XX_SOC && MACH_MAGICIAN 132 depends on SND_PXA2XX_SOC && MACH_MAGICIAN
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 6e096b480335..f3e08fd40ca2 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -23,6 +23,7 @@ snd-soc-zylonite-objs := zylonite.o
23snd-soc-magician-objs := magician.o 23snd-soc-magician-objs := magician.o
24snd-soc-mioa701-objs := mioa701_wm9713.o 24snd-soc-mioa701-objs := mioa701_wm9713.o
25snd-soc-imote2-objs := imote2.o 25snd-soc-imote2-objs := imote2.o
26snd-soc-raumfeld-objs := raumfeld.o
26 27
27obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o 28obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
28obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o 29obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -37,3 +38,4 @@ obj-$(CONFIG_SND_PXA2XX_SOC_MAGICIAN) += snd-soc-magician.o
37obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o 38obj-$(CONFIG_SND_PXA2XX_SOC_MIOA701) += snd-soc-mioa701.o
38obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o 39obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
39obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o 40obj-$(CONFIG_SND_PXA2XX_SOC_IMOTE2) += snd-soc-imote2.o
41obj-$(CONFIG_SND_SOC_RAUMFELD) += snd-soc-raumfeld.o
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 9f7c61e23daf..4c8d99a8d386 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -213,7 +213,7 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
213 return ret; 213 return ret;
214 214
215 /* set SSP audio pll clock */ 215 /* set SSP audio pll clock */
216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, acps); 216 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, acps);
217 if (ret < 0) 217 if (ret < 0)
218 return ret; 218 return ret;
219 219
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index d11a6d7e384a..3bd7712f029b 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -305,8 +305,8 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
305/* 305/*
306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only) 306 * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
307 */ 307 */
308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, 308static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
309 int pll_id, unsigned int freq_in, unsigned int freq_out) 309 int source, unsigned int freq_in, unsigned int freq_out)
310{ 310{
311 struct ssp_priv *priv = cpu_dai->private_data; 311 struct ssp_priv *priv = cpu_dai->private_data;
312 struct ssp_device *ssp = priv->dev.ssp; 312 struct ssp_device *ssp = priv->dev.ssp;
@@ -760,13 +760,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
760 .resume = pxa_ssp_resume, 760 .resume = pxa_ssp_resume,
761 .playback = { 761 .playback = {
762 .channels_min = 1, 762 .channels_min = 1,
763 .channels_max = 2, 763 .channels_max = 8,
764 .rates = PXA_SSP_RATES, 764 .rates = PXA_SSP_RATES,
765 .formats = PXA_SSP_FORMATS, 765 .formats = PXA_SSP_FORMATS,
766 }, 766 },
767 .capture = { 767 .capture = {
768 .channels_min = 1, 768 .channels_min = 1,
769 .channels_max = 2, 769 .channels_max = 8,
770 .rates = PXA_SSP_RATES, 770 .rates = PXA_SSP_RATES,
771 .formats = PXA_SSP_FORMATS, 771 .formats = PXA_SSP_FORMATS,
772 }, 772 },
@@ -780,13 +780,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
780 .resume = pxa_ssp_resume, 780 .resume = pxa_ssp_resume,
781 .playback = { 781 .playback = {
782 .channels_min = 1, 782 .channels_min = 1,
783 .channels_max = 2, 783 .channels_max = 8,
784 .rates = PXA_SSP_RATES, 784 .rates = PXA_SSP_RATES,
785 .formats = PXA_SSP_FORMATS, 785 .formats = PXA_SSP_FORMATS,
786 }, 786 },
787 .capture = { 787 .capture = {
788 .channels_min = 1, 788 .channels_min = 1,
789 .channels_max = 2, 789 .channels_max = 8,
790 .rates = PXA_SSP_RATES, 790 .rates = PXA_SSP_RATES,
791 .formats = PXA_SSP_FORMATS, 791 .formats = PXA_SSP_FORMATS,
792 }, 792 },
@@ -801,13 +801,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
801 .resume = pxa_ssp_resume, 801 .resume = pxa_ssp_resume,
802 .playback = { 802 .playback = {
803 .channels_min = 1, 803 .channels_min = 1,
804 .channels_max = 2, 804 .channels_max = 8,
805 .rates = PXA_SSP_RATES, 805 .rates = PXA_SSP_RATES,
806 .formats = PXA_SSP_FORMATS, 806 .formats = PXA_SSP_FORMATS,
807 }, 807 },
808 .capture = { 808 .capture = {
809 .channels_min = 1, 809 .channels_min = 1,
810 .channels_max = 2, 810 .channels_max = 8,
811 .rates = PXA_SSP_RATES, 811 .rates = PXA_SSP_RATES,
812 .formats = PXA_SSP_FORMATS, 812 .formats = PXA_SSP_FORMATS,
813 }, 813 },
@@ -822,13 +822,13 @@ struct snd_soc_dai pxa_ssp_dai[] = {
822 .resume = pxa_ssp_resume, 822 .resume = pxa_ssp_resume,
823 .playback = { 823 .playback = {
824 .channels_min = 1, 824 .channels_min = 1,
825 .channels_max = 2, 825 .channels_max = 8,
826 .rates = PXA_SSP_RATES, 826 .rates = PXA_SSP_RATES,
827 .formats = PXA_SSP_FORMATS, 827 .formats = PXA_SSP_FORMATS,
828 }, 828 },
829 .capture = { 829 .capture = {
830 .channels_min = 1, 830 .channels_min = 1,
831 .channels_max = 2, 831 .channels_max = 8,
832 .rates = PXA_SSP_RATES, 832 .rates = PXA_SSP_RATES,
833 .formats = PXA_SSP_FORMATS, 833 .formats = PXA_SSP_FORMATS,
834 }, 834 },
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
new file mode 100644
index 000000000000..acfce1c0f1c9
--- /dev/null
+++ b/sound/soc/pxa/raumfeld.c
@@ -0,0 +1,335 @@
1/*
2 * raumfeld_audio.c -- SoC audio for Raumfeld audio devices
3 *
4 * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
5 *
6 * based on code from:
7 *
8 * Wolfson Microelectronics PLC.
9 * Openedhand Ltd.
10 * Liam Girdwood <lrg@slimlogic.co.uk>
11 * Richard Purdie <richard@openedhand.com>
12 *
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version.
17 */
18
19#include <linux/module.h>
20#include <linux/i2c.h>
21#include <linux/delay.h>
22#include <linux/gpio.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
29#include "../codecs/cs4270.h"
30#include "../codecs/ak4104.h"
31#include "pxa2xx-pcm.h"
32#include "pxa-ssp.h"
33
34#define GPIO_SPDIF_RESET (38)
35#define GPIO_MCLK_RESET (111)
36#define GPIO_CODEC_RESET (120)
37
38static struct i2c_client *max9486_client;
39static struct i2c_board_info max9486_hwmon_info = {
40 I2C_BOARD_INFO("max9485", 0x63),
41};
42
43#define MAX9485_MCLK_FREQ_112896 0x22
44#define MAX9485_MCLK_FREQ_122880 0x23
45
46static void set_max9485_clk(char clk)
47{
48 i2c_master_send(max9486_client, &clk, 1);
49}
50
51static void raumfeld_enable_audio(bool en)
52{
53 if (en) {
54 gpio_set_value(GPIO_MCLK_RESET, 1);
55
56 /* wait some time to let the clocks become stable */
57 msleep(100);
58
59 gpio_set_value(GPIO_SPDIF_RESET, 1);
60 gpio_set_value(GPIO_CODEC_RESET, 1);
61 } else {
62 gpio_set_value(GPIO_MCLK_RESET, 0);
63 gpio_set_value(GPIO_SPDIF_RESET, 0);
64 gpio_set_value(GPIO_CODEC_RESET, 0);
65 }
66}
67
68/* CS4270 */
69static int raumfeld_cs4270_startup(struct snd_pcm_substream *substream)
70{
71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
73
74 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
75
76 return snd_soc_dai_set_sysclk(codec_dai, 0, 11289600, 0);
77}
78
79static int raumfeld_cs4270_hw_params(struct snd_pcm_substream *substream,
80 struct snd_pcm_hw_params *params)
81{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
84 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
85 unsigned int fmt, clk = 0;
86 int ret = 0;
87
88 switch (params_rate(params)) {
89 case 8000:
90 case 16000:
91 case 48000:
92 case 96000:
93 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
94 clk = 12288000;
95 break;
96 case 11025:
97 case 22050:
98 case 44100:
99 case 88200:
100 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
101 clk = 11289600;
102 break;
103 }
104
105 fmt = SND_SOC_DAIFMT_I2S |
106 SND_SOC_DAIFMT_NB_NF |
107 SND_SOC_DAIFMT_CBS_CFS;
108
109 /* setup the CODEC DAI */
110 ret = snd_soc_dai_set_fmt(codec_dai, fmt);
111 if (ret < 0)
112 return ret;
113
114 ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk, 0);
115 if (ret < 0)
116 return ret;
117
118 /* setup the CPU DAI */
119 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
120 if (ret < 0)
121 return ret;
122
123 ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
124 if (ret < 0)
125 return ret;
126
127 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
128 if (ret < 0)
129 return ret;
130
131 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, 0, 1);
132 if (ret < 0)
133 return ret;
134
135 return 0;
136}
137
138static struct snd_soc_ops raumfeld_cs4270_ops = {
139 .startup = raumfeld_cs4270_startup,
140 .hw_params = raumfeld_cs4270_hw_params,
141};
142
143static int raumfeld_line_suspend(struct platform_device *pdev, pm_message_t state)
144{
145 raumfeld_enable_audio(false);
146 return 0;
147}
148
149static int raumfeld_line_resume(struct platform_device *pdev)
150{
151 raumfeld_enable_audio(true);
152 return 0;
153}
154
155static struct snd_soc_dai_link raumfeld_line_dai = {
156 .name = "CS4270",
157 .stream_name = "CS4270",
158 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP1],
159 .codec_dai = &cs4270_dai,
160 .ops = &raumfeld_cs4270_ops,
161};
162
163static struct snd_soc_card snd_soc_line_raumfeld = {
164 .name = "Raumfeld analog",
165 .platform = &pxa2xx_soc_platform,
166 .dai_link = &raumfeld_line_dai,
167 .suspend_post = raumfeld_line_suspend,
168 .resume_pre = raumfeld_line_resume,
169 .num_links = 1,
170};
171
172
173/* AK4104 */
174
175static int raumfeld_ak4104_hw_params(struct snd_pcm_substream *substream,
176 struct snd_pcm_hw_params *params)
177{
178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
180 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
181 int fmt, ret = 0, clk = 0;
182
183 switch (params_rate(params)) {
184 case 8000:
185 case 16000:
186 case 48000:
187 case 96000:
188 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
189 clk = 12288000;
190 break;
191 case 11025:
192 case 22050:
193 case 44100:
194 case 88200:
195 set_max9485_clk(MAX9485_MCLK_FREQ_112896);
196 clk = 11289600;
197 break;
198 }
199
200 fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF;
201
202 /* setup the CODEC DAI */
203 ret = snd_soc_dai_set_fmt(codec_dai, fmt | SND_SOC_DAIFMT_CBS_CFS);
204 if (ret < 0)
205 return ret;
206
207 /* setup the CPU DAI */
208 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, clk);
209 if (ret < 0)
210 return ret;
211
212 ret = snd_soc_dai_set_fmt(cpu_dai, fmt | SND_SOC_DAIFMT_CBS_CFS);
213 if (ret < 0)
214 return ret;
215
216 ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_DIV_SCR, 4);
217 if (ret < 0)
218 return ret;
219
220 ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_EXT, 0, 1);
221 if (ret < 0)
222 return ret;
223
224 return 0;
225}
226
227static struct snd_soc_ops raumfeld_ak4104_ops = {
228 .hw_params = raumfeld_ak4104_hw_params,
229};
230
231static struct snd_soc_dai_link raumfeld_spdif_dai = {
232 .name = "ak4104",
233 .stream_name = "Playback",
234 .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP2],
235 .codec_dai = &ak4104_dai,
236 .ops = &raumfeld_ak4104_ops,
237};
238
239static struct snd_soc_card snd_soc_spdif_raumfeld = {
240 .name = "Raumfeld S/PDIF",
241 .platform = &pxa2xx_soc_platform,
242 .dai_link = &raumfeld_spdif_dai,
243 .num_links = 1
244};
245
246/* raumfeld_audio audio subsystem */
247static struct snd_soc_device raumfeld_line_devdata = {
248 .card = &snd_soc_line_raumfeld,
249 .codec_dev = &soc_codec_device_cs4270,
250};
251
252static struct snd_soc_device raumfeld_spdif_devdata = {
253 .card = &snd_soc_spdif_raumfeld,
254 .codec_dev = &soc_codec_device_ak4104,
255};
256
257static struct platform_device *raumfeld_audio_line_device;
258static struct platform_device *raumfeld_audio_spdif_device;
259
260static int __init raumfeld_audio_init(void)
261{
262 int ret;
263
264 if (!machine_is_raumfeld_speaker() &&
265 !machine_is_raumfeld_connector())
266 return 0;
267
268 max9486_client = i2c_new_device(i2c_get_adapter(0),
269 &max9486_hwmon_info);
270
271 if (!max9486_client)
272 return -ENOMEM;
273
274 set_max9485_clk(MAX9485_MCLK_FREQ_122880);
275
276 /* LINE */
277 raumfeld_audio_line_device = platform_device_alloc("soc-audio", 0);
278 if (!raumfeld_audio_line_device)
279 return -ENOMEM;
280
281 platform_set_drvdata(raumfeld_audio_line_device,
282 &raumfeld_line_devdata);
283 raumfeld_line_devdata.dev = &raumfeld_audio_line_device->dev;
284 ret = platform_device_add(raumfeld_audio_line_device);
285 if (ret)
286 platform_device_put(raumfeld_audio_line_device);
287
288 /* no S/PDIF on Speakers */
289 if (machine_is_raumfeld_speaker())
290 return ret;
291
292 /* S/PDIF */
293 raumfeld_audio_spdif_device = platform_device_alloc("soc-audio", 1);
294 if (!raumfeld_audio_spdif_device) {
295 platform_device_put(raumfeld_audio_line_device);
296 return -ENOMEM;
297 }
298
299 platform_set_drvdata(raumfeld_audio_spdif_device,
300 &raumfeld_spdif_devdata);
301 raumfeld_spdif_devdata.dev = &raumfeld_audio_spdif_device->dev;
302 ret = platform_device_add(raumfeld_audio_spdif_device);
303 if (ret) {
304 platform_device_put(raumfeld_audio_line_device);
305 platform_device_put(raumfeld_audio_spdif_device);
306 }
307
308 raumfeld_enable_audio(true);
309
310 return ret;
311}
312
313static void __exit raumfeld_audio_exit(void)
314{
315 raumfeld_enable_audio(false);
316
317 platform_device_unregister(raumfeld_audio_line_device);
318
319 if (machine_is_raumfeld_connector())
320 platform_device_unregister(raumfeld_audio_spdif_device);
321
322 i2c_unregister_device(max9486_client);
323
324 gpio_free(GPIO_MCLK_RESET);
325 gpio_free(GPIO_CODEC_RESET);
326 gpio_free(GPIO_SPDIF_RESET);
327}
328
329module_init(raumfeld_audio_init);
330module_exit(raumfeld_audio_exit);
331
332/* Module information */
333MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
334MODULE_DESCRIPTION("Raumfeld audio SoC");
335MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index 9a386b4c4ed1..dd678ae24398 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -74,7 +74,8 @@ static const struct snd_soc_dapm_route audio_map[] = {
74static int zylonite_wm9713_init(struct snd_soc_codec *codec) 74static int zylonite_wm9713_init(struct snd_soc_codec *codec)
75{ 75{
76 if (clk_pout) 76 if (clk_pout)
77 snd_soc_dai_set_pll(&codec->dai[0], 0, clk_get_rate(pout), 0); 77 snd_soc_dai_set_pll(&codec->dai[0], 0, 0,
78 clk_get_rate(pout), 0);
78 79
79 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets, 80 snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
80 ARRAY_SIZE(zylonite_dapm_widgets)); 81 ARRAY_SIZE(zylonite_dapm_widgets));
@@ -128,7 +129,7 @@ static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
128 if (ret < 0) 129 if (ret < 0)
129 return ret; 130 return ret;
130 131
131 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out); 132 ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, 0, pll_out);
132 if (ret < 0) 133 if (ret < 0)
133 return ret; 134 return ret;
134 135
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index 923428fc1adb..b489f1ae103d 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -24,6 +24,9 @@ config SND_S3C64XX_SOC_I2S
24 select SND_S3C_I2SV2_SOC 24 select SND_S3C_I2SV2_SOC
25 select S3C64XX_DMA 25 select S3C64XX_DMA
26 26
27config SND_S3C_SOC_PCM
28 tristate
29
27config SND_S3C2443_SOC_AC97 30config SND_S3C2443_SOC_AC97
28 tristate 31 tristate
29 select S3C2410_DMA 32 select S3C2410_DMA
@@ -56,6 +59,15 @@ config SND_S3C24XX_SOC_JIVE_WM8750
56 help 59 help
57 Sat Y if you want to add support for SoC audio on the Jive. 60 Sat Y if you want to add support for SoC audio on the Jive.
58 61
62config SND_S3C64XX_SOC_WM8580
63 tristate "SoC I2S Audio support for WM8580 on SMDK64XX"
64 depends on SND_S3C24XX_SOC && (MACH_SMDK6400 || MACH_SMDK6410)
65 depends on BROKEN
66 select SND_SOC_WM8580
67 select SND_S3C64XX_SOC_I2S
68 help
69 Sat Y if you want to add support for SoC audio on the SMDK64XX.
70
59config SND_S3C24XX_SOC_SMDK2443_WM9710 71config SND_S3C24XX_SOC_SMDK2443_WM9710
60 tristate "SoC AC97 Audio support for SMDK2443 - WM9710" 72 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
61 depends on SND_S3C24XX_SOC && MACH_SMDK2443 73 depends on SND_S3C24XX_SOC && MACH_SMDK2443
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 99f5a7dd3fc6..b744657733d7 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -1,10 +1,11 @@
1# S3c24XX Platform Support 1# S3c24XX Platform Support
2snd-soc-s3c24xx-objs := s3c24xx-pcm.o 2snd-soc-s3c24xx-objs := s3c-dma.o
3snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o 3snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
4snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o 4snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
5snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o 5snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o
6snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o 6snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o
7snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o 7snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
8snd-soc-s3c-pcm-objs := s3c-pcm.o
8 9
9obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o 10obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
10obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o 11obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
@@ -12,6 +13,7 @@ obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
12obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o 13obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
13obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o 14obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
14obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o 15obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
16obj-$(CONFIG_SND_S3C_SOC_PCM) += snd-soc-s3c-pcm.o
15 17
16# S3C24XX Machine Support 18# S3C24XX Machine Support
17snd-soc-jive-wm8750-objs := jive_wm8750.o 19snd-soc-jive-wm8750-objs := jive_wm8750.o
@@ -23,6 +25,7 @@ snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
23snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o 25snd-soc-s3c24xx-simtec-objs := s3c24xx_simtec.o
24snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o 26snd-soc-s3c24xx-simtec-hermes-objs := s3c24xx_simtec_hermes.o
25snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o 27snd-soc-s3c24xx-simtec-tlv320aic23-objs := s3c24xx_simtec_tlv320aic23.o
28snd-soc-smdk64xx-wm8580-objs := smdk64xx_wm8580.o
26 29
27obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o 30obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
28obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o 31obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -33,4 +36,5 @@ obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
33obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o 36obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC) += snd-soc-s3c24xx-simtec.o
34obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o 37obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_HERMES) += snd-soc-s3c24xx-simtec-hermes.o
35obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o 38obj-$(CONFIG_SND_S3C24XX_SOC_SIMTEC_TLV320AIC23) += snd-soc-s3c24xx-simtec-tlv320aic23.o
39obj-$(CONFIG_SND_S3C64XX_SOC_WM8580) += snd-soc-smdk64xx-wm8580.o
36 40
diff --git a/sound/soc/s3c24xx/jive_wm8750.c b/sound/soc/s3c24xx/jive_wm8750.c
index 93e6c87b7399..59dc2c6b56d9 100644
--- a/sound/soc/s3c24xx/jive_wm8750.c
+++ b/sound/soc/s3c24xx/jive_wm8750.c
@@ -25,7 +25,7 @@
25 25
26#include <asm/mach-types.h> 26#include <asm/mach-types.h>
27 27
28#include "s3c24xx-pcm.h" 28#include "s3c-dma.h"
29#include "s3c2412-i2s.h" 29#include "s3c2412-i2s.h"
30 30
31#include "../codecs/wm8750.h" 31#include "../codecs/wm8750.h"
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index 12c71482d258..d00d359a03e6 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -24,7 +24,7 @@
24#include <sound/soc-dapm.h> 24#include <sound/soc-dapm.h>
25 25
26#include "../codecs/ac97.h" 26#include "../codecs/ac97.h"
27#include "s3c24xx-pcm.h" 27#include "s3c-dma.h"
28#include "s3c24xx-ac97.h" 28#include "s3c24xx-ac97.h"
29 29
30static struct snd_soc_card ln2440sbc; 30static struct snd_soc_card ln2440sbc;
diff --git a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
index 0c52e36ddd87..dea83d30a5c9 100644
--- a/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
@@ -32,7 +32,7 @@
32#include <asm/io.h> 32#include <asm/io.h>
33#include <mach/gta02.h> 33#include <mach/gta02.h>
34#include "../codecs/wm8753.h" 34#include "../codecs/wm8753.h"
35#include "s3c24xx-pcm.h" 35#include "s3c-dma.h"
36#include "s3c24xx-i2s.h" 36#include "s3c24xx-i2s.h"
37 37
38static struct snd_soc_card neo1973_gta02; 38static struct snd_soc_card neo1973_gta02;
@@ -119,7 +119,7 @@ static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
119 return ret; 119 return ret;
120 120
121 /* codec PLL input is PCLK/4 */ 121 /* codec PLL input is PCLK/4 */
122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 122 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
123 iis_clkrate / 4, pll_out); 123 iis_clkrate / 4, pll_out);
124 if (ret < 0) 124 if (ret < 0)
125 return ret; 125 return ret;
@@ -133,7 +133,7 @@ static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 133 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
134 134
135 /* disable the PLL */ 135 /* disable the PLL */
136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); 136 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
137} 137}
138 138
139/* 139/*
@@ -183,7 +183,7 @@ static int neo1973_gta02_voice_hw_params(
183 return ret; 183 return ret;
184 184
185 /* configue and enable PLL for 12.288MHz output */ 185 /* configue and enable PLL for 12.288MHz output */
186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 186 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
187 iis_clkrate / 4, 12288000); 187 iis_clkrate / 4, 12288000);
188 if (ret < 0) 188 if (ret < 0)
189 return ret; 189 return ret;
@@ -197,7 +197,7 @@ static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 197 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
198 198
199 /* disable the PLL */ 199 /* disable the PLL */
200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); 200 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
201} 201}
202 202
203static struct snd_soc_ops neo1973_gta02_voice_ops = { 203static struct snd_soc_ops neo1973_gta02_voice_ops = {
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 906709e6dd5f..0cb4f86f6d1e 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -29,7 +29,6 @@
29#include <mach/regs-clock.h> 29#include <mach/regs-clock.h>
30#include <mach/regs-gpio.h> 30#include <mach/regs-gpio.h>
31#include <mach/hardware.h> 31#include <mach/hardware.h>
32#include <plat/audio.h>
33#include <linux/io.h> 32#include <linux/io.h>
34#include <mach/spi-gpio.h> 33#include <mach/spi-gpio.h>
35 34
@@ -37,7 +36,7 @@
37 36
38#include "../codecs/wm8753.h" 37#include "../codecs/wm8753.h"
39#include "lm4857.h" 38#include "lm4857.h"
40#include "s3c24xx-pcm.h" 39#include "s3c-dma.h"
41#include "s3c24xx-i2s.h" 40#include "s3c24xx-i2s.h"
42 41
43/* define the scenarios */ 42/* define the scenarios */
@@ -137,7 +136,7 @@ static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
137 return ret; 136 return ret;
138 137
139 /* codec PLL input is PCLK/4 */ 138 /* codec PLL input is PCLK/4 */
140 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 139 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0,
141 iis_clkrate / 4, pll_out); 140 iis_clkrate / 4, pll_out);
142 if (ret < 0) 141 if (ret < 0)
143 return ret; 142 return ret;
@@ -153,7 +152,7 @@ static int neo1973_hifi_hw_free(struct snd_pcm_substream *substream)
153 pr_debug("Entered %s\n", __func__); 152 pr_debug("Entered %s\n", __func__);
154 153
155 /* disable the PLL */ 154 /* disable the PLL */
156 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0); 155 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0, 0);
157} 156}
158 157
159/* 158/*
@@ -203,7 +202,7 @@ static int neo1973_voice_hw_params(struct snd_pcm_substream *substream,
203 return ret; 202 return ret;
204 203
205 /* configue and enable PLL for 12.288MHz output */ 204 /* configue and enable PLL for 12.288MHz output */
206 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 205 ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0,
207 iis_clkrate / 4, 12288000); 206 iis_clkrate / 4, 12288000);
208 if (ret < 0) 207 if (ret < 0)
209 return ret; 208 return ret;
@@ -219,7 +218,7 @@ static int neo1973_voice_hw_free(struct snd_pcm_substream *substream)
219 pr_debug("Entered %s\n", __func__); 218 pr_debug("Entered %s\n", __func__);
220 219
221 /* disable the PLL */ 220 /* disable the PLL */
222 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0); 221 return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0, 0);
223} 222}
224 223
225static struct snd_soc_ops neo1973_voice_ops = { 224static struct snd_soc_ops neo1973_voice_ops = {
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c-dma.c
index 5cbbdc80fde3..7725e26d6c91 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c-dma.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * s3c24xx-pcm.c -- ALSA Soc Audio Layer 2 * s3c-dma.c -- ALSA Soc Audio Layer
3 * 3 *
4 * (c) 2006 Wolfson Microelectronics PLC. 4 * (c) 2006 Wolfson Microelectronics PLC.
5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com 5 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
@@ -29,11 +29,10 @@
29#include <asm/dma.h> 29#include <asm/dma.h>
30#include <mach/hardware.h> 30#include <mach/hardware.h>
31#include <mach/dma.h> 31#include <mach/dma.h>
32#include <plat/audio.h>
33 32
34#include "s3c24xx-pcm.h" 33#include "s3c-dma.h"
35 34
36static const struct snd_pcm_hardware s3c24xx_pcm_hardware = { 35static const struct snd_pcm_hardware s3c_dma_hardware = {
37 .info = SNDRV_PCM_INFO_INTERLEAVED | 36 .info = SNDRV_PCM_INFO_INTERLEAVED |
38 SNDRV_PCM_INFO_BLOCK_TRANSFER | 37 SNDRV_PCM_INFO_BLOCK_TRANSFER |
39 SNDRV_PCM_INFO_MMAP | 38 SNDRV_PCM_INFO_MMAP |
@@ -63,23 +62,32 @@ struct s3c24xx_runtime_data {
63 dma_addr_t dma_start; 62 dma_addr_t dma_start;
64 dma_addr_t dma_pos; 63 dma_addr_t dma_pos;
65 dma_addr_t dma_end; 64 dma_addr_t dma_end;
66 struct s3c24xx_pcm_dma_params *params; 65 struct s3c_dma_params *params;
67}; 66};
68 67
69/* s3c24xx_pcm_enqueue 68/* s3c_dma_enqueue
70 * 69 *
71 * place a dma buffer onto the queue for the dma system 70 * place a dma buffer onto the queue for the dma system
72 * to handle. 71 * to handle.
73*/ 72*/
74static void s3c24xx_pcm_enqueue(struct snd_pcm_substream *substream) 73static void s3c_dma_enqueue(struct snd_pcm_substream *substream)
75{ 74{
76 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 75 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
77 dma_addr_t pos = prtd->dma_pos; 76 dma_addr_t pos = prtd->dma_pos;
77 unsigned int limit;
78 int ret; 78 int ret;
79 79
80 pr_debug("Entered %s\n", __func__); 80 pr_debug("Entered %s\n", __func__);
81 81
82 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",
88 __func__, prtd->dma_loaded, limit);
89
90 while (prtd->dma_loaded < limit) {
83 unsigned long len = prtd->dma_period; 91 unsigned long len = prtd->dma_period;
84 92
85 pr_debug("dma_loaded: %d\n", prtd->dma_loaded); 93 pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
@@ -123,21 +131,21 @@ static void s3c24xx_audio_buffdone(struct s3c2410_dma_chan *channel,
123 snd_pcm_period_elapsed(substream); 131 snd_pcm_period_elapsed(substream);
124 132
125 spin_lock(&prtd->lock); 133 spin_lock(&prtd->lock);
126 if (prtd->state & ST_RUNNING) { 134 if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
127 prtd->dma_loaded--; 135 prtd->dma_loaded--;
128 s3c24xx_pcm_enqueue(substream); 136 s3c_dma_enqueue(substream);
129 } 137 }
130 138
131 spin_unlock(&prtd->lock); 139 spin_unlock(&prtd->lock);
132} 140}
133 141
134static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream, 142static int s3c_dma_hw_params(struct snd_pcm_substream *substream,
135 struct snd_pcm_hw_params *params) 143 struct snd_pcm_hw_params *params)
136{ 144{
137 struct snd_pcm_runtime *runtime = substream->runtime; 145 struct snd_pcm_runtime *runtime = substream->runtime;
138 struct s3c24xx_runtime_data *prtd = runtime->private_data; 146 struct s3c24xx_runtime_data *prtd = runtime->private_data;
139 struct snd_soc_pcm_runtime *rtd = substream->private_data; 147 struct snd_soc_pcm_runtime *rtd = substream->private_data;
140 struct s3c24xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data; 148 struct s3c_dma_params *dma = rtd->dai->cpu_dai->dma_data;
141 unsigned long totbytes = params_buffer_bytes(params); 149 unsigned long totbytes = params_buffer_bytes(params);
142 int ret = 0; 150 int ret = 0;
143 151
@@ -164,6 +172,11 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
164 printk(KERN_ERR "failed to get dma channel\n"); 172 printk(KERN_ERR "failed to get dma channel\n");
165 return ret; 173 return ret;
166 } 174 }
175
176 /* use the circular buffering if we have it available. */
177 if (s3c_dma_has_circular())
178 s3c2410_dma_setflags(prtd->params->channel,
179 S3C2410_DMAF_CIRCULAR);
167 } 180 }
168 181
169 s3c2410_dma_set_buffdone_fn(prtd->params->channel, 182 s3c2410_dma_set_buffdone_fn(prtd->params->channel,
@@ -185,7 +198,7 @@ static int s3c24xx_pcm_hw_params(struct snd_pcm_substream *substream,
185 return 0; 198 return 0;
186} 199}
187 200
188static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream) 201static int s3c_dma_hw_free(struct snd_pcm_substream *substream)
189{ 202{
190 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 203 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
191 204
@@ -202,7 +215,7 @@ static int s3c24xx_pcm_hw_free(struct snd_pcm_substream *substream)
202 return 0; 215 return 0;
203} 216}
204 217
205static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream) 218static int s3c_dma_prepare(struct snd_pcm_substream *substream)
206{ 219{
207 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 220 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
208 int ret = 0; 221 int ret = 0;
@@ -235,12 +248,12 @@ static int s3c24xx_pcm_prepare(struct snd_pcm_substream *substream)
235 prtd->dma_pos = prtd->dma_start; 248 prtd->dma_pos = prtd->dma_start;
236 249
237 /* enqueue dma buffers */ 250 /* enqueue dma buffers */
238 s3c24xx_pcm_enqueue(substream); 251 s3c_dma_enqueue(substream);
239 252
240 return ret; 253 return ret;
241} 254}
242 255
243static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd) 256static int s3c_dma_trigger(struct snd_pcm_substream *substream, int cmd)
244{ 257{
245 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data; 258 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
246 int ret = 0; 259 int ret = 0;
@@ -275,7 +288,7 @@ static int s3c24xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
275} 288}
276 289
277static snd_pcm_uframes_t 290static snd_pcm_uframes_t
278s3c24xx_pcm_pointer(struct snd_pcm_substream *substream) 291s3c_dma_pointer(struct snd_pcm_substream *substream)
279{ 292{
280 struct snd_pcm_runtime *runtime = substream->runtime; 293 struct snd_pcm_runtime *runtime = substream->runtime;
281 struct s3c24xx_runtime_data *prtd = runtime->private_data; 294 struct s3c24xx_runtime_data *prtd = runtime->private_data;
@@ -310,7 +323,7 @@ s3c24xx_pcm_pointer(struct snd_pcm_substream *substream)
310 return bytes_to_frames(substream->runtime, res); 323 return bytes_to_frames(substream->runtime, res);
311} 324}
312 325
313static int s3c24xx_pcm_open(struct snd_pcm_substream *substream) 326static int s3c_dma_open(struct snd_pcm_substream *substream)
314{ 327{
315 struct snd_pcm_runtime *runtime = substream->runtime; 328 struct snd_pcm_runtime *runtime = substream->runtime;
316 struct s3c24xx_runtime_data *prtd; 329 struct s3c24xx_runtime_data *prtd;
@@ -318,7 +331,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
318 pr_debug("Entered %s\n", __func__); 331 pr_debug("Entered %s\n", __func__);
319 332
320 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS); 333 snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
321 snd_soc_set_runtime_hwparams(substream, &s3c24xx_pcm_hardware); 334 snd_soc_set_runtime_hwparams(substream, &s3c_dma_hardware);
322 335
323 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL); 336 prtd = kzalloc(sizeof(struct s3c24xx_runtime_data), GFP_KERNEL);
324 if (prtd == NULL) 337 if (prtd == NULL)
@@ -330,7 +343,7 @@ static int s3c24xx_pcm_open(struct snd_pcm_substream *substream)
330 return 0; 343 return 0;
331} 344}
332 345
333static int s3c24xx_pcm_close(struct snd_pcm_substream *substream) 346static int s3c_dma_close(struct snd_pcm_substream *substream)
334{ 347{
335 struct snd_pcm_runtime *runtime = substream->runtime; 348 struct snd_pcm_runtime *runtime = substream->runtime;
336 struct s3c24xx_runtime_data *prtd = runtime->private_data; 349 struct s3c24xx_runtime_data *prtd = runtime->private_data;
@@ -338,14 +351,14 @@ static int s3c24xx_pcm_close(struct snd_pcm_substream *substream)
338 pr_debug("Entered %s\n", __func__); 351 pr_debug("Entered %s\n", __func__);
339 352
340 if (!prtd) 353 if (!prtd)
341 pr_debug("s3c24xx_pcm_close called with prtd == NULL\n"); 354 pr_debug("s3c_dma_close called with prtd == NULL\n");
342 355
343 kfree(prtd); 356 kfree(prtd);
344 357
345 return 0; 358 return 0;
346} 359}
347 360
348static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream, 361static int s3c_dma_mmap(struct snd_pcm_substream *substream,
349 struct vm_area_struct *vma) 362 struct vm_area_struct *vma)
350{ 363{
351 struct snd_pcm_runtime *runtime = substream->runtime; 364 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -358,23 +371,23 @@ static int s3c24xx_pcm_mmap(struct snd_pcm_substream *substream,
358 runtime->dma_bytes); 371 runtime->dma_bytes);
359} 372}
360 373
361static struct snd_pcm_ops s3c24xx_pcm_ops = { 374static struct snd_pcm_ops s3c_dma_ops = {
362 .open = s3c24xx_pcm_open, 375 .open = s3c_dma_open,
363 .close = s3c24xx_pcm_close, 376 .close = s3c_dma_close,
364 .ioctl = snd_pcm_lib_ioctl, 377 .ioctl = snd_pcm_lib_ioctl,
365 .hw_params = s3c24xx_pcm_hw_params, 378 .hw_params = s3c_dma_hw_params,
366 .hw_free = s3c24xx_pcm_hw_free, 379 .hw_free = s3c_dma_hw_free,
367 .prepare = s3c24xx_pcm_prepare, 380 .prepare = s3c_dma_prepare,
368 .trigger = s3c24xx_pcm_trigger, 381 .trigger = s3c_dma_trigger,
369 .pointer = s3c24xx_pcm_pointer, 382 .pointer = s3c_dma_pointer,
370 .mmap = s3c24xx_pcm_mmap, 383 .mmap = s3c_dma_mmap,
371}; 384};
372 385
373static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 386static int s3c_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
374{ 387{
375 struct snd_pcm_substream *substream = pcm->streams[stream].substream; 388 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
376 struct snd_dma_buffer *buf = &substream->dma_buffer; 389 struct snd_dma_buffer *buf = &substream->dma_buffer;
377 size_t size = s3c24xx_pcm_hardware.buffer_bytes_max; 390 size_t size = s3c_dma_hardware.buffer_bytes_max;
378 391
379 pr_debug("Entered %s\n", __func__); 392 pr_debug("Entered %s\n", __func__);
380 393
@@ -389,7 +402,7 @@ static int s3c24xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
389 return 0; 402 return 0;
390} 403}
391 404
392static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm) 405static void s3c_dma_free_dma_buffers(struct snd_pcm *pcm)
393{ 406{
394 struct snd_pcm_substream *substream; 407 struct snd_pcm_substream *substream;
395 struct snd_dma_buffer *buf; 408 struct snd_dma_buffer *buf;
@@ -412,9 +425,9 @@ static void s3c24xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
412 } 425 }
413} 426}
414 427
415static u64 s3c24xx_pcm_dmamask = DMA_BIT_MASK(32); 428static u64 s3c_dma_mask = DMA_BIT_MASK(32);
416 429
417static int s3c24xx_pcm_new(struct snd_card *card, 430static int s3c_dma_new(struct snd_card *card,
418 struct snd_soc_dai *dai, struct snd_pcm *pcm) 431 struct snd_soc_dai *dai, struct snd_pcm *pcm)
419{ 432{
420 int ret = 0; 433 int ret = 0;
@@ -422,19 +435,19 @@ static int s3c24xx_pcm_new(struct snd_card *card,
422 pr_debug("Entered %s\n", __func__); 435 pr_debug("Entered %s\n", __func__);
423 436
424 if (!card->dev->dma_mask) 437 if (!card->dev->dma_mask)
425 card->dev->dma_mask = &s3c24xx_pcm_dmamask; 438 card->dev->dma_mask = &s3c_dma_mask;
426 if (!card->dev->coherent_dma_mask) 439 if (!card->dev->coherent_dma_mask)
427 card->dev->coherent_dma_mask = 0xffffffff; 440 card->dev->coherent_dma_mask = 0xffffffff;
428 441
429 if (dai->playback.channels_min) { 442 if (dai->playback.channels_min) {
430 ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, 443 ret = s3c_preallocate_dma_buffer(pcm,
431 SNDRV_PCM_STREAM_PLAYBACK); 444 SNDRV_PCM_STREAM_PLAYBACK);
432 if (ret) 445 if (ret)
433 goto out; 446 goto out;
434 } 447 }
435 448
436 if (dai->capture.channels_min) { 449 if (dai->capture.channels_min) {
437 ret = s3c24xx_pcm_preallocate_dma_buffer(pcm, 450 ret = s3c_preallocate_dma_buffer(pcm,
438 SNDRV_PCM_STREAM_CAPTURE); 451 SNDRV_PCM_STREAM_CAPTURE);
439 if (ret) 452 if (ret)
440 goto out; 453 goto out;
@@ -445,9 +458,9 @@ static int s3c24xx_pcm_new(struct snd_card *card,
445 458
446struct snd_soc_platform s3c24xx_soc_platform = { 459struct snd_soc_platform s3c24xx_soc_platform = {
447 .name = "s3c24xx-audio", 460 .name = "s3c24xx-audio",
448 .pcm_ops = &s3c24xx_pcm_ops, 461 .pcm_ops = &s3c_dma_ops,
449 .pcm_new = s3c24xx_pcm_new, 462 .pcm_new = s3c_dma_new,
450 .pcm_free = s3c24xx_pcm_free_dma_buffers, 463 .pcm_free = s3c_dma_free_dma_buffers,
451}; 464};
452EXPORT_SYMBOL_GPL(s3c24xx_soc_platform); 465EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
453 466
@@ -464,5 +477,5 @@ static void __exit s3c24xx_soc_platform_exit(void)
464module_exit(s3c24xx_soc_platform_exit); 477module_exit(s3c24xx_soc_platform_exit);
465 478
466MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 479MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
467MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module"); 480MODULE_DESCRIPTION("Samsung S3C Audio DMA module");
468MODULE_LICENSE("GPL"); 481MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.h b/sound/soc/s3c24xx/s3c-dma.h
index 0088c79822ea..69bb6bf6fc1c 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.h
+++ b/sound/soc/s3c24xx/s3c-dma.h
@@ -1,5 +1,5 @@
1/* 1/*
2 * s3c24xx-pcm.h -- 2 * s3c-dma.h --
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the 5 * under the terms of the GNU General Public License as published by the
@@ -9,13 +9,13 @@
9 * ALSA PCM interface for the Samsung S3C24xx CPU 9 * ALSA PCM interface for the Samsung S3C24xx CPU
10 */ 10 */
11 11
12#ifndef _S3C24XX_PCM_H 12#ifndef _S3C_AUDIO_H
13#define _S3C24XX_PCM_H 13#define _S3C_AUDIO_H
14 14
15#define ST_RUNNING (1<<0) 15#define ST_RUNNING (1<<0)
16#define ST_OPENED (1<<1) 16#define ST_OPENED (1<<1)
17 17
18struct s3c24xx_pcm_dma_params { 18struct s3c_dma_params {
19 struct s3c2410_dma_client *client; /* stream identifier */ 19 struct s3c2410_dma_client *client; /* stream identifier */
20 int channel; /* Channel ID */ 20 int channel; /* Channel ID */
21 dma_addr_t dma_addr; 21 dma_addr_t dma_addr;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.c b/sound/soc/s3c24xx/s3c-i2s-v2.c
index 9bc4aa35caab..e994d8374fe6 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.c
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.c
@@ -32,11 +32,10 @@
32 32
33#include <plat/regs-s3c2412-iis.h> 33#include <plat/regs-s3c2412-iis.h>
34 34
35#include <plat/audio.h>
36#include <mach/dma.h> 35#include <mach/dma.h>
37 36
38#include "s3c-i2s-v2.h" 37#include "s3c-i2s-v2.h"
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40 39
41#undef S3C_IIS_V2_SUPPORTED 40#undef S3C_IIS_V2_SUPPORTED
42 41
@@ -312,12 +311,15 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
312 311
313 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 312 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
314 case SND_SOC_DAIFMT_RIGHT_J: 313 case SND_SOC_DAIFMT_RIGHT_J:
314 iismod |= S3C2412_IISMOD_LR_RLOW;
315 iismod |= S3C2412_IISMOD_SDF_MSB; 315 iismod |= S3C2412_IISMOD_SDF_MSB;
316 break; 316 break;
317 case SND_SOC_DAIFMT_LEFT_J: 317 case SND_SOC_DAIFMT_LEFT_J:
318 iismod |= S3C2412_IISMOD_LR_RLOW;
318 iismod |= S3C2412_IISMOD_SDF_LSB; 319 iismod |= S3C2412_IISMOD_SDF_LSB;
319 break; 320 break;
320 case SND_SOC_DAIFMT_I2S: 321 case SND_SOC_DAIFMT_I2S:
322 iismod &= ~S3C2412_IISMOD_LR_RLOW;
321 iismod |= S3C2412_IISMOD_SDF_IIS; 323 iismod |= S3C2412_IISMOD_SDF_IIS;
322 break; 324 break;
323 default: 325 default:
@@ -392,7 +394,7 @@ static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
392 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE); 394 int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
393 unsigned long irqs; 395 unsigned long irqs;
394 int ret = 0; 396 int ret = 0;
395 int channel = ((struct s3c24xx_pcm_dma_params *) 397 int channel = ((struct s3c_dma_params *)
396 rtd->dai->cpu_dai->dma_data)->channel; 398 rtd->dai->cpu_dai->dma_data)->channel;
397 399
398 pr_debug("Entered %s\n", __func__); 400 pr_debug("Entered %s\n", __func__);
@@ -467,6 +469,31 @@ static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
467 469
468 switch (div_id) { 470 switch (div_id) {
469 case S3C_I2SV2_DIV_BCLK: 471 case S3C_I2SV2_DIV_BCLK:
472 if (div > 3) {
473 /* convert value to bit field */
474
475 switch (div) {
476 case 16:
477 div = S3C2412_IISMOD_BCLK_16FS;
478 break;
479
480 case 32:
481 div = S3C2412_IISMOD_BCLK_32FS;
482 break;
483
484 case 24:
485 div = S3C2412_IISMOD_BCLK_24FS;
486 break;
487
488 case 48:
489 div = S3C2412_IISMOD_BCLK_48FS;
490 break;
491
492 default:
493 return -EINVAL;
494 }
495 }
496
470 reg = readl(i2s->regs + S3C2412_IISMOD); 497 reg = readl(i2s->regs + S3C2412_IISMOD);
471 reg &= ~S3C2412_IISMOD_BCLK_MASK; 498 reg &= ~S3C2412_IISMOD_BCLK_MASK;
472 writel(reg | div, i2s->regs + S3C2412_IISMOD); 499 writel(reg | div, i2s->regs + S3C2412_IISMOD);
@@ -626,7 +653,7 @@ int s3c_i2sv2_probe(struct platform_device *pdev,
626 } 653 }
627 654
628 i2s->iis_pclk = clk_get(dev, "iis"); 655 i2s->iis_pclk = clk_get(dev, "iis");
629 if (i2s->iis_pclk == NULL) { 656 if (IS_ERR(i2s->iis_pclk)) {
630 dev_err(dev, "failed to get iis_clock\n"); 657 dev_err(dev, "failed to get iis_clock\n");
631 iounmap(i2s->regs); 658 iounmap(i2s->regs);
632 return -ENOENT; 659 return -ENOENT;
diff --git a/sound/soc/s3c24xx/s3c-i2s-v2.h b/sound/soc/s3c24xx/s3c-i2s-v2.h
index f66854a77fb2..ecf8eaaed1db 100644
--- a/sound/soc/s3c24xx/s3c-i2s-v2.h
+++ b/sound/soc/s3c24xx/s3c-i2s-v2.h
@@ -49,8 +49,8 @@ struct s3c_i2sv2_info {
49 49
50 unsigned char master; 50 unsigned char master;
51 51
52 struct s3c24xx_pcm_dma_params *dma_playback; 52 struct s3c_dma_params *dma_playback;
53 struct s3c24xx_pcm_dma_params *dma_capture; 53 struct s3c_dma_params *dma_capture;
54 54
55 u32 suspend_iismod; 55 u32 suspend_iismod;
56 u32 suspend_iiscon; 56 u32 suspend_iiscon;
diff --git a/sound/soc/s3c24xx/s3c-pcm.c b/sound/soc/s3c24xx/s3c-pcm.c
new file mode 100644
index 000000000000..9e61a7c2d9ac
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-pcm.c
@@ -0,0 +1,552 @@
1/* sound/soc/s3c24xx/s3c-pcm.c
2 *
3 * ALSA SoC Audio Layer - S3C PCM-Controller driver
4 *
5 * Copyright (c) 2009 Samsung Electronics Co. Ltd
6 * Author: Jaswinder Singh <jassi.brar@samsung.com>
7 * based upon I2S drivers by Ben Dooks.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#include <linux/init.h>
15#include <linux/module.h>
16#include <linux/device.h>
17#include <linux/delay.h>
18#include <linux/clk.h>
19#include <linux/kernel.h>
20#include <linux/gpio.h>
21#include <linux/io.h>
22
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include <plat/audio.h>
30#include <plat/dma.h>
31
32#include "s3c-dma.h"
33#include "s3c-pcm.h"
34
35static struct s3c2410_dma_client s3c_pcm_dma_client_out = {
36 .name = "PCM Stereo out"
37};
38
39static struct s3c2410_dma_client s3c_pcm_dma_client_in = {
40 .name = "PCM Stereo in"
41};
42
43static struct s3c_dma_params s3c_pcm_stereo_out[] = {
44 [0] = {
45 .client = &s3c_pcm_dma_client_out,
46 .dma_size = 4,
47 },
48 [1] = {
49 .client = &s3c_pcm_dma_client_out,
50 .dma_size = 4,
51 },
52};
53
54static struct s3c_dma_params s3c_pcm_stereo_in[] = {
55 [0] = {
56 .client = &s3c_pcm_dma_client_in,
57 .dma_size = 4,
58 },
59 [1] = {
60 .client = &s3c_pcm_dma_client_in,
61 .dma_size = 4,
62 },
63};
64
65static struct s3c_pcm_info s3c_pcm[2];
66
67static inline struct s3c_pcm_info *to_info(struct snd_soc_dai *cpu_dai)
68{
69 return cpu_dai->private_data;
70}
71
72static void s3c_pcm_snd_txctrl(struct s3c_pcm_info *pcm, int on)
73{
74 void __iomem *regs = pcm->regs;
75 u32 ctl, clkctl;
76
77 clkctl = readl(regs + S3C_PCM_CLKCTL);
78 ctl = readl(regs + S3C_PCM_CTL);
79 ctl &= ~(S3C_PCM_CTL_TXDIPSTICK_MASK
80 << S3C_PCM_CTL_TXDIPSTICK_SHIFT);
81
82 if (on) {
83 ctl |= S3C_PCM_CTL_TXDMA_EN;
84 ctl |= S3C_PCM_CTL_TXFIFO_EN;
85 ctl |= S3C_PCM_CTL_ENABLE;
86 ctl |= (0x20<<S3C_PCM_CTL_TXDIPSTICK_SHIFT);
87 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
88 } else {
89 ctl &= ~S3C_PCM_CTL_TXDMA_EN;
90 ctl &= ~S3C_PCM_CTL_TXFIFO_EN;
91
92 if (!(ctl & S3C_PCM_CTL_RXFIFO_EN)) {
93 ctl &= ~S3C_PCM_CTL_ENABLE;
94 if (!pcm->idleclk)
95 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
96 }
97 }
98
99 writel(clkctl, regs + S3C_PCM_CLKCTL);
100 writel(ctl, regs + S3C_PCM_CTL);
101}
102
103static void s3c_pcm_snd_rxctrl(struct s3c_pcm_info *pcm, int on)
104{
105 void __iomem *regs = pcm->regs;
106 u32 ctl, clkctl;
107
108 ctl = readl(regs + S3C_PCM_CTL);
109 clkctl = readl(regs + S3C_PCM_CLKCTL);
110
111 if (on) {
112 ctl |= S3C_PCM_CTL_RXDMA_EN;
113 ctl |= S3C_PCM_CTL_RXFIFO_EN;
114 ctl |= S3C_PCM_CTL_ENABLE;
115 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
116 } else {
117 ctl &= ~S3C_PCM_CTL_RXDMA_EN;
118 ctl &= ~S3C_PCM_CTL_RXFIFO_EN;
119
120 if (!(ctl & S3C_PCM_CTL_TXFIFO_EN)) {
121 ctl &= ~S3C_PCM_CTL_ENABLE;
122 if (!pcm->idleclk)
123 clkctl |= S3C_PCM_CLKCTL_SERCLK_EN;
124 }
125 }
126
127 writel(clkctl, regs + S3C_PCM_CLKCTL);
128 writel(ctl, regs + S3C_PCM_CTL);
129}
130
131static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
132 struct snd_soc_dai *dai)
133{
134 struct snd_soc_pcm_runtime *rtd = substream->private_data;
135 struct s3c_pcm_info *pcm = to_info(rtd->dai->cpu_dai);
136 unsigned long flags;
137
138 dev_dbg(pcm->dev, "Entered %s\n", __func__);
139
140 switch (cmd) {
141 case SNDRV_PCM_TRIGGER_START:
142 case SNDRV_PCM_TRIGGER_RESUME:
143 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
144 spin_lock_irqsave(&pcm->lock, flags);
145
146 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
147 s3c_pcm_snd_rxctrl(pcm, 1);
148 else
149 s3c_pcm_snd_txctrl(pcm, 1);
150
151 spin_unlock_irqrestore(&pcm->lock, flags);
152 break;
153
154 case SNDRV_PCM_TRIGGER_STOP:
155 case SNDRV_PCM_TRIGGER_SUSPEND:
156 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
157 spin_lock_irqsave(&pcm->lock, flags);
158
159 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
160 s3c_pcm_snd_rxctrl(pcm, 0);
161 else
162 s3c_pcm_snd_txctrl(pcm, 0);
163
164 spin_unlock_irqrestore(&pcm->lock, flags);
165 break;
166
167 default:
168 return -EINVAL;
169 }
170
171 return 0;
172}
173
174static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
175 struct snd_pcm_hw_params *params,
176 struct snd_soc_dai *socdai)
177{
178 struct snd_soc_pcm_runtime *rtd = substream->private_data;
179 struct snd_soc_dai_link *dai = rtd->dai;
180 struct s3c_pcm_info *pcm = to_info(dai->cpu_dai);
181 void __iomem *regs = pcm->regs;
182 struct clk *clk;
183 int sclk_div, sync_div;
184 unsigned long flags;
185 u32 clkctl;
186
187 dev_dbg(pcm->dev, "Entered %s\n", __func__);
188
189 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
190 dai->cpu_dai->dma_data = pcm->dma_playback;
191 else
192 dai->cpu_dai->dma_data = pcm->dma_capture;
193
194 /* Strictly check for sample size */
195 switch (params_format(params)) {
196 case SNDRV_PCM_FORMAT_S16_LE:
197 break;
198 default:
199 return -EINVAL;
200 }
201
202 spin_lock_irqsave(&pcm->lock, flags);
203
204 /* Get hold of the PCMSOURCE_CLK */
205 clkctl = readl(regs + S3C_PCM_CLKCTL);
206 if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK)
207 clk = pcm->pclk;
208 else
209 clk = pcm->cclk;
210
211 /* Set the SCLK divider */
212 sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs /
213 params_rate(params) / 2 - 1;
214
215 clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK
216 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
217 clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK)
218 << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
219
220 /* Set the SYNC divider */
221 sync_div = pcm->sclk_per_fs - 1;
222
223 clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK
224 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
225 clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK)
226 << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
227
228 writel(clkctl, regs + S3C_PCM_CLKCTL);
229
230 spin_unlock_irqrestore(&pcm->lock, flags);
231
232 dev_dbg(pcm->dev, "PCMSOURCE_CLK-%lu SCLK=%ufs \
233 SCLK_DIV=%d SYNC_DIV=%d\n",
234 clk_get_rate(clk), pcm->sclk_per_fs,
235 sclk_div, sync_div);
236
237 return 0;
238}
239
240static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
241 unsigned int fmt)
242{
243 struct s3c_pcm_info *pcm = to_info(cpu_dai);
244 void __iomem *regs = pcm->regs;
245 unsigned long flags;
246 int ret = 0;
247 u32 ctl;
248
249 dev_dbg(pcm->dev, "Entered %s\n", __func__);
250
251 spin_lock_irqsave(&pcm->lock, flags);
252
253 ctl = readl(regs + S3C_PCM_CTL);
254
255 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
256 case SND_SOC_DAIFMT_NB_NF:
257 /* Nothing to do, NB_NF by default */
258 break;
259 default:
260 dev_err(pcm->dev, "Unsupported clock inversion!\n");
261 ret = -EINVAL;
262 goto exit;
263 }
264
265 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
266 case SND_SOC_DAIFMT_CBS_CFS:
267 /* Nothing to do, Master by default */
268 break;
269 default:
270 dev_err(pcm->dev, "Unsupported master/slave format!\n");
271 ret = -EINVAL;
272 goto exit;
273 }
274
275 switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
276 case SND_SOC_DAIFMT_CONT:
277 pcm->idleclk = 1;
278 break;
279 case SND_SOC_DAIFMT_GATED:
280 pcm->idleclk = 0;
281 break;
282 default:
283 dev_err(pcm->dev, "Invalid Clock gating request!\n");
284 ret = -EINVAL;
285 goto exit;
286 }
287
288 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
289 case SND_SOC_DAIFMT_DSP_A:
290 ctl |= S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
291 ctl |= S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
292 break;
293 case SND_SOC_DAIFMT_DSP_B:
294 ctl &= ~S3C_PCM_CTL_TXMSB_AFTER_FSYNC;
295 ctl &= ~S3C_PCM_CTL_RXMSB_AFTER_FSYNC;
296 break;
297 default:
298 dev_err(pcm->dev, "Unsupported data format!\n");
299 ret = -EINVAL;
300 goto exit;
301 }
302
303 writel(ctl, regs + S3C_PCM_CTL);
304
305exit:
306 spin_unlock_irqrestore(&pcm->lock, flags);
307
308 return ret;
309}
310
311static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
312 int div_id, int div)
313{
314 struct s3c_pcm_info *pcm = to_info(cpu_dai);
315
316 switch (div_id) {
317 case S3C_PCM_SCLK_PER_FS:
318 pcm->sclk_per_fs = div;
319 break;
320
321 default:
322 return -EINVAL;
323 }
324
325 return 0;
326}
327
328static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
329 int clk_id, unsigned int freq, int dir)
330{
331 struct s3c_pcm_info *pcm = to_info(cpu_dai);
332 void __iomem *regs = pcm->regs;
333 u32 clkctl = readl(regs + S3C_PCM_CLKCTL);
334
335 switch (clk_id) {
336 case S3C_PCM_CLKSRC_PCLK:
337 clkctl |= S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
338 break;
339
340 case S3C_PCM_CLKSRC_MUX:
341 clkctl &= ~S3C_PCM_CLKCTL_SERCLKSEL_PCLK;
342
343 if (clk_get_rate(pcm->cclk) != freq)
344 clk_set_rate(pcm->cclk, freq);
345
346 break;
347
348 default:
349 return -EINVAL;
350 }
351
352 writel(clkctl, regs + S3C_PCM_CLKCTL);
353
354 return 0;
355}
356
357static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
358 .set_sysclk = s3c_pcm_set_sysclk,
359 .set_clkdiv = s3c_pcm_set_clkdiv,
360 .trigger = s3c_pcm_trigger,
361 .hw_params = s3c_pcm_hw_params,
362 .set_fmt = s3c_pcm_set_fmt,
363};
364
365#define S3C_PCM_RATES SNDRV_PCM_RATE_8000_96000
366
367#define S3C_PCM_DECLARE(n) \
368{ \
369 .name = "samsung-pcm", \
370 .id = (n), \
371 .symmetric_rates = 1, \
372 .ops = &s3c_pcm_dai_ops, \
373 .playback = { \
374 .channels_min = 2, \
375 .channels_max = 2, \
376 .rates = S3C_PCM_RATES, \
377 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
378 }, \
379 .capture = { \
380 .channels_min = 2, \
381 .channels_max = 2, \
382 .rates = S3C_PCM_RATES, \
383 .formats = SNDRV_PCM_FMTBIT_S16_LE, \
384 }, \
385}
386
387struct snd_soc_dai s3c_pcm_dai[] = {
388 S3C_PCM_DECLARE(0),
389 S3C_PCM_DECLARE(1),
390};
391EXPORT_SYMBOL_GPL(s3c_pcm_dai);
392
393static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
394{
395 struct s3c_pcm_info *pcm;
396 struct snd_soc_dai *dai;
397 struct resource *mem_res, *dmatx_res, *dmarx_res;
398 struct s3c_audio_pdata *pcm_pdata;
399 int ret;
400
401 /* Check for valid device index */
402 if ((pdev->id < 0) || pdev->id >= ARRAY_SIZE(s3c_pcm)) {
403 dev_err(&pdev->dev, "id %d out of range\n", pdev->id);
404 return -EINVAL;
405 }
406
407 pcm_pdata = pdev->dev.platform_data;
408
409 /* Check for availability of necessary resource */
410 dmatx_res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
411 if (!dmatx_res) {
412 dev_err(&pdev->dev, "Unable to get PCM-TX dma resource\n");
413 return -ENXIO;
414 }
415
416 dmarx_res = platform_get_resource(pdev, IORESOURCE_DMA, 1);
417 if (!dmarx_res) {
418 dev_err(&pdev->dev, "Unable to get PCM-RX dma resource\n");
419 return -ENXIO;
420 }
421
422 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
423 if (!mem_res) {
424 dev_err(&pdev->dev, "Unable to get register resource\n");
425 return -ENXIO;
426 }
427
428 if (pcm_pdata && pcm_pdata->cfg_gpio && pcm_pdata->cfg_gpio(pdev)) {
429 dev_err(&pdev->dev, "Unable to configure gpio\n");
430 return -EINVAL;
431 }
432
433 pcm = &s3c_pcm[pdev->id];
434 pcm->dev = &pdev->dev;
435
436 spin_lock_init(&pcm->lock);
437
438 dai = &s3c_pcm_dai[pdev->id];
439 dai->dev = &pdev->dev;
440
441 /* Default is 128fs */
442 pcm->sclk_per_fs = 128;
443
444 pcm->cclk = clk_get(&pdev->dev, "audio-bus");
445 if (IS_ERR(pcm->cclk)) {
446 dev_err(&pdev->dev, "failed to get audio-bus\n");
447 ret = PTR_ERR(pcm->cclk);
448 goto err1;
449 }
450 clk_enable(pcm->cclk);
451
452 /* record our pcm structure for later use in the callbacks */
453 dai->private_data = pcm;
454
455 if (!request_mem_region(mem_res->start,
456 resource_size(mem_res), "samsung-pcm")) {
457 dev_err(&pdev->dev, "Unable to request register region\n");
458 ret = -EBUSY;
459 goto err2;
460 }
461
462 pcm->regs = ioremap(mem_res->start, 0x100);
463 if (pcm->regs == NULL) {
464 dev_err(&pdev->dev, "cannot ioremap registers\n");
465 ret = -ENXIO;
466 goto err3;
467 }
468
469 pcm->pclk = clk_get(&pdev->dev, "pcm");
470 if (IS_ERR(pcm->pclk)) {
471 dev_err(&pdev->dev, "failed to get pcm_clock\n");
472 ret = -ENOENT;
473 goto err4;
474 }
475 clk_enable(pcm->pclk);
476
477 ret = snd_soc_register_dai(dai);
478 if (ret != 0) {
479 dev_err(&pdev->dev, "failed to get pcm_clock\n");
480 goto err5;
481 }
482
483 s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
484 + S3C_PCM_RXFIFO;
485 s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
486 + S3C_PCM_TXFIFO;
487
488 s3c_pcm_stereo_in[pdev->id].channel = dmarx_res->start;
489 s3c_pcm_stereo_out[pdev->id].channel = dmatx_res->start;
490
491 pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
492 pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
493
494 return 0;
495
496err5:
497 clk_disable(pcm->pclk);
498 clk_put(pcm->pclk);
499err4:
500 iounmap(pcm->regs);
501err3:
502 release_mem_region(mem_res->start, resource_size(mem_res));
503err2:
504 clk_disable(pcm->cclk);
505 clk_put(pcm->cclk);
506err1:
507 return ret;
508}
509
510static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
511{
512 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
513 struct resource *mem_res;
514
515 iounmap(pcm->regs);
516
517 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
518 release_mem_region(mem_res->start, resource_size(mem_res));
519
520 clk_disable(pcm->cclk);
521 clk_disable(pcm->pclk);
522 clk_put(pcm->pclk);
523 clk_put(pcm->cclk);
524
525 return 0;
526}
527
528static struct platform_driver s3c_pcm_driver = {
529 .probe = s3c_pcm_dev_probe,
530 .remove = s3c_pcm_dev_remove,
531 .driver = {
532 .name = "samsung-pcm",
533 .owner = THIS_MODULE,
534 },
535};
536
537static int __init s3c_pcm_init(void)
538{
539 return platform_driver_register(&s3c_pcm_driver);
540}
541module_init(s3c_pcm_init);
542
543static void __exit s3c_pcm_exit(void)
544{
545 platform_driver_unregister(&s3c_pcm_driver);
546}
547module_exit(s3c_pcm_exit);
548
549/* Module information */
550MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
551MODULE_DESCRIPTION("S3C PCM Controller Driver");
552MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c-pcm.h b/sound/soc/s3c24xx/s3c-pcm.h
new file mode 100644
index 000000000000..69ff9971692f
--- /dev/null
+++ b/sound/soc/s3c24xx/s3c-pcm.h
@@ -0,0 +1,123 @@
1/* sound/soc/s3c24xx/s3c-pcm.h
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 *
7 */
8
9#ifndef __S3C_PCM_H
10#define __S3C_PCM_H __FILE__
11
12/*Register Offsets */
13#define S3C_PCM_CTL (0x00)
14#define S3C_PCM_CLKCTL (0x04)
15#define S3C_PCM_TXFIFO (0x08)
16#define S3C_PCM_RXFIFO (0x0C)
17#define S3C_PCM_IRQCTL (0x10)
18#define S3C_PCM_IRQSTAT (0x14)
19#define S3C_PCM_FIFOSTAT (0x18)
20#define S3C_PCM_CLRINT (0x20)
21
22/* PCM_CTL Bit-Fields */
23#define S3C_PCM_CTL_TXDIPSTICK_MASK (0x3f)
24#define S3C_PCM_CTL_TXDIPSTICK_SHIFT (13)
25#define S3C_PCM_CTL_RXDIPSTICK_MSK (0x3f<<7)
26#define S3C_PCM_CTL_TXDMA_EN (0x1<<6)
27#define S3C_PCM_CTL_RXDMA_EN (0x1<<5)
28#define S3C_PCM_CTL_TXMSB_AFTER_FSYNC (0x1<<4)
29#define S3C_PCM_CTL_RXMSB_AFTER_FSYNC (0x1<<3)
30#define S3C_PCM_CTL_TXFIFO_EN (0x1<<2)
31#define S3C_PCM_CTL_RXFIFO_EN (0x1<<1)
32#define S3C_PCM_CTL_ENABLE (0x1<<0)
33
34/* PCM_CLKCTL Bit-Fields */
35#define S3C_PCM_CLKCTL_SERCLK_EN (0x1<<19)
36#define S3C_PCM_CLKCTL_SERCLKSEL_PCLK (0x1<<18)
37#define S3C_PCM_CLKCTL_SCLKDIV_MASK (0x1ff)
38#define S3C_PCM_CLKCTL_SYNCDIV_MASK (0x1ff)
39#define S3C_PCM_CLKCTL_SCLKDIV_SHIFT (9)
40#define S3C_PCM_CLKCTL_SYNCDIV_SHIFT (0)
41
42/* PCM_TXFIFO Bit-Fields */
43#define S3C_PCM_TXFIFO_DVALID (0x1<<16)
44#define S3C_PCM_TXFIFO_DATA_MSK (0xffff<<0)
45
46/* PCM_RXFIFO Bit-Fields */
47#define S3C_PCM_RXFIFO_DVALID (0x1<<16)
48#define S3C_PCM_RXFIFO_DATA_MSK (0xffff<<0)
49
50/* PCM_IRQCTL Bit-Fields */
51#define S3C_PCM_IRQCTL_IRQEN (0x1<<14)
52#define S3C_PCM_IRQCTL_WRDEN (0x1<<12)
53#define S3C_PCM_IRQCTL_TXEMPTYEN (0x1<<11)
54#define S3C_PCM_IRQCTL_TXALMSTEMPTYEN (0x1<<10)
55#define S3C_PCM_IRQCTL_TXFULLEN (0x1<<9)
56#define S3C_PCM_IRQCTL_TXALMSTFULLEN (0x1<<8)
57#define S3C_PCM_IRQCTL_TXSTARVEN (0x1<<7)
58#define S3C_PCM_IRQCTL_TXERROVRFLEN (0x1<<6)
59#define S3C_PCM_IRQCTL_RXEMPTEN (0x1<<5)
60#define S3C_PCM_IRQCTL_RXALMSTEMPTEN (0x1<<4)
61#define S3C_PCM_IRQCTL_RXFULLEN (0x1<<3)
62#define S3C_PCM_IRQCTL_RXALMSTFULLEN (0x1<<2)
63#define S3C_PCM_IRQCTL_RXSTARVEN (0x1<<1)
64#define S3C_PCM_IRQCTL_RXERROVRFLEN (0x1<<0)
65
66/* PCM_IRQSTAT Bit-Fields */
67#define S3C_PCM_IRQSTAT_IRQPND (0x1<<13)
68#define S3C_PCM_IRQSTAT_WRD_XFER (0x1<<12)
69#define S3C_PCM_IRQSTAT_TXEMPTY (0x1<<11)
70#define S3C_PCM_IRQSTAT_TXALMSTEMPTY (0x1<<10)
71#define S3C_PCM_IRQSTAT_TXFULL (0x1<<9)
72#define S3C_PCM_IRQSTAT_TXALMSTFULL (0x1<<8)
73#define S3C_PCM_IRQSTAT_TXSTARV (0x1<<7)
74#define S3C_PCM_IRQSTAT_TXERROVRFL (0x1<<6)
75#define S3C_PCM_IRQSTAT_RXEMPT (0x1<<5)
76#define S3C_PCM_IRQSTAT_RXALMSTEMPT (0x1<<4)
77#define S3C_PCM_IRQSTAT_RXFULL (0x1<<3)
78#define S3C_PCM_IRQSTAT_RXALMSTFULL (0x1<<2)
79#define S3C_PCM_IRQSTAT_RXSTARV (0x1<<1)
80#define S3C_PCM_IRQSTAT_RXERROVRFL (0x1<<0)
81
82/* PCM_FIFOSTAT Bit-Fields */
83#define S3C_PCM_FIFOSTAT_TXCNT_MSK (0x3f<<14)
84#define S3C_PCM_FIFOSTAT_TXFIFOEMPTY (0x1<<13)
85#define S3C_PCM_FIFOSTAT_TXFIFOALMSTEMPTY (0x1<<12)
86#define S3C_PCM_FIFOSTAT_TXFIFOFULL (0x1<<11)
87#define S3C_PCM_FIFOSTAT_TXFIFOALMSTFULL (0x1<<10)
88#define S3C_PCM_FIFOSTAT_RXCNT_MSK (0x3f<<4)
89#define S3C_PCM_FIFOSTAT_RXFIFOEMPTY (0x1<<3)
90#define S3C_PCM_FIFOSTAT_RXFIFOALMSTEMPTY (0x1<<2)
91#define S3C_PCM_FIFOSTAT_RXFIFOFULL (0x1<<1)
92#define S3C_PCM_FIFOSTAT_RXFIFOALMSTFULL (0x1<<0)
93
94#define S3C_PCM_CLKSRC_PCLK 0
95#define S3C_PCM_CLKSRC_MUX 1
96
97#define S3C_PCM_SCLK_PER_FS 0
98
99/**
100 * struct s3c_pcm_info - S3C PCM Controller information
101 * @dev: The parent device passed to use from the probe.
102 * @regs: The pointer to the device register block.
103 * @dma_playback: DMA information for playback channel.
104 * @dma_capture: DMA information for capture channel.
105 */
106struct s3c_pcm_info {
107 spinlock_t lock;
108 struct device *dev;
109 void __iomem *regs;
110
111 unsigned int sclk_per_fs;
112
113 /* Whether to keep PCMSCLK enabled even when idle(no active xfer) */
114 unsigned int idleclk;
115
116 struct clk *pclk;
117 struct clk *cclk;
118
119 struct s3c_dma_params *dma_playback;
120 struct s3c_dma_params *dma_capture;
121};
122
123#endif /* __S3C_PCM_H */
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index a587ec40b449..359e59346ba2 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -34,11 +34,10 @@
34 34
35#include <plat/regs-s3c2412-iis.h> 35#include <plat/regs-s3c2412-iis.h>
36 36
37#include <plat/audio.h>
38#include <mach/regs-gpio.h> 37#include <mach/regs-gpio.h>
39#include <mach/dma.h> 38#include <mach/dma.h>
40 39
41#include "s3c24xx-pcm.h" 40#include "s3c-dma.h"
42#include "s3c2412-i2s.h" 41#include "s3c2412-i2s.h"
43 42
44#define S3C2412_I2S_DEBUG 0 43#define S3C2412_I2S_DEBUG 0
@@ -51,14 +50,14 @@ static struct s3c2410_dma_client s3c2412_dma_client_in = {
51 .name = "I2S PCM Stereo in" 50 .name = "I2S PCM Stereo in"
52}; 51};
53 52
54static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_out = { 53static struct s3c_dma_params s3c2412_i2s_pcm_stereo_out = {
55 .client = &s3c2412_dma_client_out, 54 .client = &s3c2412_dma_client_out,
56 .channel = DMACH_I2S_OUT, 55 .channel = DMACH_I2S_OUT,
57 .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD, 56 .dma_addr = S3C2410_PA_IIS + S3C2412_IISTXD,
58 .dma_size = 4, 57 .dma_size = 4,
59}; 58};
60 59
61static struct s3c24xx_pcm_dma_params s3c2412_i2s_pcm_stereo_in = { 60static struct s3c_dma_params s3c2412_i2s_pcm_stereo_in = {
62 .client = &s3c2412_dma_client_in, 61 .client = &s3c2412_dma_client_in,
63 .channel = DMACH_I2S_IN, 62 .channel = DMACH_I2S_IN,
64 .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD, 63 .dma_addr = S3C2410_PA_IIS + S3C2412_IISRXD,
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index fc1beb0930b9..0191e3acb0b4 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -32,11 +32,10 @@
32#include <plat/regs-ac97.h> 32#include <plat/regs-ac97.h>
33#include <mach/regs-gpio.h> 33#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h> 34#include <mach/regs-clock.h>
35#include <plat/audio.h>
36#include <asm/dma.h> 35#include <asm/dma.h>
37#include <mach/dma.h> 36#include <mach/dma.h>
38 37
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40#include "s3c24xx-ac97.h" 39#include "s3c24xx-ac97.h"
41 40
42struct s3c24xx_ac97_info { 41struct s3c24xx_ac97_info {
@@ -189,21 +188,21 @@ static struct s3c2410_dma_client s3c2443_dma_client_micin = {
189 .name = "AC97 Mic Mono in" 188 .name = "AC97 Mic Mono in"
190}; 189};
191 190
192static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_out = { 191static struct s3c_dma_params s3c2443_ac97_pcm_stereo_out = {
193 .client = &s3c2443_dma_client_out, 192 .client = &s3c2443_dma_client_out,
194 .channel = DMACH_PCM_OUT, 193 .channel = DMACH_PCM_OUT,
195 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 194 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
196 .dma_size = 4, 195 .dma_size = 4,
197}; 196};
198 197
199static struct s3c24xx_pcm_dma_params s3c2443_ac97_pcm_stereo_in = { 198static struct s3c_dma_params s3c2443_ac97_pcm_stereo_in = {
200 .client = &s3c2443_dma_client_in, 199 .client = &s3c2443_dma_client_in,
201 .channel = DMACH_PCM_IN, 200 .channel = DMACH_PCM_IN,
202 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA, 201 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_PCM_DATA,
203 .dma_size = 4, 202 .dma_size = 4,
204}; 203};
205 204
206static struct s3c24xx_pcm_dma_params s3c2443_ac97_mic_mono_in = { 205static struct s3c_dma_params s3c2443_ac97_mic_mono_in = {
207 .client = &s3c2443_dma_client_micin, 206 .client = &s3c2443_dma_client_micin,
208 .channel = DMACH_MIC_IN, 207 .channel = DMACH_MIC_IN,
209 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA, 208 .dma_addr = S3C2440_PA_AC97 + S3C_AC97_MIC_DATA,
@@ -291,7 +290,7 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
291{ 290{
292 u32 ac_glbctrl; 291 u32 ac_glbctrl;
293 struct snd_soc_pcm_runtime *rtd = substream->private_data; 292 struct snd_soc_pcm_runtime *rtd = substream->private_data;
294 int channel = ((struct s3c24xx_pcm_dma_params *) 293 int channel = ((struct s3c_dma_params *)
295 rtd->dai->cpu_dai->dma_data)->channel; 294 rtd->dai->cpu_dai->dma_data)->channel;
296 295
297 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 296 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
@@ -340,7 +339,7 @@ static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
340{ 339{
341 u32 ac_glbctrl; 340 u32 ac_glbctrl;
342 struct snd_soc_pcm_runtime *rtd = substream->private_data; 341 struct snd_soc_pcm_runtime *rtd = substream->private_data;
343 int channel = ((struct s3c24xx_pcm_dma_params *) 342 int channel = ((struct s3c_dma_params *)
344 rtd->dai->cpu_dai->dma_data)->channel; 343 rtd->dai->cpu_dai->dma_data)->channel;
345 344
346 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL); 345 ac_glbctrl = readl(s3c24xx_ac97.regs + S3C_AC97_GLBCTRL);
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 40e2c4790f0d..0bc5950b9f02 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -32,13 +32,13 @@
32#include <mach/hardware.h> 32#include <mach/hardware.h>
33#include <mach/regs-gpio.h> 33#include <mach/regs-gpio.h>
34#include <mach/regs-clock.h> 34#include <mach/regs-clock.h>
35#include <plat/audio.h> 35
36#include <asm/dma.h> 36#include <asm/dma.h>
37#include <mach/dma.h> 37#include <mach/dma.h>
38 38
39#include <plat/regs-iis.h> 39#include <plat/regs-iis.h>
40 40
41#include "s3c24xx-pcm.h" 41#include "s3c-dma.h"
42#include "s3c24xx-i2s.h" 42#include "s3c24xx-i2s.h"
43 43
44static struct s3c2410_dma_client s3c24xx_dma_client_out = { 44static struct s3c2410_dma_client s3c24xx_dma_client_out = {
@@ -49,14 +49,14 @@ static struct s3c2410_dma_client s3c24xx_dma_client_in = {
49 .name = "I2S PCM Stereo in" 49 .name = "I2S PCM Stereo in"
50}; 50};
51 51
52static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_out = { 52static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_out = {
53 .client = &s3c24xx_dma_client_out, 53 .client = &s3c24xx_dma_client_out,
54 .channel = DMACH_I2S_OUT, 54 .channel = DMACH_I2S_OUT,
55 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, 55 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
56 .dma_size = 2, 56 .dma_size = 2,
57}; 57};
58 58
59static struct s3c24xx_pcm_dma_params s3c24xx_i2s_pcm_stereo_in = { 59static struct s3c_dma_params s3c24xx_i2s_pcm_stereo_in = {
60 .client = &s3c24xx_dma_client_in, 60 .client = &s3c24xx_dma_client_in,
61 .channel = DMACH_I2S_IN, 61 .channel = DMACH_I2S_IN,
62 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO, 62 .dma_addr = S3C2410_PA_IIS + S3C2410_IISFIFO,
@@ -258,12 +258,12 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
258 switch (params_format(params)) { 258 switch (params_format(params)) {
259 case SNDRV_PCM_FORMAT_S8: 259 case SNDRV_PCM_FORMAT_S8:
260 iismod &= ~S3C2410_IISMOD_16BIT; 260 iismod &= ~S3C2410_IISMOD_16BIT;
261 ((struct s3c24xx_pcm_dma_params *) 261 ((struct s3c_dma_params *)
262 rtd->dai->cpu_dai->dma_data)->dma_size = 1; 262 rtd->dai->cpu_dai->dma_data)->dma_size = 1;
263 break; 263 break;
264 case SNDRV_PCM_FORMAT_S16_LE: 264 case SNDRV_PCM_FORMAT_S16_LE:
265 iismod |= S3C2410_IISMOD_16BIT; 265 iismod |= S3C2410_IISMOD_16BIT;
266 ((struct s3c24xx_pcm_dma_params *) 266 ((struct s3c_dma_params *)
267 rtd->dai->cpu_dai->dma_data)->dma_size = 2; 267 rtd->dai->cpu_dai->dma_data)->dma_size = 2;
268 break; 268 break;
269 default: 269 default:
@@ -280,7 +280,7 @@ static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
280{ 280{
281 int ret = 0; 281 int ret = 0;
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 282 struct snd_soc_pcm_runtime *rtd = substream->private_data;
283 int channel = ((struct s3c24xx_pcm_dma_params *) 283 int channel = ((struct s3c_dma_params *)
284 rtd->dai->cpu_dai->dma_data)->channel; 284 rtd->dai->cpu_dai->dma_data)->channel;
285 285
286 pr_debug("Entered %s\n", __func__); 286 pr_debug("Entered %s\n", __func__);
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec.c b/sound/soc/s3c24xx/s3c24xx_simtec.c
index 1966e0d5652d..507b2ed5d58b 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec.c
@@ -21,7 +21,7 @@
21 21
22#include <plat/audio-simtec.h> 22#include <plat/audio-simtec.h>
23 23
24#include "s3c24xx-pcm.h" 24#include "s3c-dma.h"
25#include "s3c24xx-i2s.h" 25#include "s3c24xx-i2s.h"
26#include "s3c24xx_simtec.h" 26#include "s3c24xx_simtec.h"
27 27
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
index 8346bd96eaf5..bdf8951af8e3 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_hermes.c
@@ -18,7 +18,7 @@
18 18
19#include <plat/audio-simtec.h> 19#include <plat/audio-simtec.h>
20 20
21#include "s3c24xx-pcm.h" 21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h" 22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h" 23#include "s3c24xx_simtec.h"
24 24
diff --git a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
index 25797e096175..185c0acb5ce6 100644
--- a/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/s3c24xx/s3c24xx_simtec_tlv320aic23.c
@@ -18,7 +18,7 @@
18 18
19#include <plat/audio-simtec.h> 19#include <plat/audio-simtec.h>
20 20
21#include "s3c24xx-pcm.h" 21#include "s3c-dma.h"
22#include "s3c24xx-i2s.h" 22#include "s3c24xx-i2s.h"
23#include "s3c24xx_simtec.h" 23#include "s3c24xx_simtec.h"
24 24
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
index c215d32d6322..052d59659c29 100644
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ b/sound/soc/s3c24xx/s3c24xx_uda134x.c
@@ -24,7 +24,7 @@
24 24
25#include <plat/regs-iis.h> 25#include <plat/regs-iis.h>
26 26
27#include "s3c24xx-pcm.h" 27#include "s3c-dma.h"
28#include "s3c24xx-i2s.h" 28#include "s3c24xx-i2s.h"
29#include "../codecs/uda134x.h" 29#include "../codecs/uda134x.h"
30 30
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.c b/sound/soc/s3c24xx/s3c64xx-i2s.c
index 3c06c401d0fb..cc7edb5f792d 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.c
@@ -31,12 +31,11 @@
31#include <plat/gpio-bank-d.h> 31#include <plat/gpio-bank-d.h>
32#include <plat/gpio-bank-e.h> 32#include <plat/gpio-bank-e.h>
33#include <plat/gpio-cfg.h> 33#include <plat/gpio-cfg.h>
34#include <plat/audio.h>
35 34
36#include <mach/map.h> 35#include <mach/map.h>
37#include <mach/dma.h> 36#include <mach/dma.h>
38 37
39#include "s3c24xx-pcm.h" 38#include "s3c-dma.h"
40#include "s3c64xx-i2s.h" 39#include "s3c64xx-i2s.h"
41 40
42static struct s3c2410_dma_client s3c64xx_dma_client_out = { 41static struct s3c2410_dma_client s3c64xx_dma_client_out = {
@@ -47,7 +46,7 @@ static struct s3c2410_dma_client s3c64xx_dma_client_in = {
47 .name = "I2S PCM Stereo in" 46 .name = "I2S PCM Stereo in"
48}; 47};
49 48
50static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = { 49static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
51 [0] = { 50 [0] = {
52 .channel = DMACH_I2S0_OUT, 51 .channel = DMACH_I2S0_OUT,
53 .client = &s3c64xx_dma_client_out, 52 .client = &s3c64xx_dma_client_out,
@@ -62,7 +61,7 @@ static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
62 }, 61 },
63}; 62};
64 63
65static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = { 64static struct s3c_dma_params s3c64xx_i2s_pcm_stereo_in[2] = {
66 [0] = { 65 [0] = {
67 .channel = DMACH_I2S0_IN, 66 .channel = DMACH_I2S0_IN,
68 .client = &s3c64xx_dma_client_in, 67 .client = &s3c64xx_dma_client_in,
@@ -99,6 +98,19 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
99 iismod |= S3C64XX_IISMOD_IMS_SYSMUX; 98 iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
100 break; 99 break;
101 100
101 case S3C64XX_CLKSRC_CDCLK:
102 switch (dir) {
103 case SND_SOC_CLOCK_IN:
104 iismod |= S3C64XX_IISMOD_CDCLKCON;
105 break;
106 case SND_SOC_CLOCK_OUT:
107 iismod &= ~S3C64XX_IISMOD_CDCLKCON;
108 break;
109 default:
110 return -EINVAL;
111 }
112 break;
113
102 default: 114 default:
103 return -EINVAL; 115 return -EINVAL;
104 } 116 }
@@ -111,8 +123,12 @@ static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
111struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai) 123struct clk *s3c64xx_i2s_get_clock(struct snd_soc_dai *dai)
112{ 124{
113 struct s3c_i2sv2_info *i2s = to_info(dai); 125 struct s3c_i2sv2_info *i2s = to_info(dai);
126 u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
114 127
115 return i2s->iis_cclk; 128 if (iismod & S3C64XX_IISMOD_IMS_SYSMUX)
129 return i2s->iis_cclk;
130 else
131 return i2s->iis_pclk;
116} 132}
117EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock); 133EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clock);
118 134
@@ -220,6 +236,8 @@ static __devinit int s3c64xx_iis_dev_probe(struct platform_device *pdev)
220 goto err; 236 goto err;
221 } 237 }
222 238
239 clk_enable(i2s->iis_cclk);
240
223 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0); 241 ret = s3c_i2sv2_probe(pdev, dai, i2s, 0);
224 if (ret) 242 if (ret)
225 goto err_clk; 243 goto err_clk;
diff --git a/sound/soc/s3c24xx/s3c64xx-i2s.h b/sound/soc/s3c24xx/s3c64xx-i2s.h
index 02148cee2613..abe7253b55fc 100644
--- a/sound/soc/s3c24xx/s3c64xx-i2s.h
+++ b/sound/soc/s3c24xx/s3c64xx-i2s.h
@@ -25,6 +25,7 @@ struct clk;
25 25
26#define S3C64XX_CLKSRC_PCLK (0) 26#define S3C64XX_CLKSRC_PCLK (0)
27#define S3C64XX_CLKSRC_MUX (1) 27#define S3C64XX_CLKSRC_MUX (1)
28#define S3C64XX_CLKSRC_CDCLK (2)
28 29
29extern struct snd_soc_dai s3c64xx_i2s_dai[]; 30extern struct snd_soc_dai s3c64xx_i2s_dai[];
30 31
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index a2a4f5323c17..12b783b12fcb 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -20,7 +20,7 @@
20#include <sound/soc-dapm.h> 20#include <sound/soc-dapm.h>
21 21
22#include "../codecs/ac97.h" 22#include "../codecs/ac97.h"
23#include "s3c24xx-pcm.h" 23#include "s3c-dma.h"
24#include "s3c24xx-ac97.h" 24#include "s3c24xx-ac97.h"
25 25
26static struct snd_soc_card smdk2443; 26static struct snd_soc_card smdk2443;
diff --git a/sound/soc/s3c24xx/smdk64xx_wm8580.c b/sound/soc/s3c24xx/smdk64xx_wm8580.c
new file mode 100644
index 000000000000..efe4901213a3
--- /dev/null
+++ b/sound/soc/s3c24xx/smdk64xx_wm8580.c
@@ -0,0 +1,268 @@
1/*
2 * smdk64xx_wm8580.c
3 *
4 * Copyright (c) 2009 Samsung Electronics Co. Ltd
5 * Author: Jaswinder Singh <jassi.brar@samsung.com>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
11 */
12
13#include <linux/platform_device.h>
14#include <linux/clk.h>
15#include <sound/core.h>
16#include <sound/pcm.h>
17#include <sound/pcm_params.h>
18#include <sound/soc.h>
19#include <sound/soc-dapm.h>
20
21#include "../codecs/wm8580.h"
22#include "s3c-dma.h"
23#include "s3c64xx-i2s.h"
24
25#define S3C64XX_I2S_V4 2
26
27/* SMDK64XX has a 12MHZ crystal attached to WM8580 */
28#define SMDK64XX_WM8580_FREQ 12000000
29
30static int smdk64xx_hw_params(struct snd_pcm_substream *substream,
31 struct snd_pcm_hw_params *params)
32{
33 struct snd_soc_pcm_runtime *rtd = substream->private_data;
34 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
35 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
36 unsigned int pll_out;
37 int bfs, rfs, ret;
38
39 switch (params_format(params)) {
40 case SNDRV_PCM_FORMAT_U8:
41 case SNDRV_PCM_FORMAT_S8:
42 bfs = 16;
43 break;
44 case SNDRV_PCM_FORMAT_U16_LE:
45 case SNDRV_PCM_FORMAT_S16_LE:
46 bfs = 32;
47 break;
48 default:
49 return -EINVAL;
50 }
51
52 /* The Fvco for WM8580 PLLs must fall within [90,100]MHz.
53 * This criterion can't be met if we request PLL output
54 * as {8000x256, 64000x256, 11025x256}Hz.
55 * As a wayout, we rather change rfs to a minimum value that
56 * results in (params_rate(params) * rfs), and itself, acceptable
57 * to both - the CODEC and the CPU.
58 */
59 switch (params_rate(params)) {
60 case 16000:
61 case 22050:
62 case 32000:
63 case 44100:
64 case 48000:
65 case 88200:
66 case 96000:
67 rfs = 256;
68 break;
69 case 64000:
70 rfs = 384;
71 break;
72 case 8000:
73 case 11025:
74 rfs = 512;
75 break;
76 default:
77 return -EINVAL;
78 }
79 pll_out = params_rate(params) * rfs;
80
81 /* Set the Codec DAI configuration */
82 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
83 | SND_SOC_DAIFMT_NB_NF
84 | SND_SOC_DAIFMT_CBM_CFM);
85 if (ret < 0)
86 return ret;
87
88 /* Set the AP DAI configuration */
89 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
90 | SND_SOC_DAIFMT_NB_NF
91 | SND_SOC_DAIFMT_CBM_CFM);
92 if (ret < 0)
93 return ret;
94
95 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_CDCLK,
96 0, SND_SOC_CLOCK_IN);
97 if (ret < 0)
98 return ret;
99
100 /* We use PCLK for basic ops in SoC-Slave mode */
101 ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_PCLK,
102 0, SND_SOC_CLOCK_IN);
103 if (ret < 0)
104 return ret;
105
106 /* Set WM8580 to drive MCLK from its PLLA */
107 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_MCLK,
108 WM8580_CLKSRC_PLLA);
109 if (ret < 0)
110 return ret;
111
112 /* Explicitly set WM8580-DAC to source from MCLK */
113 ret = snd_soc_dai_set_clkdiv(codec_dai, WM8580_DAC_CLKSEL,
114 WM8580_CLKSRC_MCLK);
115 if (ret < 0)
116 return ret;
117
118 ret = snd_soc_dai_set_pll(codec_dai, WM8580_PLLA, 0,
119 SMDK64XX_WM8580_FREQ, pll_out);
120 if (ret < 0)
121 return ret;
122
123 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_BCLK, bfs);
124 if (ret < 0)
125 return ret;
126
127 ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C_I2SV2_DIV_RCLK, rfs);
128 if (ret < 0)
129 return ret;
130
131 return 0;
132}
133
134/*
135 * SMDK64XX WM8580 DAI operations.
136 */
137static struct snd_soc_ops smdk64xx_ops = {
138 .hw_params = smdk64xx_hw_params,
139};
140
141/* SMDK64xx Playback widgets */
142static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
143 SND_SOC_DAPM_HP("Front-L/R", NULL),
144 SND_SOC_DAPM_HP("Center/Sub", NULL),
145 SND_SOC_DAPM_HP("Rear-L/R", NULL),
146};
147
148/* SMDK64xx Capture widgets */
149static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
150 SND_SOC_DAPM_MIC("MicIn", NULL),
151 SND_SOC_DAPM_LINE("LineIn", NULL),
152};
153
154/* SMDK-PAIFTX connections */
155static const struct snd_soc_dapm_route audio_map_tx[] = {
156 /* MicIn feeds AINL */
157 {"AINL", NULL, "MicIn"},
158
159 /* LineIn feeds AINL/R */
160 {"AINL", NULL, "LineIn"},
161 {"AINR", NULL, "LineIn"},
162};
163
164/* SMDK-PAIFRX connections */
165static const struct snd_soc_dapm_route audio_map_rx[] = {
166 /* Front Left/Right are fed VOUT1L/R */
167 {"Front-L/R", NULL, "VOUT1L"},
168 {"Front-L/R", NULL, "VOUT1R"},
169
170 /* Center/Sub are fed VOUT2L/R */
171 {"Center/Sub", NULL, "VOUT2L"},
172 {"Center/Sub", NULL, "VOUT2R"},
173
174 /* Rear Left/Right are fed VOUT3L/R */
175 {"Rear-L/R", NULL, "VOUT3L"},
176 {"Rear-L/R", NULL, "VOUT3R"},
177};
178
179static int smdk64xx_wm8580_init_paiftx(struct snd_soc_codec *codec)
180{
181 /* Add smdk64xx specific Capture widgets */
182 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_cpt,
183 ARRAY_SIZE(wm8580_dapm_widgets_cpt));
184
185 /* Set up PAIFTX audio path */
186 snd_soc_dapm_add_routes(codec, audio_map_tx, ARRAY_SIZE(audio_map_tx));
187
188 /* Enabling the microphone requires the fitting of a 0R
189 * resistor to connect the line from the microphone jack.
190 */
191 snd_soc_dapm_disable_pin(codec, "MicIn");
192
193 /* signal a DAPM event */
194 snd_soc_dapm_sync(codec);
195
196 return 0;
197}
198
199static int smdk64xx_wm8580_init_paifrx(struct snd_soc_codec *codec)
200{
201 /* Add smdk64xx specific Playback widgets */
202 snd_soc_dapm_new_controls(codec, wm8580_dapm_widgets_pbk,
203 ARRAY_SIZE(wm8580_dapm_widgets_pbk));
204
205 /* Set up PAIFRX audio path */
206 snd_soc_dapm_add_routes(codec, audio_map_rx, ARRAY_SIZE(audio_map_rx));
207
208 /* signal a DAPM event */
209 snd_soc_dapm_sync(codec);
210
211 return 0;
212}
213
214static struct snd_soc_dai_link smdk64xx_dai[] = {
215{ /* Primary Playback i/f */
216 .name = "WM8580 PAIF RX",
217 .stream_name = "Playback",
218 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
219 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFRX],
220 .init = smdk64xx_wm8580_init_paifrx,
221 .ops = &smdk64xx_ops,
222},
223{ /* Primary Capture i/f */
224 .name = "WM8580 PAIF TX",
225 .stream_name = "Capture",
226 .cpu_dai = &s3c64xx_i2s_dai[S3C64XX_I2S_V4],
227 .codec_dai = &wm8580_dai[WM8580_DAI_PAIFTX],
228 .init = smdk64xx_wm8580_init_paiftx,
229 .ops = &smdk64xx_ops,
230},
231};
232
233static struct snd_soc_card smdk64xx = {
234 .name = "smdk64xx",
235 .platform = &s3c24xx_soc_platform,
236 .dai_link = smdk64xx_dai,
237 .num_links = ARRAY_SIZE(smdk64xx_dai),
238};
239
240static struct snd_soc_device smdk64xx_snd_devdata = {
241 .card = &smdk64xx,
242 .codec_dev = &soc_codec_dev_wm8580,
243};
244
245static struct platform_device *smdk64xx_snd_device;
246
247static int __init smdk64xx_audio_init(void)
248{
249 int ret;
250
251 smdk64xx_snd_device = platform_device_alloc("soc-audio", -1);
252 if (!smdk64xx_snd_device)
253 return -ENOMEM;
254
255 platform_set_drvdata(smdk64xx_snd_device, &smdk64xx_snd_devdata);
256 smdk64xx_snd_devdata.dev = &smdk64xx_snd_device->dev;
257 ret = platform_device_add(smdk64xx_snd_device);
258
259 if (ret)
260 platform_device_put(smdk64xx_snd_device);
261
262 return ret;
263}
264module_init(smdk64xx_audio_init);
265
266MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
267MODULE_DESCRIPTION("ALSA SoC SMDK64XX WM8580");
268MODULE_LICENSE("GPL");
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 83b8028e209d..0eb1722f6581 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -423,7 +423,7 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
423 snd_pcm_lib_preallocate_free_for_all(pcm); 423 snd_pcm_lib_preallocate_free_for_all(pcm);
424} 424}
425 425
426static u64 s6000_pcm_dmamask = DMA_32BIT_MASK; 426static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
427 427
428static int s6000_pcm_new(struct snd_card *card, 428static int s6000_pcm_new(struct snd_card *card,
429 struct snd_soc_dai *dai, struct snd_pcm *pcm) 429 struct snd_soc_dai *dai, struct snd_pcm *pcm)
@@ -435,7 +435,7 @@ static int s6000_pcm_new(struct snd_card *card,
435 if (!card->dev->dma_mask) 435 if (!card->dev->dma_mask)
436 card->dev->dma_mask = &s6000_pcm_dmamask; 436 card->dev->dma_mask = &s6000_pcm_dmamask;
437 if (!card->dev->coherent_dma_mask) 437 if (!card->dev->coherent_dma_mask)
438 card->dev->coherent_dma_mask = DMA_32BIT_MASK; 438 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
439 439
440 if (params->dma_in) { 440 if (params->dma_in) {
441 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in), 441 s6dmac_disable_chan(DMA_MASK_DMAC(params->dma_in),
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..9c49c11c43ce 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -17,7 +17,7 @@
17#include <linux/platform_device.h> 17#include <linux/platform_device.h>
18#include <linux/delay.h> 18#include <linux/delay.h>
19#include <linux/list.h> 19#include <linux/list.h>
20#include <linux/clk.h> 20#include <linux/pm_runtime.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <sound/core.h> 22#include <sound/core.h>
23#include <sound/pcm.h> 23#include <sound/pcm.h>
@@ -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;
@@ -108,7 +105,6 @@ struct fsi_priv {
108struct fsi_master { 105struct fsi_master {
109 void __iomem *base; 106 void __iomem *base;
110 int irq; 107 int irq;
111 struct clk *clk;
112 struct fsi_priv fsia; 108 struct fsi_priv fsia;
113 struct fsi_priv fsib; 109 struct fsi_priv fsib;
114 struct sh_fsi_platform_info *info; 110 struct sh_fsi_platform_info *info;
@@ -308,62 +304,6 @@ static int fsi_get_fifo_residue(struct fsi_priv *fsi, int is_play)
308 return residue; 304 return residue;
309} 305}
310 306
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/************************************************************************ 307/************************************************************************
368 308
369 309
@@ -435,44 +375,6 @@ static void fsi_soft_all_reset(void)
435 mdelay(10); 375 mdelay(10);
436} 376}
437 377
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 */ 378/* playback interrupt */
477static int fsi_data_push(struct fsi_priv *fsi) 379static int fsi_data_push(struct fsi_priv *fsi)
478{ 380{
@@ -481,6 +383,8 @@ static int fsi_data_push(struct fsi_priv *fsi)
481 int send; 383 int send;
482 int fifo_free; 384 int fifo_free;
483 int width; 385 int width;
386 u8 *start;
387 int i;
484 388
485 if (!fsi || 389 if (!fsi ||
486 !fsi->substream || 390 !fsi->substream ||
@@ -515,12 +419,22 @@ static int fsi_data_push(struct fsi_priv *fsi)
515 if (fifo_free < send) 419 if (fifo_free < send)
516 send = fifo_free; 420 send = fifo_free;
517 421
518 if (2 == width) 422 start = runtime->dma_area;
519 fsi_16data_push(fsi, runtime, send); 423 start += fsi->byte_offset;
520 else if (4 == width) 424
521 fsi_32data_push(fsi, runtime, send); 425 switch (width) {
522 else 426 case 2:
427 for (i = 0; i < send; i++)
428 fsi_reg_write(fsi, DODT,
429 ((u32)*((u16 *)start + i) << 8));
430 break;
431 case 4:
432 for (i = 0; i < send; i++)
433 fsi_reg_write(fsi, DODT, *((u32 *)start + i));
434 break;
435 default:
523 return -EINVAL; 436 return -EINVAL;
437 }
524 438
525 fsi->byte_offset += send * width; 439 fsi->byte_offset += send * width;
526 440
@@ -532,6 +446,75 @@ static int fsi_data_push(struct fsi_priv *fsi)
532 return 0; 446 return 0;
533} 447}
534 448
449static int fsi_data_pop(struct fsi_priv *fsi)
450{
451 struct snd_pcm_runtime *runtime;
452 struct snd_pcm_substream *substream = NULL;
453 int free;
454 int fifo_fill;
455 int width;
456 u8 *start;
457 int i;
458
459 if (!fsi ||
460 !fsi->substream ||
461 !fsi->substream->runtime)
462 return -EINVAL;
463
464 runtime = fsi->substream->runtime;
465
466 /* FSI FIFO has limit.
467 * So, this driver can not send periods data at a time
468 */
469 if (fsi->byte_offset >=
470 fsi->period_len * (fsi->periods + 1)) {
471
472 substream = fsi->substream;
473 fsi->periods = (fsi->periods + 1) % runtime->periods;
474
475 if (0 == fsi->periods)
476 fsi->byte_offset = 0;
477 }
478
479 /* get 1 channel data width */
480 width = frames_to_bytes(runtime, 1) / fsi->chan;
481
482 /* get free space for alsa */
483 free = (fsi->buffer_len - fsi->byte_offset) / width;
484
485 /* get recv size */
486 fifo_fill = fsi_get_fifo_residue(fsi, 0);
487
488 if (free < fifo_fill)
489 fifo_fill = free;
490
491 start = runtime->dma_area;
492 start += fsi->byte_offset;
493
494 switch (width) {
495 case 2:
496 for (i = 0; i < fifo_fill; i++)
497 *((u16 *)start + i) =
498 (u16)(fsi_reg_read(fsi, DIDT) >> 8);
499 break;
500 case 4:
501 for (i = 0; i < fifo_fill; i++)
502 *((u32 *)start + i) = fsi_reg_read(fsi, DIDT);
503 break;
504 default:
505 return -EINVAL;
506 }
507
508 fsi->byte_offset += fifo_fill * width;
509
510 fsi_irq_enable(fsi, 0);
511
512 if (substream)
513 snd_pcm_period_elapsed(substream);
514
515 return 0;
516}
517
535static irqreturn_t fsi_interrupt(int irq, void *data) 518static irqreturn_t fsi_interrupt(int irq, void *data)
536{ 519{
537 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010; 520 u32 status = fsi_master_read(SOFT_RST) & ~0x00000010;
@@ -545,6 +528,10 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
545 fsi_data_push(&master->fsia); 528 fsi_data_push(&master->fsia);
546 if (int_st & INT_B_OUT) 529 if (int_st & INT_B_OUT)
547 fsi_data_push(&master->fsib); 530 fsi_data_push(&master->fsib);
531 if (int_st & INT_A_IN)
532 fsi_data_pop(&master->fsia);
533 if (int_st & INT_B_IN)
534 fsi_data_pop(&master->fsib);
548 535
549 fsi_master_write(INT_ST, 0x0000000); 536 fsi_master_write(INT_ST, 0x0000000);
550 537
@@ -571,7 +558,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
571 int is_master; 558 int is_master;
572 int ret = 0; 559 int ret = 0;
573 560
574 clk_enable(master->clk); 561 pm_runtime_get_sync(dai->dev);
575 562
576 /* CKG1 */ 563 /* CKG1 */
577 data = is_play ? (1 << 0) : (1 << 4); 564 data = is_play ? (1 << 0) : (1 << 4);
@@ -664,8 +651,6 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
664 } 651 }
665 652
666 fsi_reg_write(fsi, reg, data); 653 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 654
670 /* 655 /*
671 * clear clk reset if master mode 656 * clear clk reset if master mode
@@ -688,7 +673,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
688 fsi_irq_disable(fsi, is_play); 673 fsi_irq_disable(fsi, is_play);
689 fsi_clk_ctrl(fsi, 0); 674 fsi_clk_ctrl(fsi, 0);
690 675
691 clk_disable(master->clk); 676 pm_runtime_put_sync(dai->dev);
692} 677}
693 678
694static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd, 679static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
@@ -699,16 +684,12 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
699 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK; 684 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
700 int ret = 0; 685 int ret = 0;
701 686
702 /* capture not supported */
703 if (!is_play)
704 return -ENODEV;
705
706 switch (cmd) { 687 switch (cmd) {
707 case SNDRV_PCM_TRIGGER_START: 688 case SNDRV_PCM_TRIGGER_START:
708 fsi_stream_push(fsi, substream, 689 fsi_stream_push(fsi, substream,
709 frames_to_bytes(runtime, runtime->buffer_size), 690 frames_to_bytes(runtime, runtime->buffer_size),
710 frames_to_bytes(runtime, runtime->period_size)); 691 frames_to_bytes(runtime, runtime->period_size));
711 ret = fsi_data_push(fsi); 692 ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
712 break; 693 break;
713 case SNDRV_PCM_TRIGGER_STOP: 694 case SNDRV_PCM_TRIGGER_STOP:
714 fsi_irq_disable(fsi, is_play); 695 fsi_irq_disable(fsi, is_play);
@@ -780,10 +761,9 @@ static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
780{ 761{
781 struct snd_pcm_runtime *runtime = substream->runtime; 762 struct snd_pcm_runtime *runtime = substream->runtime;
782 struct fsi_priv *fsi = fsi_get(substream); 763 struct fsi_priv *fsi = fsi_get(substream);
783 int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
784 long location; 764 long location;
785 765
786 location = (fsi->byte_offset - 1) - fsi_get_residue(fsi, is_play); 766 location = (fsi->byte_offset - 1);
787 if (location < 0) 767 if (location < 0)
788 location = 0; 768 location = 0;
789 769
@@ -845,7 +825,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
845 .channels_min = 1, 825 .channels_min = 1,
846 .channels_max = 8, 826 .channels_max = 8,
847 }, 827 },
848 /* capture not supported */ 828 .capture = {
829 .rates = FSI_RATES,
830 .formats = FSI_FMTS,
831 .channels_min = 1,
832 .channels_max = 8,
833 },
849 .ops = &fsi_dai_ops, 834 .ops = &fsi_dai_ops,
850 }, 835 },
851 { 836 {
@@ -857,7 +842,12 @@ struct snd_soc_dai fsi_soc_dai[] = {
857 .channels_min = 1, 842 .channels_min = 1,
858 .channels_max = 8, 843 .channels_max = 8,
859 }, 844 },
860 /* capture not supported */ 845 .capture = {
846 .rates = FSI_RATES,
847 .formats = FSI_FMTS,
848 .channels_min = 1,
849 .channels_max = 8,
850 },
861 .ops = &fsi_dai_ops, 851 .ops = &fsi_dai_ops,
862 }, 852 },
863}; 853};
@@ -881,7 +871,6 @@ EXPORT_SYMBOL_GPL(fsi_soc_platform);
881static int fsi_probe(struct platform_device *pdev) 871static int fsi_probe(struct platform_device *pdev)
882{ 872{
883 struct resource *res; 873 struct resource *res;
884 char clk_name[8];
885 unsigned int irq; 874 unsigned int irq;
886 int ret; 875 int ret;
887 876
@@ -912,23 +901,8 @@ static int fsi_probe(struct platform_device *pdev)
912 master->fsia.base = master->base; 901 master->fsia.base = master->base;
913 master->fsib.base = master->base + 0x40; 902 master->fsib.base = master->base + 0x40;
914 903
915 master->fsia.dma_chan = -1; 904 pm_runtime_enable(&pdev->dev);
916 master->fsib.dma_chan = -1; 905 pm_runtime_resume(&pdev->dev);
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 */
925 snprintf(clk_name, sizeof(clk_name), "spu%d", pdev->id);
926 master->clk = clk_get(NULL, clk_name);
927 if (IS_ERR(master->clk)) {
928 dev_err(&pdev->dev, "cannot get %s mstp\n", clk_name);
929 ret = -EIO;
930 goto exit_free_dma;
931 }
932 906
933 fsi_soc_dai[0].dev = &pdev->dev; 907 fsi_soc_dai[0].dev = &pdev->dev;
934 fsi_soc_dai[1].dev = &pdev->dev; 908 fsi_soc_dai[1].dev = &pdev->dev;
@@ -938,7 +912,7 @@ static int fsi_probe(struct platform_device *pdev)
938 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master); 912 ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED, "fsi", master);
939 if (ret) { 913 if (ret) {
940 dev_err(&pdev->dev, "irq request err\n"); 914 dev_err(&pdev->dev, "irq request err\n");
941 goto exit_free_dma; 915 goto exit_iounmap;
942 } 916 }
943 917
944 ret = snd_soc_register_platform(&fsi_soc_platform); 918 ret = snd_soc_register_platform(&fsi_soc_platform);
@@ -951,10 +925,9 @@ static int fsi_probe(struct platform_device *pdev)
951 925
952exit_free_irq: 926exit_free_irq:
953 free_irq(irq, master); 927 free_irq(irq, master);
954exit_free_dma:
955 fsi_free_dma_chan();
956exit_iounmap: 928exit_iounmap:
957 iounmap(master->base); 929 iounmap(master->base);
930 pm_runtime_disable(&pdev->dev);
958exit_kfree: 931exit_kfree:
959 kfree(master); 932 kfree(master);
960 master = NULL; 933 master = NULL;
@@ -967,9 +940,7 @@ static int fsi_remove(struct platform_device *pdev)
967 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai)); 940 snd_soc_unregister_dais(fsi_soc_dai, ARRAY_SIZE(fsi_soc_dai));
968 snd_soc_unregister_platform(&fsi_soc_platform); 941 snd_soc_unregister_platform(&fsi_soc_platform);
969 942
970 clk_put(master->clk); 943 pm_runtime_disable(&pdev->dev);
971
972 fsi_free_dma_chan();
973 944
974 free_irq(master->irq, master); 945 free_irq(master->irq, master);
975 946
@@ -979,9 +950,27 @@ static int fsi_remove(struct platform_device *pdev)
979 return 0; 950 return 0;
980} 951}
981 952
953static int fsi_runtime_nop(struct device *dev)
954{
955 /* Runtime PM callback shared between ->runtime_suspend()
956 * and ->runtime_resume(). Simply returns success.
957 *
958 * This driver re-initializes all registers after
959 * pm_runtime_get_sync() anyway so there is no need
960 * to save and restore registers here.
961 */
962 return 0;
963}
964
965static struct dev_pm_ops fsi_pm_ops = {
966 .runtime_suspend = fsi_runtime_nop,
967 .runtime_resume = fsi_runtime_nop,
968};
969
982static struct platform_driver fsi_driver = { 970static struct platform_driver fsi_driver = {
983 .driver = { 971 .driver = {
984 .name = "sh_fsi", 972 .name = "sh_fsi",
973 .pm = &fsi_pm_ops,
985 }, 974 },
986 .probe = fsi_probe, 975 .probe = fsi_probe,
987 .remove = fsi_remove, 976 .remove = fsi_remove,
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index c8ceddc2a26c..d2505e8b06c9 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -77,6 +77,35 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data,
77#define snd_soc_7_9_spi_write NULL 77#define snd_soc_7_9_spi_write NULL
78#endif 78#endif
79 79
80static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 *cache = codec->reg_cache;
84 u8 data[2];
85
86 BUG_ON(codec->volatile_register);
87
88 data[0] = reg & 0xff;
89 data[1] = value & 0xff;
90
91 if (reg < codec->reg_cache_size)
92 cache[reg] = value;
93
94 if (codec->hw_write(codec->control_data, data, 2) == 2)
95 return 0;
96 else
97 return -EIO;
98}
99
100static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
101 unsigned int reg)
102{
103 u8 *cache = codec->reg_cache;
104 if (reg >= codec->reg_cache_size)
105 return -1;
106 return cache[reg];
107}
108
80static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, 109static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value) 110 unsigned int value)
82{ 111{
@@ -150,9 +179,20 @@ static struct {
150 unsigned int (*read)(struct snd_soc_codec *, unsigned int); 179 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
151 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); 180 unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
152} io_types[] = { 181} io_types[] = {
153 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_spi_write, snd_soc_7_9_read }, 182 {
154 { 8, 16, snd_soc_8_16_write, NULL, snd_soc_8_16_read, 183 .addr_bits = 7, .data_bits = 9,
155 snd_soc_8_16_read_i2c }, 184 .write = snd_soc_7_9_write, .read = snd_soc_7_9_read,
185 .spi_write = snd_soc_7_9_spi_write
186 },
187 {
188 .addr_bits = 8, .data_bits = 8,
189 .write = snd_soc_8_8_write, .read = snd_soc_8_8_read,
190 },
191 {
192 .addr_bits = 8, .data_bits = 16,
193 .write = snd_soc_8_16_write, .read = snd_soc_8_16_read,
194 .i2c_read = snd_soc_8_16_read_i2c,
195 },
156}; 196};
157 197
158/** 198/**
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 7ff04ad2a97e..ef8f28284cb9 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)
@@ -790,56 +956,21 @@ static int soc_resume(struct device *dev)
790 956
791 return 0; 957 return 0;
792} 958}
793
794/**
795 * snd_soc_suspend_device: Notify core of device suspend
796 *
797 * @dev: Device being suspended.
798 *
799 * In order to ensure that the entire audio subsystem is suspended in a
800 * coordinated fashion ASoC devices should suspend themselves when
801 * called by ASoC. When the standard kernel suspend process asks the
802 * device to suspend it should call this function to initiate a suspend
803 * of the entire ASoC card.
804 *
805 * \note Currently this function is stubbed out.
806 */
807int snd_soc_suspend_device(struct device *dev)
808{
809 return 0;
810}
811EXPORT_SYMBOL_GPL(snd_soc_suspend_device);
812
813/**
814 * snd_soc_resume_device: Notify core of device resume
815 *
816 * @dev: Device being resumed.
817 *
818 * In order to ensure that the entire audio subsystem is resumed in a
819 * coordinated fashion ASoC devices should resume themselves when called
820 * by ASoC. When the standard kernel resume process asks the device
821 * to resume it should call this function. Once all the components of
822 * the card have notified that they are ready to be resumed the card
823 * will be resumed.
824 *
825 * \note Currently this function is stubbed out.
826 */
827int snd_soc_resume_device(struct device *dev)
828{
829 return 0;
830}
831EXPORT_SYMBOL_GPL(snd_soc_resume_device);
832#else 959#else
833#define soc_suspend NULL 960#define soc_suspend NULL
834#define soc_resume NULL 961#define soc_resume NULL
835#endif 962#endif
836 963
964static struct snd_soc_dai_ops null_dai_ops = {
965};
966
837static void snd_soc_instantiate_card(struct snd_soc_card *card) 967static void snd_soc_instantiate_card(struct snd_soc_card *card)
838{ 968{
839 struct platform_device *pdev = container_of(card->dev, 969 struct platform_device *pdev = container_of(card->dev,
840 struct platform_device, 970 struct platform_device,
841 dev); 971 dev);
842 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;
843 struct snd_soc_platform *platform; 974 struct snd_soc_platform *platform;
844 struct snd_soc_dai *dai; 975 struct snd_soc_dai *dai;
845 int i, found, ret, ac97; 976 int i, found, ret, ac97;
@@ -877,6 +1008,11 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
877 ac97 = 1; 1008 ac97 = 1;
878 } 1009 }
879 1010
1011 for (i = 0; i < card->num_links; i++) {
1012 if (!card->dai_link[i].codec_dai->ops)
1013 card->dai_link[i].codec_dai->ops = &null_dai_ops;
1014 }
1015
880 /* If we have AC97 in the system then don't wait for the 1016 /* If we have AC97 in the system then don't wait for the
881 * codec. This will need revisiting if we have to handle 1017 * codec. This will need revisiting if we have to handle
882 * systems with mixed AC97 and non-AC97 parts. Only check for 1018 * systems with mixed AC97 and non-AC97 parts. Only check for
@@ -923,6 +1059,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
923 if (ret < 0) 1059 if (ret < 0)
924 goto cpu_dai_err; 1060 goto cpu_dai_err;
925 } 1061 }
1062 codec = card->codec;
926 1063
927 if (platform->probe) { 1064 if (platform->probe) {
928 ret = platform->probe(pdev); 1065 ret = platform->probe(pdev);
@@ -937,10 +1074,69 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
937 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); 1074 INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
938#endif 1075#endif
939 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 }
1089
1090 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1091 "%s", card->name);
1092 snprintf(codec->card->longname, sizeof(codec->card->longname),
1093 "%s (%s)", card->name, codec->name);
1094
1095 /* Make sure all DAPM widgets are instantiated */
1096 snd_soc_dapm_new_widgets(codec);
1097
1098 ret = snd_card_register(codec->card);
1099 if (ret < 0) {
1100 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1101 codec->name);
1102 goto card_err;
1103 }
1104
1105 mutex_lock(&codec->mutex);
1106#ifdef CONFIG_SND_SOC_AC97_BUS
1107 /* Only instantiate AC97 if not already done by the adaptor
1108 * for the generic AC97 subsystem.
1109 */
1110 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1111 ret = soc_ac97_dev_register(codec);
1112 if (ret < 0) {
1113 printk(KERN_ERR "asoc: AC97 device register failed\n");
1114 snd_card_free(codec->card);
1115 mutex_unlock(&codec->mutex);
1116 goto card_err;
1117 }
1118 }
1119#endif
1120
1121 ret = snd_soc_dapm_sys_add(card->socdev->dev);
1122 if (ret < 0)
1123 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1124
1125 ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg);
1126 if (ret < 0)
1127 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1128
1129 soc_init_codec_debugfs(codec);
1130 mutex_unlock(&codec->mutex);
1131
940 card->instantiated = 1; 1132 card->instantiated = 1;
941 1133
942 return; 1134 return;
943 1135
1136card_err:
1137 if (platform->remove)
1138 platform->remove(pdev);
1139
944platform_err: 1140platform_err:
945 if (codec_dev->remove) 1141 if (codec_dev->remove)
946 codec_dev->remove(pdev); 1142 codec_dev->remove(pdev);
@@ -1143,157 +1339,6 @@ int snd_soc_codec_volatile_register(struct snd_soc_codec *codec, int reg)
1143} 1339}
1144EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register); 1340EXPORT_SYMBOL_GPL(snd_soc_codec_volatile_register);
1145 1341
1146/* codec register dump */
1147static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf)
1148{
1149 int i, step = 1, count = 0;
1150
1151 if (!codec->reg_cache_size)
1152 return 0;
1153
1154 if (codec->reg_cache_step)
1155 step = codec->reg_cache_step;
1156
1157 count += sprintf(buf, "%s registers\n", codec->name);
1158 for (i = 0; i < codec->reg_cache_size; i += step) {
1159 if (codec->readable_register && !codec->readable_register(i))
1160 continue;
1161
1162 count += sprintf(buf + count, "%2x: ", i);
1163 if (count >= PAGE_SIZE - 1)
1164 break;
1165
1166 if (codec->display_register)
1167 count += codec->display_register(codec, buf + count,
1168 PAGE_SIZE - count, i);
1169 else
1170 count += snprintf(buf + count, PAGE_SIZE - count,
1171 "%4x", codec->read(codec, i));
1172
1173 if (count >= PAGE_SIZE - 1)
1174 break;
1175
1176 count += snprintf(buf + count, PAGE_SIZE - count, "\n");
1177 if (count >= PAGE_SIZE - 1)
1178 break;
1179 }
1180
1181 /* Truncate count; min() would cause a warning */
1182 if (count >= PAGE_SIZE)
1183 count = PAGE_SIZE - 1;
1184
1185 return count;
1186}
1187static ssize_t codec_reg_show(struct device *dev,
1188 struct device_attribute *attr, char *buf)
1189{
1190 struct snd_soc_device *devdata = dev_get_drvdata(dev);
1191 return soc_codec_reg_show(devdata->card->codec, buf);
1192}
1193
1194static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
1195
1196#ifdef CONFIG_DEBUG_FS
1197static int codec_reg_open_file(struct inode *inode, struct file *file)
1198{
1199 file->private_data = inode->i_private;
1200 return 0;
1201}
1202
1203static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
1204 size_t count, loff_t *ppos)
1205{
1206 ssize_t ret;
1207 struct snd_soc_codec *codec = file->private_data;
1208 char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
1209 if (!buf)
1210 return -ENOMEM;
1211 ret = soc_codec_reg_show(codec, buf);
1212 if (ret >= 0)
1213 ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
1214 kfree(buf);
1215 return ret;
1216}
1217
1218static ssize_t codec_reg_write_file(struct file *file,
1219 const char __user *user_buf, size_t count, loff_t *ppos)
1220{
1221 char buf[32];
1222 int buf_size;
1223 char *start = buf;
1224 unsigned long reg, value;
1225 int step = 1;
1226 struct snd_soc_codec *codec = file->private_data;
1227
1228 buf_size = min(count, (sizeof(buf)-1));
1229 if (copy_from_user(buf, user_buf, buf_size))
1230 return -EFAULT;
1231 buf[buf_size] = 0;
1232
1233 if (codec->reg_cache_step)
1234 step = codec->reg_cache_step;
1235
1236 while (*start == ' ')
1237 start++;
1238 reg = simple_strtoul(start, &start, 16);
1239 if ((reg >= codec->reg_cache_size) || (reg % step))
1240 return -EINVAL;
1241 while (*start == ' ')
1242 start++;
1243 if (strict_strtoul(start, 16, &value))
1244 return -EINVAL;
1245 codec->write(codec, reg, value);
1246 return buf_size;
1247}
1248
1249static const struct file_operations codec_reg_fops = {
1250 .open = codec_reg_open_file,
1251 .read = codec_reg_read_file,
1252 .write = codec_reg_write_file,
1253};
1254
1255static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1256{
1257 codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
1258 debugfs_root, codec,
1259 &codec_reg_fops);
1260 if (!codec->debugfs_reg)
1261 printk(KERN_WARNING
1262 "ASoC: Failed to create codec register debugfs file\n");
1263
1264 codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
1265 debugfs_root,
1266 &codec->pop_time);
1267 if (!codec->debugfs_pop_time)
1268 printk(KERN_WARNING
1269 "Failed to create pop time debugfs file\n");
1270
1271 codec->debugfs_dapm = debugfs_create_dir("dapm", debugfs_root);
1272 if (!codec->debugfs_dapm)
1273 printk(KERN_WARNING
1274 "Failed to create DAPM debugfs directory\n");
1275
1276 snd_soc_dapm_debugfs_init(codec);
1277}
1278
1279static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1280{
1281 debugfs_remove_recursive(codec->debugfs_dapm);
1282 debugfs_remove(codec->debugfs_pop_time);
1283 debugfs_remove(codec->debugfs_reg);
1284}
1285
1286#else
1287
1288static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
1289{
1290}
1291
1292static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
1293{
1294}
1295#endif
1296
1297/** 1342/**
1298 * snd_soc_new_ac97_codec - initailise AC97 device 1343 * snd_soc_new_ac97_codec - initailise AC97 device
1299 * @codec: audio codec 1344 * @codec: audio codec
@@ -1361,19 +1406,41 @@ int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
1361 int change; 1406 int change;
1362 unsigned int old, new; 1407 unsigned int old, new;
1363 1408
1364 mutex_lock(&io_mutex);
1365 old = snd_soc_read(codec, reg); 1409 old = snd_soc_read(codec, reg);
1366 new = (old & ~mask) | value; 1410 new = (old & ~mask) | value;
1367 change = old != new; 1411 change = old != new;
1368 if (change) 1412 if (change)
1369 snd_soc_write(codec, reg, new); 1413 snd_soc_write(codec, reg, new);
1370 1414
1371 mutex_unlock(&io_mutex);
1372 return change; 1415 return change;
1373} 1416}
1374EXPORT_SYMBOL_GPL(snd_soc_update_bits); 1417EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1375 1418
1376/** 1419/**
1420 * snd_soc_update_bits_locked - update codec register bits
1421 * @codec: audio codec
1422 * @reg: codec register
1423 * @mask: register mask
1424 * @value: new value
1425 *
1426 * Writes new register value, and takes the codec mutex.
1427 *
1428 * Returns 1 for change else 0.
1429 */
1430static int snd_soc_update_bits_locked(struct snd_soc_codec *codec,
1431 unsigned short reg, unsigned int mask,
1432 unsigned int value)
1433{
1434 int change;
1435
1436 mutex_lock(&codec->mutex);
1437 change = snd_soc_update_bits(codec, reg, mask, value);
1438 mutex_unlock(&codec->mutex);
1439
1440 return change;
1441}
1442
1443/**
1377 * snd_soc_test_bits - test register for change 1444 * snd_soc_test_bits - test register for change
1378 * @codec: audio codec 1445 * @codec: audio codec
1379 * @reg: codec register 1446 * @reg: codec register
@@ -1391,11 +1458,9 @@ int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1391 int change; 1458 int change;
1392 unsigned int old, new; 1459 unsigned int old, new;
1393 1460
1394 mutex_lock(&io_mutex);
1395 old = snd_soc_read(codec, reg); 1461 old = snd_soc_read(codec, reg);
1396 new = (old & ~mask) | value; 1462 new = (old & ~mask) | value;
1397 change = old != new; 1463 change = old != new;
1398 mutex_unlock(&io_mutex);
1399 1464
1400 return change; 1465 return change;
1401} 1466}
@@ -1442,89 +1507,16 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1442 mutex_unlock(&codec->mutex); 1507 mutex_unlock(&codec->mutex);
1443 return ret; 1508 return ret;
1444 } 1509 }
1445 }
1446
1447 mutex_unlock(&codec->mutex);
1448 return ret;
1449}
1450EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1451
1452/**
1453 * snd_soc_init_card - register sound card
1454 * @socdev: the SoC audio device
1455 *
1456 * Register a SoC sound card. Also registers an AC97 device if the
1457 * codec is AC97 for ad hoc devices.
1458 *
1459 * Returns 0 for success, else error.
1460 */
1461int snd_soc_init_card(struct snd_soc_device *socdev)
1462{
1463 struct snd_soc_card *card = socdev->card;
1464 struct snd_soc_codec *codec = card->codec;
1465 int ret = 0, i, ac97 = 0, err = 0;
1466
1467 for (i = 0; i < card->num_links; i++) {
1468 if (card->dai_link[i].init) {
1469 err = card->dai_link[i].init(codec);
1470 if (err < 0) {
1471 printk(KERN_ERR "asoc: failed to init %s\n",
1472 card->dai_link[i].stream_name);
1473 continue;
1474 }
1475 }
1476 if (card->dai_link[i].codec_dai->ac97_control) { 1510 if (card->dai_link[i].codec_dai->ac97_control) {
1477 ac97 = 1;
1478 snd_ac97_dev_add_pdata(codec->ac97, 1511 snd_ac97_dev_add_pdata(codec->ac97,
1479 card->dai_link[i].cpu_dai->ac97_pdata); 1512 card->dai_link[i].cpu_dai->ac97_pdata);
1480 } 1513 }
1481 } 1514 }
1482 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1483 "%s", card->name);
1484 snprintf(codec->card->longname, sizeof(codec->card->longname),
1485 "%s (%s)", card->name, codec->name);
1486 1515
1487 /* Make sure all DAPM widgets are instantiated */
1488 snd_soc_dapm_new_widgets(codec);
1489
1490 ret = snd_card_register(codec->card);
1491 if (ret < 0) {
1492 printk(KERN_ERR "asoc: failed to register soundcard for %s\n",
1493 codec->name);
1494 goto out;
1495 }
1496
1497 mutex_lock(&codec->mutex);
1498#ifdef CONFIG_SND_SOC_AC97_BUS
1499 /* Only instantiate AC97 if not already done by the adaptor
1500 * for the generic AC97 subsystem.
1501 */
1502 if (ac97 && strcmp(codec->name, "AC97") != 0) {
1503 ret = soc_ac97_dev_register(codec);
1504 if (ret < 0) {
1505 printk(KERN_ERR "asoc: AC97 device register failed\n");
1506 snd_card_free(codec->card);
1507 mutex_unlock(&codec->mutex);
1508 goto out;
1509 }
1510 }
1511#endif
1512
1513 err = snd_soc_dapm_sys_add(socdev->dev);
1514 if (err < 0)
1515 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1516
1517 err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1518 if (err < 0)
1519 printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
1520
1521 soc_init_codec_debugfs(codec);
1522 mutex_unlock(&codec->mutex); 1516 mutex_unlock(&codec->mutex);
1523
1524out:
1525 return ret; 1517 return ret;
1526} 1518}
1527EXPORT_SYMBOL_GPL(snd_soc_init_card); 1519EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1528 1520
1529/** 1521/**
1530 * snd_soc_free_pcms - free sound card and pcms 1522 * snd_soc_free_pcms - free sound card and pcms
@@ -1726,7 +1718,7 @@ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1726 mask |= (bitmask - 1) << e->shift_r; 1718 mask |= (bitmask - 1) << e->shift_r;
1727 } 1719 }
1728 1720
1729 return snd_soc_update_bits(codec, e->reg, mask, val); 1721 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1730} 1722}
1731EXPORT_SYMBOL_GPL(snd_soc_put_enum_double); 1723EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1732 1724
@@ -1800,7 +1792,7 @@ int snd_soc_put_value_enum_double(struct snd_kcontrol *kcontrol,
1800 mask |= e->mask << e->shift_r; 1792 mask |= e->mask << e->shift_r;
1801 } 1793 }
1802 1794
1803 return snd_soc_update_bits(codec, e->reg, mask, val); 1795 return snd_soc_update_bits_locked(codec, e->reg, mask, val);
1804} 1796}
1805EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double); 1797EXPORT_SYMBOL_GPL(snd_soc_put_value_enum_double);
1806 1798
@@ -1961,7 +1953,7 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1961 val_mask |= mask << rshift; 1953 val_mask |= mask << rshift;
1962 val |= val2 << rshift; 1954 val |= val2 << rshift;
1963 } 1955 }
1964 return snd_soc_update_bits(codec, reg, val_mask, val); 1956 return snd_soc_update_bits_locked(codec, reg, val_mask, val);
1965} 1957}
1966EXPORT_SYMBOL_GPL(snd_soc_put_volsw); 1958EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1967 1959
@@ -2067,11 +2059,11 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
2067 val = val << shift; 2059 val = val << shift;
2068 val2 = val2 << shift; 2060 val2 = val2 << shift;
2069 2061
2070 err = snd_soc_update_bits(codec, reg, val_mask, val); 2062 err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
2071 if (err < 0) 2063 if (err < 0)
2072 return err; 2064 return err;
2073 2065
2074 err = snd_soc_update_bits(codec, reg2, val_mask, val2); 2066 err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
2075 return err; 2067 return err;
2076} 2068}
2077EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r); 2069EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
@@ -2150,7 +2142,7 @@ int snd_soc_put_volsw_s8(struct snd_kcontrol *kcontrol,
2150 val = (ucontrol->value.integer.value[0]+min) & 0xff; 2142 val = (ucontrol->value.integer.value[0]+min) & 0xff;
2151 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8; 2143 val |= ((ucontrol->value.integer.value[1]+min) & 0xff) << 8;
2152 2144
2153 return snd_soc_update_bits(codec, reg, 0xffff, val); 2145 return snd_soc_update_bits_locked(codec, reg, 0xffff, val);
2154} 2146}
2155EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); 2147EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
2156 2148
@@ -2197,16 +2189,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
2197 * snd_soc_dai_set_pll - configure DAI PLL. 2189 * snd_soc_dai_set_pll - configure DAI PLL.
2198 * @dai: DAI 2190 * @dai: DAI
2199 * @pll_id: DAI specific PLL ID 2191 * @pll_id: DAI specific PLL ID
2192 * @source: DAI specific source for the PLL
2200 * @freq_in: PLL input clock frequency in Hz 2193 * @freq_in: PLL input clock frequency in Hz
2201 * @freq_out: requested PLL output clock frequency in Hz 2194 * @freq_out: requested PLL output clock frequency in Hz
2202 * 2195 *
2203 * Configures and enables PLL to generate output clock based on input clock. 2196 * Configures and enables PLL to generate output clock based on input clock.
2204 */ 2197 */
2205int snd_soc_dai_set_pll(struct snd_soc_dai *dai, 2198int snd_soc_dai_set_pll(struct snd_soc_dai *dai, int pll_id, int source,
2206 int pll_id, unsigned int freq_in, unsigned int freq_out) 2199 unsigned int freq_in, unsigned int freq_out)
2207{ 2200{
2208 if (dai->ops && dai->ops->set_pll) 2201 if (dai->ops && dai->ops->set_pll)
2209 return dai->ops->set_pll(dai, pll_id, freq_in, freq_out); 2202 return dai->ops->set_pll(dai, pll_id, source,
2203 freq_in, freq_out);
2210 else 2204 else
2211 return -EINVAL; 2205 return -EINVAL;
2212} 2206}
@@ -2251,6 +2245,30 @@ int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
2251EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); 2245EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
2252 2246
2253/** 2247/**
2248 * snd_soc_dai_set_channel_map - configure DAI audio channel map
2249 * @dai: DAI
2250 * @tx_num: how many TX channels
2251 * @tx_slot: pointer to an array which imply the TX slot number channel
2252 * 0~num-1 uses
2253 * @rx_num: how many RX channels
2254 * @rx_slot: pointer to an array which imply the RX slot number channel
2255 * 0~num-1 uses
2256 *
2257 * configure the relationship between channel number and TDM slot number.
2258 */
2259int snd_soc_dai_set_channel_map(struct snd_soc_dai *dai,
2260 unsigned int tx_num, unsigned int *tx_slot,
2261 unsigned int rx_num, unsigned int *rx_slot)
2262{
2263 if (dai->ops && dai->ops->set_channel_map)
2264 return dai->ops->set_channel_map(dai, tx_num, tx_slot,
2265 rx_num, rx_slot);
2266 else
2267 return -EINVAL;
2268}
2269EXPORT_SYMBOL_GPL(snd_soc_dai_set_channel_map);
2270
2271/**
2254 * snd_soc_dai_set_tristate - configure DAI system or master clock. 2272 * snd_soc_dai_set_tristate - configure DAI system or master clock.
2255 * @dai: DAI 2273 * @dai: DAI
2256 * @tristate: tristate enable 2274 * @tristate: tristate enable
@@ -2329,9 +2347,6 @@ static int snd_soc_unregister_card(struct snd_soc_card *card)
2329 return 0; 2347 return 0;
2330} 2348}
2331 2349
2332static struct snd_soc_dai_ops null_dai_ops = {
2333};
2334
2335/** 2350/**
2336 * snd_soc_register_dai - Register a DAI with the ASoC core 2351 * snd_soc_register_dai - Register a DAI with the ASoC core
2337 * 2352 *
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 8de6f9dec4a2..0d294ef72590 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -719,6 +719,10 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
719 719
720 /* Check if one of our outputs is connected */ 720 /* Check if one of our outputs is connected */
721 list_for_each_entry(path, &w->sinks, list_source) { 721 list_for_each_entry(path, &w->sinks, list_source) {
722 if (path->connected &&
723 !path->connected(path->source, path->sink))
724 continue;
725
722 if (path->sink && path->sink->power_check && 726 if (path->sink && path->sink->power_check &&
723 path->sink->power_check(path->sink)) { 727 path->sink->power_check(path->sink)) {
724 power = 1; 728 power = 1;
@@ -973,9 +977,19 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
973 if (!w->power_check) 977 if (!w->power_check)
974 continue; 978 continue;
975 979
976 power = w->power_check(w); 980 /* If we're suspending then pull down all the
977 if (power) 981 * power. */
978 sys_power = 1; 982 switch (event) {
983 case SND_SOC_DAPM_STREAM_SUSPEND:
984 power = 0;
985 break;
986
987 default:
988 power = w->power_check(w);
989 if (power)
990 sys_power = 1;
991 break;
992 }
979 993
980 if (w->power == power) 994 if (w->power == power)
981 continue; 995 continue;
@@ -999,8 +1013,12 @@ static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
999 case SND_SOC_DAPM_STREAM_RESUME: 1013 case SND_SOC_DAPM_STREAM_RESUME:
1000 sys_power = 1; 1014 sys_power = 1;
1001 break; 1015 break;
1016 case SND_SOC_DAPM_STREAM_SUSPEND:
1017 sys_power = 0;
1018 break;
1002 case SND_SOC_DAPM_STREAM_NOP: 1019 case SND_SOC_DAPM_STREAM_NOP:
1003 sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY; 1020 sys_power = codec->bias_level != SND_SOC_BIAS_STANDBY;
1021 break;
1004 default: 1022 default:
1005 break; 1023 break;
1006 } 1024 }
@@ -1138,6 +1156,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1138 w->active ? "active" : "inactive"); 1156 w->active ? "active" : "inactive");
1139 1157
1140 list_for_each_entry(p, &w->sources, list_sink) { 1158 list_for_each_entry(p, &w->sources, list_sink) {
1159 if (p->connected && !p->connected(w, p->sink))
1160 continue;
1161
1141 if (p->connect) 1162 if (p->connect)
1142 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1163 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1143 " in %s %s\n", 1164 " in %s %s\n",
@@ -1145,6 +1166,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
1145 p->source->name); 1166 p->source->name);
1146 } 1167 }
1147 list_for_each_entry(p, &w->sinks, list_source) { 1168 list_for_each_entry(p, &w->sinks, list_source) {
1169 if (p->connected && !p->connected(w, p->sink))
1170 continue;
1171
1148 if (p->connect) 1172 if (p->connect)
1149 ret += snprintf(buf + ret, PAGE_SIZE - ret, 1173 ret += snprintf(buf + ret, PAGE_SIZE - ret,
1150 " out %s %s\n", 1174 " out %s %s\n",
@@ -1192,8 +1216,8 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_codec *codec)
1192 1216
1193/* test and update the power status of a mux widget */ 1217/* test and update the power status of a mux widget */
1194static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget, 1218static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1195 struct snd_kcontrol *kcontrol, int mask, 1219 struct snd_kcontrol *kcontrol, int change,
1196 int mux, int val, struct soc_enum *e) 1220 int mux, struct soc_enum *e)
1197{ 1221{
1198 struct snd_soc_dapm_path *path; 1222 struct snd_soc_dapm_path *path;
1199 int found = 0; 1223 int found = 0;
@@ -1202,7 +1226,7 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
1202 widget->id != snd_soc_dapm_value_mux) 1226 widget->id != snd_soc_dapm_value_mux)
1203 return -ENODEV; 1227 return -ENODEV;
1204 1228
1205 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val)) 1229 if (!change)
1206 return 0; 1230 return 0;
1207 1231
1208 /* find dapm widget path assoc with kcontrol */ 1232 /* find dapm widget path assoc with kcontrol */
@@ -1387,10 +1411,13 @@ int snd_soc_dapm_sync(struct snd_soc_codec *codec)
1387EXPORT_SYMBOL_GPL(snd_soc_dapm_sync); 1411EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
1388 1412
1389static int snd_soc_dapm_add_route(struct snd_soc_codec *codec, 1413static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1390 const char *sink, const char *control, const char *source) 1414 const struct snd_soc_dapm_route *route)
1391{ 1415{
1392 struct snd_soc_dapm_path *path; 1416 struct snd_soc_dapm_path *path;
1393 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w; 1417 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
1418 const char *sink = route->sink;
1419 const char *control = route->control;
1420 const char *source = route->source;
1394 int ret = 0; 1421 int ret = 0;
1395 1422
1396 /* find src and dest widgets */ 1423 /* find src and dest widgets */
@@ -1414,6 +1441,7 @@ static int snd_soc_dapm_add_route(struct snd_soc_codec *codec,
1414 1441
1415 path->source = wsource; 1442 path->source = wsource;
1416 path->sink = wsink; 1443 path->sink = wsink;
1444 path->connected = route->connected;
1417 INIT_LIST_HEAD(&path->list); 1445 INIT_LIST_HEAD(&path->list);
1418 INIT_LIST_HEAD(&path->list_source); 1446 INIT_LIST_HEAD(&path->list_source);
1419 INIT_LIST_HEAD(&path->list_sink); 1447 INIT_LIST_HEAD(&path->list_sink);
@@ -1514,8 +1542,7 @@ int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
1514 int i, ret; 1542 int i, ret;
1515 1543
1516 for (i = 0; i < num; i++) { 1544 for (i = 0; i < num; i++) {
1517 ret = snd_soc_dapm_add_route(codec, route->sink, 1545 ret = snd_soc_dapm_add_route(codec, route);
1518 route->control, route->source);
1519 if (ret < 0) { 1546 if (ret < 0) {
1520 printk(KERN_ERR "Failed to add route %s->%s\n", 1547 printk(KERN_ERR "Failed to add route %s->%s\n",
1521 route->source, 1548 route->source,
@@ -1752,7 +1779,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1752{ 1779{
1753 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1780 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1754 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1781 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1755 unsigned int val, mux; 1782 unsigned int val, mux, change;
1756 unsigned int mask, bitmask; 1783 unsigned int mask, bitmask;
1757 int ret = 0; 1784 int ret = 0;
1758 1785
@@ -1772,20 +1799,21 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1772 1799
1773 mutex_lock(&widget->codec->mutex); 1800 mutex_lock(&widget->codec->mutex);
1774 widget->value = val; 1801 widget->value = val;
1775 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1802 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1776 if (widget->event) { 1803 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1777 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1804
1778 ret = widget->event(widget, 1805 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1779 kcontrol, SND_SOC_DAPM_PRE_REG); 1806 ret = widget->event(widget,
1780 if (ret < 0) 1807 kcontrol, SND_SOC_DAPM_PRE_REG);
1781 goto out; 1808 if (ret < 0)
1782 } 1809 goto out;
1783 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1810 }
1784 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1811
1785 ret = widget->event(widget, 1812 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1786 kcontrol, SND_SOC_DAPM_POST_REG); 1813
1787 } else 1814 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1788 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1815 ret = widget->event(widget,
1816 kcontrol, SND_SOC_DAPM_POST_REG);
1789 1817
1790out: 1818out:
1791 mutex_unlock(&widget->codec->mutex); 1819 mutex_unlock(&widget->codec->mutex);
@@ -1794,6 +1822,54 @@ out:
1794EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double); 1822EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1795 1823
1796/** 1824/**
1825 * snd_soc_dapm_get_enum_virt - Get virtual DAPM mux
1826 * @kcontrol: mixer control
1827 * @ucontrol: control element information
1828 *
1829 * Returns 0 for success.
1830 */
1831int snd_soc_dapm_get_enum_virt(struct snd_kcontrol *kcontrol,
1832 struct snd_ctl_elem_value *ucontrol)
1833{
1834 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1835
1836 ucontrol->value.enumerated.item[0] = widget->value;
1837
1838 return 0;
1839}
1840EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_virt);
1841
1842/**
1843 * snd_soc_dapm_put_enum_virt - Set virtual DAPM mux
1844 * @kcontrol: mixer control
1845 * @ucontrol: control element information
1846 *
1847 * Returns 0 for success.
1848 */
1849int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
1850 struct snd_ctl_elem_value *ucontrol)
1851{
1852 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1853 struct soc_enum *e =
1854 (struct soc_enum *)kcontrol->private_value;
1855 int change;
1856 int ret = 0;
1857
1858 if (ucontrol->value.enumerated.item[0] >= e->max)
1859 return -EINVAL;
1860
1861 mutex_lock(&widget->codec->mutex);
1862
1863 change = widget->value != ucontrol->value.enumerated.item[0];
1864 widget->value = ucontrol->value.enumerated.item[0];
1865 dapm_mux_update_power(widget, kcontrol, change, widget->value, e);
1866
1867 mutex_unlock(&widget->codec->mutex);
1868 return ret;
1869}
1870EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_virt);
1871
1872/**
1797 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get 1873 * snd_soc_dapm_get_value_enum_double - dapm semi enumerated double mixer get
1798 * callback 1874 * callback
1799 * @kcontrol: mixer control 1875 * @kcontrol: mixer control
@@ -1851,7 +1927,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1851{ 1927{
1852 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol); 1928 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1853 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; 1929 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1854 unsigned int val, mux; 1930 unsigned int val, mux, change;
1855 unsigned int mask; 1931 unsigned int mask;
1856 int ret = 0; 1932 int ret = 0;
1857 1933
@@ -1869,20 +1945,21 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
1869 1945
1870 mutex_lock(&widget->codec->mutex); 1946 mutex_lock(&widget->codec->mutex);
1871 widget->value = val; 1947 widget->value = val;
1872 dapm_mux_update_power(widget, kcontrol, mask, mux, val, e); 1948 change = snd_soc_test_bits(widget->codec, e->reg, mask, val);
1873 if (widget->event) { 1949 dapm_mux_update_power(widget, kcontrol, change, mux, e);
1874 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) { 1950
1875 ret = widget->event(widget, 1951 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1876 kcontrol, SND_SOC_DAPM_PRE_REG); 1952 ret = widget->event(widget,
1877 if (ret < 0) 1953 kcontrol, SND_SOC_DAPM_PRE_REG);
1878 goto out; 1954 if (ret < 0)
1879 } 1955 goto out;
1880 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1956 }
1881 if (widget->event_flags & SND_SOC_DAPM_POST_REG) 1957
1882 ret = widget->event(widget, 1958 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1883 kcontrol, SND_SOC_DAPM_POST_REG); 1959
1884 } else 1960 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1885 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val); 1961 ret = widget->event(widget,
1962 kcontrol, SND_SOC_DAPM_POST_REG);
1886 1963
1887out: 1964out:
1888 mutex_unlock(&widget->codec->mutex); 1965 mutex_unlock(&widget->codec->mutex);
@@ -2072,9 +2149,9 @@ int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
2072 } 2149 }
2073 } 2150 }
2074 } 2151 }
2075 mutex_unlock(&codec->mutex);
2076 2152
2077 dapm_power_widgets(codec, event); 2153 dapm_power_widgets(codec, event);
2154 mutex_unlock(&codec->mutex);
2078 dump_dapm(codec, __func__); 2155 dump_dapm(codec, __func__);
2079 return 0; 2156 return 0;
2080} 2157}
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 1d455ab79490..3c07a94c2e30 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(snd_soc_jack_new);
58 */ 58 */
59void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) 59void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
60{ 60{
61 struct snd_soc_codec *codec = jack->card->codec; 61 struct snd_soc_codec *codec;
62 struct snd_soc_jack_pin *pin; 62 struct snd_soc_jack_pin *pin;
63 int enable; 63 int enable;
64 int oldstatus; 64 int oldstatus;
@@ -67,6 +67,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
67 WARN_ON_ONCE(!jack); 67 WARN_ON_ONCE(!jack);
68 return; 68 return;
69 } 69 }
70 codec = jack->card->codec;
70 71
71 mutex_lock(&codec->mutex); 72 mutex_lock(&codec->mutex);
72 73
@@ -162,6 +163,9 @@ static void snd_soc_jack_gpio_detect(struct snd_soc_jack_gpio *gpio)
162 else 163 else
163 report = 0; 164 report = 0;
164 165
166 if (gpio->jack_status_check)
167 report = gpio->jack_status_check();
168
165 snd_soc_jack_report(jack, report, gpio->report); 169 snd_soc_jack_report(jack, report, gpio->report);
166} 170}
167 171
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
new file mode 100644
index 000000000000..1d07b931f3d8
--- /dev/null
+++ b/sound/soc/soc-utils.c
@@ -0,0 +1,74 @@
1/*
2 * soc-util.c -- ALSA SoC Audio Layer utility functions
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * Liam Girdwood <lrg@slimlogic.co.uk>
8 *
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; either version 2 of the License, or (at your
13 * option) any later version.
14 */
15
16#include <sound/core.h>
17#include <sound/pcm.h>
18#include <sound/pcm_params.h>
19#include <sound/soc.h>
20
21int snd_soc_calc_frame_size(int sample_size, int channels, int tdm_slots)
22{
23 return sample_size * channels * tdm_slots;
24}
25EXPORT_SYMBOL_GPL(snd_soc_calc_frame_size);
26
27int snd_soc_params_to_frame_size(struct snd_pcm_hw_params *params)
28{
29 int sample_size;
30
31 switch (params_format(params)) {
32 case SNDRV_PCM_FORMAT_S16_LE:
33 case SNDRV_PCM_FORMAT_S16_BE:
34 sample_size = 16;
35 break;
36 case SNDRV_PCM_FORMAT_S20_3LE:
37 case SNDRV_PCM_FORMAT_S20_3BE:
38 sample_size = 20;
39 break;
40 case SNDRV_PCM_FORMAT_S24_LE:
41 case SNDRV_PCM_FORMAT_S24_BE:
42 sample_size = 24;
43 break;
44 case SNDRV_PCM_FORMAT_S32_LE:
45 case SNDRV_PCM_FORMAT_S32_BE:
46 sample_size = 32;
47 break;
48 default:
49 return -ENOTSUPP;
50 }
51
52 return snd_soc_calc_frame_size(sample_size, params_channels(params),
53 1);
54}
55EXPORT_SYMBOL_GPL(snd_soc_params_to_frame_size);
56
57int snd_soc_calc_bclk(int fs, int sample_size, int channels, int tdm_slots)
58{
59 return fs * snd_soc_calc_frame_size(sample_size, channels, tdm_slots);
60}
61EXPORT_SYMBOL_GPL(snd_soc_calc_bclk);
62
63int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
64{
65 int ret;
66
67 ret = snd_soc_params_to_frame_size(params);
68
69 if (ret > 0)
70 return ret * params_rate(params);
71 else
72 return ret;
73}
74EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);