aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/samsung
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/samsung')
-rw-r--r--sound/soc/samsung/ac97.c11
-rw-r--r--sound/soc/samsung/dma.c12
-rw-r--r--sound/soc/samsung/dma.h4
-rw-r--r--sound/soc/samsung/i2s-regs.h51
-rw-r--r--sound/soc/samsung/i2s.c193
-rw-r--r--sound/soc/samsung/pcm.c4
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c4
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c4
-rw-r--r--sound/soc/samsung/smdk_wm8994.c58
-rw-r--r--sound/soc/samsung/spdif.c12
10 files changed, 234 insertions, 119 deletions
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index 2dd623fa3882..2acf987844e8 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -404,18 +404,13 @@ static int s3c_ac97_probe(struct platform_device *pdev)
404 return -ENXIO; 404 return -ENXIO;
405 } 405 }
406 406
407 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
408 if (!mem_res) {
409 dev_err(&pdev->dev, "Unable to get register resource\n");
410 return -ENXIO;
411 }
412
413 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 407 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
414 if (!irq_res) { 408 if (!irq_res) {
415 dev_err(&pdev->dev, "AC97 IRQ not provided!\n"); 409 dev_err(&pdev->dev, "AC97 IRQ not provided!\n");
416 return -ENXIO; 410 return -ENXIO;
417 } 411 }
418 412
413 mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
419 s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); 414 s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res);
420 if (IS_ERR(s3c_ac97.regs)) 415 if (IS_ERR(s3c_ac97.regs))
421 return PTR_ERR(s3c_ac97.regs); 416 return PTR_ERR(s3c_ac97.regs);
@@ -462,7 +457,7 @@ static int s3c_ac97_probe(struct platform_device *pdev)
462 if (ret) 457 if (ret)
463 goto err5; 458 goto err5;
464 459
465 ret = asoc_dma_platform_register(&pdev->dev); 460 ret = samsung_asoc_dma_platform_register(&pdev->dev);
466 if (ret) { 461 if (ret) {
467 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); 462 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
468 goto err6; 463 goto err6;
@@ -485,7 +480,7 @@ static int s3c_ac97_remove(struct platform_device *pdev)
485{ 480{
486 struct resource *irq_res; 481 struct resource *irq_res;
487 482
488 asoc_dma_platform_unregister(&pdev->dev); 483 samsung_asoc_dma_platform_unregister(&pdev->dev);
489 snd_soc_unregister_component(&pdev->dev); 484 snd_soc_unregister_component(&pdev->dev);
490 485
491 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 486 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 21b79262010e..a0c67f60f594 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -176,6 +176,10 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
176 prtd->params->ch = prtd->params->ops->request( 176 prtd->params->ch = prtd->params->ops->request(
177 prtd->params->channel, &req, rtd->cpu_dai->dev, 177 prtd->params->channel, &req, rtd->cpu_dai->dev,
178 prtd->params->ch_name); 178 prtd->params->ch_name);
179 if (!prtd->params->ch) {
180 pr_err("Failed to allocate DMA channel\n");
181 return -ENXIO;
182 }
179 prtd->params->ops->config(prtd->params->ch, &config); 183 prtd->params->ops->config(prtd->params->ch, &config);
180 } 184 }
181 185
@@ -433,17 +437,17 @@ static struct snd_soc_platform_driver samsung_asoc_platform = {
433 .pcm_free = dma_free_dma_buffers, 437 .pcm_free = dma_free_dma_buffers,
434}; 438};
435 439
436int asoc_dma_platform_register(struct device *dev) 440int samsung_asoc_dma_platform_register(struct device *dev)
437{ 441{
438 return snd_soc_register_platform(dev, &samsung_asoc_platform); 442 return snd_soc_register_platform(dev, &samsung_asoc_platform);
439} 443}
440EXPORT_SYMBOL_GPL(asoc_dma_platform_register); 444EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_register);
441 445
442void asoc_dma_platform_unregister(struct device *dev) 446void samsung_asoc_dma_platform_unregister(struct device *dev)
443{ 447{
444 snd_soc_unregister_platform(dev); 448 snd_soc_unregister_platform(dev);
445} 449}
446EXPORT_SYMBOL_GPL(asoc_dma_platform_unregister); 450EXPORT_SYMBOL_GPL(samsung_asoc_dma_platform_unregister);
447 451
448MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); 452MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
449MODULE_DESCRIPTION("Samsung ASoC DMA Driver"); 453MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index 189a7a6d5020..0e86315a3eaf 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -22,7 +22,7 @@ struct s3c_dma_params {
22 char *ch_name; 22 char *ch_name;
23}; 23};
24 24
25int asoc_dma_platform_register(struct device *dev); 25int samsung_asoc_dma_platform_register(struct device *dev);
26void asoc_dma_platform_unregister(struct device *dev); 26void samsung_asoc_dma_platform_unregister(struct device *dev);
27 27
28#endif 28#endif
diff --git a/sound/soc/samsung/i2s-regs.h b/sound/soc/samsung/i2s-regs.h
index c0e6d9a19efc..821a50231002 100644
--- a/sound/soc/samsung/i2s-regs.h
+++ b/sound/soc/samsung/i2s-regs.h
@@ -31,6 +31,10 @@
31#define I2SLVL1ADDR 0x34 31#define I2SLVL1ADDR 0x34
32#define I2SLVL2ADDR 0x38 32#define I2SLVL2ADDR 0x38
33#define I2SLVL3ADDR 0x3c 33#define I2SLVL3ADDR 0x3c
34#define I2SSTR1 0x40
35#define I2SVER 0x44
36#define I2SFIC2 0x48
37#define I2STDM 0x4c
34 38
35#define CON_RSTCLR (1 << 31) 39#define CON_RSTCLR (1 << 31)
36#define CON_FRXOFSTATUS (1 << 26) 40#define CON_FRXOFSTATUS (1 << 26)
@@ -95,24 +99,39 @@
95#define MOD_RXONLY (1 << 8) 99#define MOD_RXONLY (1 << 8)
96#define MOD_TXRX (2 << 8) 100#define MOD_TXRX (2 << 8)
97#define MOD_MASK (3 << 8) 101#define MOD_MASK (3 << 8)
98#define MOD_LR_LLOW (0 << 7) 102#define MOD_LRP_SHIFT 7
99#define MOD_LR_RLOW (1 << 7) 103#define MOD_LR_LLOW 0
100#define MOD_SDF_IIS (0 << 5) 104#define MOD_LR_RLOW 1
101#define MOD_SDF_MSB (1 << 5) 105#define MOD_SDF_SHIFT 5
102#define MOD_SDF_LSB (2 << 5) 106#define MOD_SDF_IIS 0
103#define MOD_SDF_MASK (3 << 5) 107#define MOD_SDF_MSB 1
104#define MOD_RCLK_256FS (0 << 3) 108#define MOD_SDF_LSB 2
105#define MOD_RCLK_512FS (1 << 3) 109#define MOD_SDF_MASK 3
106#define MOD_RCLK_384FS (2 << 3) 110#define MOD_RCLK_SHIFT 3
107#define MOD_RCLK_768FS (3 << 3) 111#define MOD_RCLK_256FS 0
108#define MOD_RCLK_MASK (3 << 3) 112#define MOD_RCLK_512FS 1
109#define MOD_BCLK_32FS (0 << 1) 113#define MOD_RCLK_384FS 2
110#define MOD_BCLK_48FS (1 << 1) 114#define MOD_RCLK_768FS 3
111#define MOD_BCLK_16FS (2 << 1) 115#define MOD_RCLK_MASK 3
112#define MOD_BCLK_24FS (3 << 1) 116#define MOD_BCLK_SHIFT 1
113#define MOD_BCLK_MASK (3 << 1) 117#define MOD_BCLK_32FS 0
118#define MOD_BCLK_48FS 1
119#define MOD_BCLK_16FS 2
120#define MOD_BCLK_24FS 3
121#define MOD_BCLK_MASK 3
114#define MOD_8BIT (1 << 0) 122#define MOD_8BIT (1 << 0)
115 123
124#define EXYNOS5420_MOD_LRP_SHIFT 15
125#define EXYNOS5420_MOD_SDF_SHIFT 6
126#define EXYNOS5420_MOD_RCLK_SHIFT 4
127#define EXYNOS5420_MOD_BCLK_SHIFT 0
128#define EXYNOS5420_MOD_BCLK_64FS 4
129#define EXYNOS5420_MOD_BCLK_96FS 5
130#define EXYNOS5420_MOD_BCLK_128FS 6
131#define EXYNOS5420_MOD_BCLK_192FS 7
132#define EXYNOS5420_MOD_BCLK_256FS 8
133#define EXYNOS5420_MOD_BCLK_MASK 0xf
134
116#define MOD_CDCLKCON (1 << 12) 135#define MOD_CDCLKCON (1 << 12)
117 136
118#define PSR_PSREN (1 << 15) 137#define PSR_PSREN (1 << 15)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 959c702235c8..b302f3b7a587 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -40,6 +40,7 @@ enum samsung_dai_type {
40 40
41struct samsung_i2s_dai_data { 41struct samsung_i2s_dai_data {
42 int dai_type; 42 int dai_type;
43 u32 quirks;
43}; 44};
44 45
45struct i2s_dai { 46struct i2s_dai {
@@ -198,7 +199,13 @@ static inline bool is_manager(struct i2s_dai *i2s)
198/* Read RCLK of I2S (in multiples of LRCLK) */ 199/* Read RCLK of I2S (in multiples of LRCLK) */
199static inline unsigned get_rfs(struct i2s_dai *i2s) 200static inline unsigned get_rfs(struct i2s_dai *i2s)
200{ 201{
201 u32 rfs = (readl(i2s->addr + I2SMOD) >> 3) & 0x3; 202 u32 rfs;
203
204 if (i2s->quirks & QUIRK_SUPPORTS_TDM)
205 rfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_RCLK_SHIFT;
206 else
207 rfs = (readl(i2s->addr + I2SMOD) >> MOD_RCLK_SHIFT);
208 rfs &= MOD_RCLK_MASK;
202 209
203 switch (rfs) { 210 switch (rfs) {
204 case 3: return 768; 211 case 3: return 768;
@@ -212,21 +219,26 @@ static inline unsigned get_rfs(struct i2s_dai *i2s)
212static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs) 219static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
213{ 220{
214 u32 mod = readl(i2s->addr + I2SMOD); 221 u32 mod = readl(i2s->addr + I2SMOD);
222 int rfs_shift;
215 223
216 mod &= ~MOD_RCLK_MASK; 224 if (i2s->quirks & QUIRK_SUPPORTS_TDM)
225 rfs_shift = EXYNOS5420_MOD_RCLK_SHIFT;
226 else
227 rfs_shift = MOD_RCLK_SHIFT;
228 mod &= ~(MOD_RCLK_MASK << rfs_shift);
217 229
218 switch (rfs) { 230 switch (rfs) {
219 case 768: 231 case 768:
220 mod |= MOD_RCLK_768FS; 232 mod |= (MOD_RCLK_768FS << rfs_shift);
221 break; 233 break;
222 case 512: 234 case 512:
223 mod |= MOD_RCLK_512FS; 235 mod |= (MOD_RCLK_512FS << rfs_shift);
224 break; 236 break;
225 case 384: 237 case 384:
226 mod |= MOD_RCLK_384FS; 238 mod |= (MOD_RCLK_384FS << rfs_shift);
227 break; 239 break;
228 default: 240 default:
229 mod |= MOD_RCLK_256FS; 241 mod |= (MOD_RCLK_256FS << rfs_shift);
230 break; 242 break;
231 } 243 }
232 244
@@ -236,9 +248,22 @@ static inline void set_rfs(struct i2s_dai *i2s, unsigned rfs)
236/* Read Bit-Clock of I2S (in multiples of LRCLK) */ 248/* Read Bit-Clock of I2S (in multiples of LRCLK) */
237static inline unsigned get_bfs(struct i2s_dai *i2s) 249static inline unsigned get_bfs(struct i2s_dai *i2s)
238{ 250{
239 u32 bfs = (readl(i2s->addr + I2SMOD) >> 1) & 0x3; 251 u32 bfs;
252
253 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
254 bfs = readl(i2s->addr + I2SMOD) >> EXYNOS5420_MOD_BCLK_SHIFT;
255 bfs &= EXYNOS5420_MOD_BCLK_MASK;
256 } else {
257 bfs = readl(i2s->addr + I2SMOD) >> MOD_BCLK_SHIFT;
258 bfs &= MOD_BCLK_MASK;
259 }
240 260
241 switch (bfs) { 261 switch (bfs) {
262 case 8: return 256;
263 case 7: return 192;
264 case 6: return 128;
265 case 5: return 96;
266 case 4: return 64;
242 case 3: return 24; 267 case 3: return 24;
243 case 2: return 16; 268 case 2: return 16;
244 case 1: return 48; 269 case 1: return 48;
@@ -250,21 +275,50 @@ static inline unsigned get_bfs(struct i2s_dai *i2s)
250static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs) 275static inline void set_bfs(struct i2s_dai *i2s, unsigned bfs)
251{ 276{
252 u32 mod = readl(i2s->addr + I2SMOD); 277 u32 mod = readl(i2s->addr + I2SMOD);
278 int bfs_shift;
279 int tdm = i2s->quirks & QUIRK_SUPPORTS_TDM;
253 280
254 mod &= ~MOD_BCLK_MASK; 281 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
282 bfs_shift = EXYNOS5420_MOD_BCLK_SHIFT;
283 mod &= ~(EXYNOS5420_MOD_BCLK_MASK << bfs_shift);
284 } else {
285 bfs_shift = MOD_BCLK_SHIFT;
286 mod &= ~(MOD_BCLK_MASK << bfs_shift);
287 }
288
289 /* Non-TDM I2S controllers do not support BCLK > 48 * FS */
290 if (!tdm && bfs > 48) {
291 dev_err(&i2s->pdev->dev, "Unsupported BCLK divider\n");
292 return;
293 }
255 294
256 switch (bfs) { 295 switch (bfs) {
257 case 48: 296 case 48:
258 mod |= MOD_BCLK_48FS; 297 mod |= (MOD_BCLK_48FS << bfs_shift);
259 break; 298 break;
260 case 32: 299 case 32:
261 mod |= MOD_BCLK_32FS; 300 mod |= (MOD_BCLK_32FS << bfs_shift);
262 break; 301 break;
263 case 24: 302 case 24:
264 mod |= MOD_BCLK_24FS; 303 mod |= (MOD_BCLK_24FS << bfs_shift);
265 break; 304 break;
266 case 16: 305 case 16:
267 mod |= MOD_BCLK_16FS; 306 mod |= (MOD_BCLK_16FS << bfs_shift);
307 break;
308 case 64:
309 mod |= (EXYNOS5420_MOD_BCLK_64FS << bfs_shift);
310 break;
311 case 96:
312 mod |= (EXYNOS5420_MOD_BCLK_96FS << bfs_shift);
313 break;
314 case 128:
315 mod |= (EXYNOS5420_MOD_BCLK_128FS << bfs_shift);
316 break;
317 case 192:
318 mod |= (EXYNOS5420_MOD_BCLK_192FS << bfs_shift);
319 break;
320 case 256:
321 mod |= (EXYNOS5420_MOD_BCLK_256FS << bfs_shift);
268 break; 322 break;
269 default: 323 default:
270 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n"); 324 dev_err(&i2s->pdev->dev, "Wrong BCLK Divider!\n");
@@ -491,20 +545,32 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
491{ 545{
492 struct i2s_dai *i2s = to_info(dai); 546 struct i2s_dai *i2s = to_info(dai);
493 u32 mod = readl(i2s->addr + I2SMOD); 547 u32 mod = readl(i2s->addr + I2SMOD);
548 int lrp_shift, sdf_shift, sdf_mask, lrp_rlow;
494 u32 tmp = 0; 549 u32 tmp = 0;
495 550
551 if (i2s->quirks & QUIRK_SUPPORTS_TDM) {
552 lrp_shift = EXYNOS5420_MOD_LRP_SHIFT;
553 sdf_shift = EXYNOS5420_MOD_SDF_SHIFT;
554 } else {
555 lrp_shift = MOD_LRP_SHIFT;
556 sdf_shift = MOD_SDF_SHIFT;
557 }
558
559 sdf_mask = MOD_SDF_MASK << sdf_shift;
560 lrp_rlow = MOD_LR_RLOW << lrp_shift;
561
496 /* Format is priority */ 562 /* Format is priority */
497 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 563 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
498 case SND_SOC_DAIFMT_RIGHT_J: 564 case SND_SOC_DAIFMT_RIGHT_J:
499 tmp |= MOD_LR_RLOW; 565 tmp |= lrp_rlow;
500 tmp |= MOD_SDF_MSB; 566 tmp |= (MOD_SDF_MSB << sdf_shift);
501 break; 567 break;
502 case SND_SOC_DAIFMT_LEFT_J: 568 case SND_SOC_DAIFMT_LEFT_J:
503 tmp |= MOD_LR_RLOW; 569 tmp |= lrp_rlow;
504 tmp |= MOD_SDF_LSB; 570 tmp |= (MOD_SDF_LSB << sdf_shift);
505 break; 571 break;
506 case SND_SOC_DAIFMT_I2S: 572 case SND_SOC_DAIFMT_I2S:
507 tmp |= MOD_SDF_IIS; 573 tmp |= (MOD_SDF_IIS << sdf_shift);
508 break; 574 break;
509 default: 575 default:
510 dev_err(&i2s->pdev->dev, "Format not supported\n"); 576 dev_err(&i2s->pdev->dev, "Format not supported\n");
@@ -519,10 +585,10 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
519 case SND_SOC_DAIFMT_NB_NF: 585 case SND_SOC_DAIFMT_NB_NF:
520 break; 586 break;
521 case SND_SOC_DAIFMT_NB_IF: 587 case SND_SOC_DAIFMT_NB_IF:
522 if (tmp & MOD_LR_RLOW) 588 if (tmp & lrp_rlow)
523 tmp &= ~MOD_LR_RLOW; 589 tmp &= ~lrp_rlow;
524 else 590 else
525 tmp |= MOD_LR_RLOW; 591 tmp |= lrp_rlow;
526 break; 592 break;
527 default: 593 default:
528 dev_err(&i2s->pdev->dev, "Polarity not supported\n"); 594 dev_err(&i2s->pdev->dev, "Polarity not supported\n");
@@ -544,15 +610,18 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
544 return -EINVAL; 610 return -EINVAL;
545 } 611 }
546 612
613 /*
614 * Don't change the I2S mode if any controller is active on this
615 * channel.
616 */
547 if (any_active(i2s) && 617 if (any_active(i2s) &&
548 ((mod & (MOD_SDF_MASK | MOD_LR_RLOW 618 ((mod & (sdf_mask | lrp_rlow | MOD_SLAVE)) != tmp)) {
549 | MOD_SLAVE)) != tmp)) {
550 dev_err(&i2s->pdev->dev, 619 dev_err(&i2s->pdev->dev,
551 "%s:%d Other DAI busy\n", __func__, __LINE__); 620 "%s:%d Other DAI busy\n", __func__, __LINE__);
552 return -EAGAIN; 621 return -EAGAIN;
553 } 622 }
554 623
555 mod &= ~(MOD_SDF_MASK | MOD_LR_RLOW | MOD_SLAVE); 624 mod &= ~(sdf_mask | lrp_rlow | MOD_SLAVE);
556 mod |= tmp; 625 mod |= tmp;
557 writel(mod, i2s->addr + I2SMOD); 626 writel(mod, i2s->addr + I2SMOD);
558 627
@@ -1007,6 +1076,8 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
1007 if (IS_ERR(i2s->pdev)) 1076 if (IS_ERR(i2s->pdev))
1008 return NULL; 1077 return NULL;
1009 1078
1079 i2s->pdev->dev.parent = &pdev->dev;
1080
1010 platform_set_drvdata(i2s->pdev, i2s); 1081 platform_set_drvdata(i2s->pdev, i2s);
1011 ret = platform_device_add(i2s->pdev); 1082 ret = platform_device_add(i2s->pdev);
1012 if (ret < 0) 1083 if (ret < 0)
@@ -1018,18 +1089,18 @@ static struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
1018 1089
1019static const struct of_device_id exynos_i2s_match[]; 1090static const struct of_device_id exynos_i2s_match[];
1020 1091
1021static inline int samsung_i2s_get_driver_data(struct platform_device *pdev) 1092static inline const struct samsung_i2s_dai_data *samsung_i2s_get_driver_data(
1093 struct platform_device *pdev)
1022{ 1094{
1023#ifdef CONFIG_OF 1095#ifdef CONFIG_OF
1024 struct samsung_i2s_dai_data *data;
1025 if (pdev->dev.of_node) { 1096 if (pdev->dev.of_node) {
1026 const struct of_device_id *match; 1097 const struct of_device_id *match;
1027 match = of_match_node(exynos_i2s_match, pdev->dev.of_node); 1098 match = of_match_node(exynos_i2s_match, pdev->dev.of_node);
1028 data = (struct samsung_i2s_dai_data *) match->data; 1099 return match->data;
1029 return data->dai_type;
1030 } else 1100 } else
1031#endif 1101#endif
1032 return platform_get_device_id(pdev)->driver_data; 1102 return (struct samsung_i2s_dai_data *)
1103 platform_get_device_id(pdev)->driver_data;
1033} 1104}
1034 1105
1035#ifdef CONFIG_PM_RUNTIME 1106#ifdef CONFIG_PM_RUNTIME
@@ -1060,13 +1131,13 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1060 struct resource *res; 1131 struct resource *res;
1061 u32 regs_base, quirks = 0, idma_addr = 0; 1132 u32 regs_base, quirks = 0, idma_addr = 0;
1062 struct device_node *np = pdev->dev.of_node; 1133 struct device_node *np = pdev->dev.of_node;
1063 enum samsung_dai_type samsung_dai_type; 1134 const struct samsung_i2s_dai_data *i2s_dai_data;
1064 int ret = 0; 1135 int ret = 0;
1065 1136
1066 /* Call during Seconday interface registration */ 1137 /* Call during Seconday interface registration */
1067 samsung_dai_type = samsung_i2s_get_driver_data(pdev); 1138 i2s_dai_data = samsung_i2s_get_driver_data(pdev);
1068 1139
1069 if (samsung_dai_type == TYPE_SEC) { 1140 if (i2s_dai_data->dai_type == TYPE_SEC) {
1070 sec_dai = dev_get_drvdata(&pdev->dev); 1141 sec_dai = dev_get_drvdata(&pdev->dev);
1071 if (!sec_dai) { 1142 if (!sec_dai) {
1072 dev_err(&pdev->dev, "Unable to get drvdata\n"); 1143 dev_err(&pdev->dev, "Unable to get drvdata\n");
@@ -1075,7 +1146,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1075 snd_soc_register_component(&sec_dai->pdev->dev, 1146 snd_soc_register_component(&sec_dai->pdev->dev,
1076 &samsung_i2s_component, 1147 &samsung_i2s_component,
1077 &sec_dai->i2s_dai_drv, 1); 1148 &sec_dai->i2s_dai_drv, 1);
1078 asoc_dma_platform_register(&pdev->dev); 1149 samsung_asoc_dma_platform_register(&pdev->dev);
1079 return 0; 1150 return 0;
1080 } 1151 }
1081 1152
@@ -1115,15 +1186,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1115 idma_addr = i2s_cfg->idma_addr; 1186 idma_addr = i2s_cfg->idma_addr;
1116 } 1187 }
1117 } else { 1188 } else {
1118 if (of_find_property(np, "samsung,supports-6ch", NULL)) 1189 quirks = i2s_dai_data->quirks;
1119 quirks |= QUIRK_PRI_6CHAN;
1120
1121 if (of_find_property(np, "samsung,supports-secdai", NULL))
1122 quirks |= QUIRK_SEC_DAI;
1123
1124 if (of_find_property(np, "samsung,supports-rstclr", NULL))
1125 quirks |= QUIRK_NEED_RSTCLR;
1126
1127 if (of_property_read_u32(np, "samsung,idma-addr", 1190 if (of_property_read_u32(np, "samsung,idma-addr",
1128 &idma_addr)) { 1191 &idma_addr)) {
1129 if (quirks & QUIRK_SEC_DAI) { 1192 if (quirks & QUIRK_SEC_DAI) {
@@ -1200,7 +1263,7 @@ static int samsung_i2s_probe(struct platform_device *pdev)
1200 1263
1201 pm_runtime_enable(&pdev->dev); 1264 pm_runtime_enable(&pdev->dev);
1202 1265
1203 asoc_dma_platform_register(&pdev->dev); 1266 samsung_asoc_dma_platform_register(&pdev->dev);
1204 1267
1205 return 0; 1268 return 0;
1206err: 1269err:
@@ -1230,33 +1293,59 @@ static int samsung_i2s_remove(struct platform_device *pdev)
1230 i2s->pri_dai = NULL; 1293 i2s->pri_dai = NULL;
1231 i2s->sec_dai = NULL; 1294 i2s->sec_dai = NULL;
1232 1295
1233 asoc_dma_platform_unregister(&pdev->dev); 1296 samsung_asoc_dma_platform_unregister(&pdev->dev);
1234 snd_soc_unregister_component(&pdev->dev); 1297 snd_soc_unregister_component(&pdev->dev);
1235 1298
1236 return 0; 1299 return 0;
1237} 1300}
1238 1301
1302static const struct samsung_i2s_dai_data i2sv3_dai_type = {
1303 .dai_type = TYPE_PRI,
1304 .quirks = QUIRK_NO_MUXPSR,
1305};
1306
1307static const struct samsung_i2s_dai_data i2sv5_dai_type = {
1308 .dai_type = TYPE_PRI,
1309 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR,
1310};
1311
1312static const struct samsung_i2s_dai_data i2sv6_dai_type = {
1313 .dai_type = TYPE_PRI,
1314 .quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI | QUIRK_NEED_RSTCLR |
1315 QUIRK_SUPPORTS_TDM,
1316};
1317
1318static const struct samsung_i2s_dai_data samsung_dai_type_pri = {
1319 .dai_type = TYPE_PRI,
1320};
1321
1322static const struct samsung_i2s_dai_data samsung_dai_type_sec = {
1323 .dai_type = TYPE_SEC,
1324};
1325
1239static struct platform_device_id samsung_i2s_driver_ids[] = { 1326static struct platform_device_id samsung_i2s_driver_ids[] = {
1240 { 1327 {
1241 .name = "samsung-i2s", 1328 .name = "samsung-i2s",
1242 .driver_data = TYPE_PRI, 1329 .driver_data = (kernel_ulong_t)&samsung_dai_type_pri,
1243 }, { 1330 }, {
1244 .name = "samsung-i2s-sec", 1331 .name = "samsung-i2s-sec",
1245 .driver_data = TYPE_SEC, 1332 .driver_data = (kernel_ulong_t)&samsung_dai_type_sec,
1246 }, 1333 },
1247 {}, 1334 {},
1248}; 1335};
1249MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids); 1336MODULE_DEVICE_TABLE(platform, samsung_i2s_driver_ids);
1250 1337
1251#ifdef CONFIG_OF 1338#ifdef CONFIG_OF
1252static struct samsung_i2s_dai_data samsung_i2s_dai_data_array[] = {
1253 [TYPE_PRI] = { TYPE_PRI },
1254 [TYPE_SEC] = { TYPE_SEC },
1255};
1256
1257static const struct of_device_id exynos_i2s_match[] = { 1339static const struct of_device_id exynos_i2s_match[] = {
1258 { .compatible = "samsung,i2s-v5", 1340 {
1259 .data = &samsung_i2s_dai_data_array[TYPE_PRI], 1341 .compatible = "samsung,s3c6410-i2s",
1342 .data = &i2sv3_dai_type,
1343 }, {
1344 .compatible = "samsung,s5pv210-i2s",
1345 .data = &i2sv5_dai_type,
1346 }, {
1347 .compatible = "samsung,exynos5420-i2s",
1348 .data = &i2sv6_dai_type,
1260 }, 1349 },
1261 {}, 1350 {},
1262}; 1351};
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 1566afe9ef52..e54256fc4b2c 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -594,7 +594,7 @@ static int s3c_pcm_dev_probe(struct platform_device *pdev)
594 goto err5; 594 goto err5;
595 } 595 }
596 596
597 ret = asoc_dma_platform_register(&pdev->dev); 597 ret = samsung_asoc_dma_platform_register(&pdev->dev);
598 if (ret) { 598 if (ret) {
599 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret); 599 dev_err(&pdev->dev, "failed to get register DMA: %d\n", ret);
600 goto err6; 600 goto err6;
@@ -623,7 +623,7 @@ static int s3c_pcm_dev_remove(struct platform_device *pdev)
623 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id]; 623 struct s3c_pcm_info *pcm = &s3c_pcm[pdev->id];
624 struct resource *mem_res; 624 struct resource *mem_res;
625 625
626 asoc_dma_platform_unregister(&pdev->dev); 626 samsung_asoc_dma_platform_unregister(&pdev->dev);
627 snd_soc_unregister_component(&pdev->dev); 627 snd_soc_unregister_component(&pdev->dev);
628 628
629 pm_runtime_disable(&pdev->dev); 629 pm_runtime_disable(&pdev->dev);
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 47e23864ea72..ea885cb9f76c 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -176,7 +176,7 @@ static int s3c2412_iis_dev_probe(struct platform_device *pdev)
176 return ret; 176 return ret;
177 } 177 }
178 178
179 ret = asoc_dma_platform_register(&pdev->dev); 179 ret = samsung_asoc_dma_platform_register(&pdev->dev);
180 if (ret) { 180 if (ret) {
181 pr_err("failed to register the DMA: %d\n", ret); 181 pr_err("failed to register the DMA: %d\n", ret);
182 goto err; 182 goto err;
@@ -190,7 +190,7 @@ err:
190 190
191static int s3c2412_iis_dev_remove(struct platform_device *pdev) 191static int s3c2412_iis_dev_remove(struct platform_device *pdev)
192{ 192{
193 asoc_dma_platform_unregister(&pdev->dev); 193 samsung_asoc_dma_platform_unregister(&pdev->dev);
194 snd_soc_unregister_component(&pdev->dev); 194 snd_soc_unregister_component(&pdev->dev);
195 return 0; 195 return 0;
196} 196}
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 8b3414551a62..9c8ebd872fac 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -480,7 +480,7 @@ static int s3c24xx_iis_dev_probe(struct platform_device *pdev)
480 return ret; 480 return ret;
481 } 481 }
482 482
483 ret = asoc_dma_platform_register(&pdev->dev); 483 ret = samsung_asoc_dma_platform_register(&pdev->dev);
484 if (ret) { 484 if (ret) {
485 pr_err("failed to register the dma: %d\n", ret); 485 pr_err("failed to register the dma: %d\n", ret);
486 goto err; 486 goto err;
@@ -494,7 +494,7 @@ err:
494 494
495static int s3c24xx_iis_dev_remove(struct platform_device *pdev) 495static int s3c24xx_iis_dev_remove(struct platform_device *pdev)
496{ 496{
497 asoc_dma_platform_unregister(&pdev->dev); 497 samsung_asoc_dma_platform_unregister(&pdev->dev);
498 snd_soc_unregister_component(&pdev->dev); 498 snd_soc_unregister_component(&pdev->dev);
499 return 0; 499 return 0;
500} 500}
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 581ea4a06fc6..5fd7a05a9b9e 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -11,6 +11,7 @@
11#include <sound/pcm_params.h> 11#include <sound/pcm_params.h>
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/of.h> 13#include <linux/of.h>
14#include <linux/of_device.h>
14 15
15 /* 16 /*
16 * Default CFG switch settings to use this driver: 17 * Default CFG switch settings to use this driver:
@@ -37,11 +38,19 @@
37/* SMDK has a 16.934MHZ crystal attached to WM8994 */ 38/* SMDK has a 16.934MHZ crystal attached to WM8994 */
38#define SMDK_WM8994_FREQ 16934000 39#define SMDK_WM8994_FREQ 16934000
39 40
41struct smdk_wm8994_data {
42 int mclk1_rate;
43};
44
45/* Default SMDKs */
46static struct smdk_wm8994_data smdk_board_data = {
47 .mclk1_rate = SMDK_WM8994_FREQ,
48};
49
40static int smdk_hw_params(struct snd_pcm_substream *substream, 50static int smdk_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params) 51 struct snd_pcm_hw_params *params)
42{ 52{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data; 53 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
45 struct snd_soc_dai *codec_dai = rtd->codec_dai; 54 struct snd_soc_dai *codec_dai = rtd->codec_dai;
46 unsigned int pll_out; 55 unsigned int pll_out;
47 int ret; 56 int ret;
@@ -54,18 +63,6 @@ static int smdk_hw_params(struct snd_pcm_substream *substream,
54 else 63 else
55 pll_out = params_rate(params) * 256; 64 pll_out = params_rate(params) * 256;
56 65
57 ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
58 | SND_SOC_DAIFMT_NB_NF
59 | SND_SOC_DAIFMT_CBM_CFM);
60 if (ret < 0)
61 return ret;
62
63 ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
64 | SND_SOC_DAIFMT_NB_NF
65 | SND_SOC_DAIFMT_CBM_CFM);
66 if (ret < 0)
67 return ret;
68
69 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1, 66 ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1, WM8994_FLL_SRC_MCLK1,
70 SMDK_WM8994_FREQ, pll_out); 67 SMDK_WM8994_FREQ, pll_out);
71 if (ret < 0) 68 if (ret < 0)
@@ -131,6 +128,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
131 .platform_name = "samsung-i2s.0", 128 .platform_name = "samsung-i2s.0",
132 .codec_name = "wm8994-codec", 129 .codec_name = "wm8994-codec",
133 .init = smdk_wm8994_init_paiftx, 130 .init = smdk_wm8994_init_paiftx,
131 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
132 SND_SOC_DAIFMT_CBM_CFM,
134 .ops = &smdk_ops, 133 .ops = &smdk_ops,
135 }, { /* Sec_Fifo Playback i/f */ 134 }, { /* Sec_Fifo Playback i/f */
136 .name = "Sec_FIFO TX", 135 .name = "Sec_FIFO TX",
@@ -139,6 +138,8 @@ static struct snd_soc_dai_link smdk_dai[] = {
139 .codec_dai_name = "wm8994-aif1", 138 .codec_dai_name = "wm8994-aif1",
140 .platform_name = "samsung-i2s-sec", 139 .platform_name = "samsung-i2s-sec",
141 .codec_name = "wm8994-codec", 140 .codec_name = "wm8994-codec",
141 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
142 SND_SOC_DAIFMT_CBM_CFM,
142 .ops = &smdk_ops, 143 .ops = &smdk_ops,
143 }, 144 },
144}; 145};
@@ -150,15 +151,28 @@ static struct snd_soc_card smdk = {
150 .num_links = ARRAY_SIZE(smdk_dai), 151 .num_links = ARRAY_SIZE(smdk_dai),
151}; 152};
152 153
154#ifdef CONFIG_OF
155static const struct of_device_id samsung_wm8994_of_match[] = {
156 { .compatible = "samsung,smdk-wm8994", .data = &smdk_board_data },
157 {},
158};
159MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
160#endif /* CONFIG_OF */
153 161
154static int smdk_audio_probe(struct platform_device *pdev) 162static int smdk_audio_probe(struct platform_device *pdev)
155{ 163{
156 int ret; 164 int ret;
157 struct device_node *np = pdev->dev.of_node; 165 struct device_node *np = pdev->dev.of_node;
158 struct snd_soc_card *card = &smdk; 166 struct snd_soc_card *card = &smdk;
167 struct smdk_wm8994_data *board;
168 const struct of_device_id *id;
159 169
160 card->dev = &pdev->dev; 170 card->dev = &pdev->dev;
161 171
172 board = devm_kzalloc(&pdev->dev, sizeof(*board), GFP_KERNEL);
173 if (!board)
174 return -ENOMEM;
175
162 if (np) { 176 if (np) {
163 smdk_dai[0].cpu_dai_name = NULL; 177 smdk_dai[0].cpu_dai_name = NULL;
164 smdk_dai[0].cpu_of_node = of_parse_phandle(np, 178 smdk_dai[0].cpu_of_node = of_parse_phandle(np,
@@ -173,6 +187,12 @@ static int smdk_audio_probe(struct platform_device *pdev)
173 smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node; 187 smdk_dai[0].platform_of_node = smdk_dai[0].cpu_of_node;
174 } 188 }
175 189
190 id = of_match_device(samsung_wm8994_of_match, &pdev->dev);
191 if (id)
192 *board = *((struct smdk_wm8994_data *)id->data);
193
194 platform_set_drvdata(pdev, board);
195
176 ret = snd_soc_register_card(card); 196 ret = snd_soc_register_card(card);
177 197
178 if (ret) 198 if (ret)
@@ -190,17 +210,9 @@ static int smdk_audio_remove(struct platform_device *pdev)
190 return 0; 210 return 0;
191} 211}
192 212
193#ifdef CONFIG_OF
194static const struct of_device_id samsung_wm8994_of_match[] = {
195 { .compatible = "samsung,smdk-wm8994", },
196 {},
197};
198MODULE_DEVICE_TABLE(of, samsung_wm8994_of_match);
199#endif /* CONFIG_OF */
200
201static struct platform_driver smdk_audio_driver = { 213static struct platform_driver smdk_audio_driver = {
202 .driver = { 214 .driver = {
203 .name = "smdk-audio", 215 .name = "smdk-audio-wm8894",
204 .owner = THIS_MODULE, 216 .owner = THIS_MODULE,
205 .of_match_table = of_match_ptr(samsung_wm8994_of_match), 217 .of_match_table = of_match_ptr(samsung_wm8994_of_match),
206 }, 218 },
@@ -212,4 +224,4 @@ module_platform_driver(smdk_audio_driver);
212 224
213MODULE_DESCRIPTION("ALSA SoC SMDK WM8994"); 225MODULE_DESCRIPTION("ALSA SoC SMDK WM8994");
214MODULE_LICENSE("GPL"); 226MODULE_LICENSE("GPL");
215MODULE_ALIAS("platform:smdk-audio"); 227MODULE_ALIAS("platform:smdk-audio-wm8994");
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 2e5ebb2f1982..28487dcc4538 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -395,7 +395,7 @@ static int spdif_probe(struct platform_device *pdev)
395 395
396 spin_lock_init(&spdif->lock); 396 spin_lock_init(&spdif->lock);
397 397
398 spdif->pclk = clk_get(&pdev->dev, "spdif"); 398 spdif->pclk = devm_clk_get(&pdev->dev, "spdif");
399 if (IS_ERR(spdif->pclk)) { 399 if (IS_ERR(spdif->pclk)) {
400 dev_err(&pdev->dev, "failed to get peri-clock\n"); 400 dev_err(&pdev->dev, "failed to get peri-clock\n");
401 ret = -ENOENT; 401 ret = -ENOENT;
@@ -403,7 +403,7 @@ static int spdif_probe(struct platform_device *pdev)
403 } 403 }
404 clk_prepare_enable(spdif->pclk); 404 clk_prepare_enable(spdif->pclk);
405 405
406 spdif->sclk = clk_get(&pdev->dev, "sclk_spdif"); 406 spdif->sclk = devm_clk_get(&pdev->dev, "sclk_spdif");
407 if (IS_ERR(spdif->sclk)) { 407 if (IS_ERR(spdif->sclk)) {
408 dev_err(&pdev->dev, "failed to get internal source clock\n"); 408 dev_err(&pdev->dev, "failed to get internal source clock\n");
409 ret = -ENOENT; 409 ret = -ENOENT;
@@ -442,7 +442,7 @@ static int spdif_probe(struct platform_device *pdev)
442 442
443 spdif->dma_playback = &spdif_stereo_out; 443 spdif->dma_playback = &spdif_stereo_out;
444 444
445 ret = asoc_dma_platform_register(&pdev->dev); 445 ret = samsung_asoc_dma_platform_register(&pdev->dev);
446 if (ret) { 446 if (ret) {
447 dev_err(&pdev->dev, "failed to register DMA: %d\n", ret); 447 dev_err(&pdev->dev, "failed to register DMA: %d\n", ret);
448 goto err5; 448 goto err5;
@@ -457,10 +457,8 @@ err3:
457 release_mem_region(mem_res->start, resource_size(mem_res)); 457 release_mem_region(mem_res->start, resource_size(mem_res));
458err2: 458err2:
459 clk_disable_unprepare(spdif->sclk); 459 clk_disable_unprepare(spdif->sclk);
460 clk_put(spdif->sclk);
461err1: 460err1:
462 clk_disable_unprepare(spdif->pclk); 461 clk_disable_unprepare(spdif->pclk);
463 clk_put(spdif->pclk);
464err0: 462err0:
465 return ret; 463 return ret;
466} 464}
@@ -470,7 +468,7 @@ static int spdif_remove(struct platform_device *pdev)
470 struct samsung_spdif_info *spdif = &spdif_info; 468 struct samsung_spdif_info *spdif = &spdif_info;
471 struct resource *mem_res; 469 struct resource *mem_res;
472 470
473 asoc_dma_platform_unregister(&pdev->dev); 471 samsung_asoc_dma_platform_unregister(&pdev->dev);
474 snd_soc_unregister_component(&pdev->dev); 472 snd_soc_unregister_component(&pdev->dev);
475 473
476 iounmap(spdif->regs); 474 iounmap(spdif->regs);
@@ -480,9 +478,7 @@ static int spdif_remove(struct platform_device *pdev)
480 release_mem_region(mem_res->start, resource_size(mem_res)); 478 release_mem_region(mem_res->start, resource_size(mem_res));
481 479
482 clk_disable_unprepare(spdif->sclk); 480 clk_disable_unprepare(spdif->sclk);
483 clk_put(spdif->sclk);
484 clk_disable_unprepare(spdif->pclk); 481 clk_disable_unprepare(spdif->pclk);
485 clk_put(spdif->pclk);
486 482
487 return 0; 483 return 0;
488} 484}