aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/imx/imx-ssi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/imx/imx-ssi.c')
-rw-r--r--sound/soc/imx/imx-ssi.c148
1 files changed, 67 insertions, 81 deletions
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 50f51624c535..02a3e7c799d8 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -61,7 +61,7 @@
61static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 61static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
62 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 62 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
63{ 63{
64 struct imx_ssi *ssi = cpu_dai->private_data; 64 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
65 u32 sccr; 65 u32 sccr;
66 66
67 sccr = readl(ssi->base + SSI_STCCR); 67 sccr = readl(ssi->base + SSI_STCCR);
@@ -86,7 +86,7 @@ static int imx_ssi_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
86 */ 86 */
87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt) 87static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
88{ 88{
89 struct imx_ssi *ssi = cpu_dai->private_data; 89 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
90 u32 strcr = 0, scr; 90 u32 strcr = 0, scr;
91 91
92 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET); 92 scr = readl(ssi->base + SSI_SCR) & ~(SSI_SCR_SYN | SSI_SCR_NET);
@@ -164,7 +164,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
164static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 164static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
165 int clk_id, unsigned int freq, int dir) 165 int clk_id, unsigned int freq, int dir)
166{ 166{
167 struct imx_ssi *ssi = cpu_dai->private_data; 167 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
168 u32 scr; 168 u32 scr;
169 169
170 scr = readl(ssi->base + SSI_SCR); 170 scr = readl(ssi->base + SSI_SCR);
@@ -192,7 +192,7 @@ static int imx_ssi_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
192static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 192static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
193 int div_id, int div) 193 int div_id, int div)
194{ 194{
195 struct imx_ssi *ssi = cpu_dai->private_data; 195 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
196 u32 stccr, srccr; 196 u32 stccr, srccr;
197 197
198 stccr = readl(ssi->base + SSI_STCCR); 198 stccr = readl(ssi->base + SSI_STCCR);
@@ -241,7 +241,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
241 struct snd_pcm_hw_params *params, 241 struct snd_pcm_hw_params *params,
242 struct snd_soc_dai *cpu_dai) 242 struct snd_soc_dai *cpu_dai)
243{ 243{
244 struct imx_ssi *ssi = cpu_dai->private_data; 244 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
245 struct imx_pcm_dma_params *dma_data; 245 struct imx_pcm_dma_params *dma_data;
246 u32 reg, sccr; 246 u32 reg, sccr;
247 247
@@ -279,9 +279,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
279static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, 279static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
280 struct snd_soc_dai *dai) 280 struct snd_soc_dai *dai)
281{ 281{
282 struct snd_soc_pcm_runtime *rtd = substream->private_data; 282 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);
283 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
284 struct imx_ssi *ssi = cpu_dai->private_data;
285 unsigned int sier_bits, sier; 283 unsigned int sier_bits, sier;
286 unsigned int scr; 284 unsigned int scr;
287 285
@@ -350,22 +348,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
350 .trigger = imx_ssi_trigger, 348 .trigger = imx_ssi_trigger,
351}; 349};
352 350
353static struct snd_soc_dai imx_ssi_dai = {
354 .playback = {
355 .channels_min = 2,
356 .channels_max = 2,
357 .rates = SNDRV_PCM_RATE_8000_96000,
358 .formats = SNDRV_PCM_FMTBIT_S16_LE,
359 },
360 .capture = {
361 .channels_min = 2,
362 .channels_max = 2,
363 .rates = SNDRV_PCM_RATE_8000_96000,
364 .formats = SNDRV_PCM_FMTBIT_S16_LE,
365 },
366 .ops = &imx_ssi_pcm_dai_ops,
367};
368
369int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, 351int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
370 struct vm_area_struct *vma) 352 struct vm_area_struct *vma)
371{ 353{
@@ -381,6 +363,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
381 runtime->dma_bytes); 363 runtime->dma_bytes);
382 return ret; 364 return ret;
383} 365}
366EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
384 367
385static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 368static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
386{ 369{
@@ -412,14 +395,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
412 card->dev->dma_mask = &imx_pcm_dmamask; 395 card->dev->dma_mask = &imx_pcm_dmamask;
413 if (!card->dev->coherent_dma_mask) 396 if (!card->dev->coherent_dma_mask)
414 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 397 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
415 if (dai->playback.channels_min) { 398 if (dai->driver->playback.channels_min) {
416 ret = imx_pcm_preallocate_dma_buffer(pcm, 399 ret = imx_pcm_preallocate_dma_buffer(pcm,
417 SNDRV_PCM_STREAM_PLAYBACK); 400 SNDRV_PCM_STREAM_PLAYBACK);
418 if (ret) 401 if (ret)
419 goto out; 402 goto out;
420 } 403 }
421 404
422 if (dai->capture.channels_min) { 405 if (dai->driver->capture.channels_min) {
423 ret = imx_pcm_preallocate_dma_buffer(pcm, 406 ret = imx_pcm_preallocate_dma_buffer(pcm,
424 SNDRV_PCM_STREAM_CAPTURE); 407 SNDRV_PCM_STREAM_CAPTURE);
425 if (ret) 408 if (ret)
@@ -429,6 +412,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
429out: 412out:
430 return ret; 413 return ret;
431} 414}
415EXPORT_SYMBOL_GPL(imx_pcm_new);
432 416
433void imx_pcm_free(struct snd_pcm *pcm) 417void imx_pcm_free(struct snd_pcm *pcm)
434{ 418{
@@ -450,14 +434,40 @@ void imx_pcm_free(struct snd_pcm *pcm)
450 buf->area = NULL; 434 buf->area = NULL;
451 } 435 }
452} 436}
437EXPORT_SYMBOL_GPL(imx_pcm_free);
453 438
454struct snd_soc_platform imx_soc_platform = { 439static struct snd_soc_dai_driver imx_ssi_dai = {
455 .name = "imx-audio", 440 .playback = {
441 .channels_min = 2,
442 .channels_max = 2,
443 .rates = SNDRV_PCM_RATE_8000_96000,
444 .formats = SNDRV_PCM_FMTBIT_S16_LE,
445 },
446 .capture = {
447 .channels_min = 2,
448 .channels_max = 2,
449 .rates = SNDRV_PCM_RATE_8000_96000,
450 .formats = SNDRV_PCM_FMTBIT_S16_LE,
451 },
452 .ops = &imx_ssi_pcm_dai_ops,
456}; 453};
457EXPORT_SYMBOL_GPL(imx_soc_platform);
458 454
459static struct snd_soc_dai imx_ac97_dai = { 455static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
460 .name = "AC97", 456{
457 struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
458 uint32_t val;
459
460 snd_soc_dai_set_drvdata(dai, ssi);
461
462 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
463 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
464 writel(val, ssi->base + SSI_SFCSR);
465
466 return 0;
467}
468
469static struct snd_soc_dai_driver imx_ac97_dai = {
470 .probe = imx_ssi_dai_probe,
461 .ac97_control = 1, 471 .ac97_control = 1,
462 .playback = { 472 .playback = {
463 .stream_name = "AC97 Playback", 473 .stream_name = "AC97 Playback",
@@ -577,25 +587,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
577}; 587};
578EXPORT_SYMBOL_GPL(soc_ac97_ops); 588EXPORT_SYMBOL_GPL(soc_ac97_ops);
579 589
580struct snd_soc_dai imx_ssi_pcm_dai[2];
581EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
582
583static int imx_ssi_probe(struct platform_device *pdev) 590static int imx_ssi_probe(struct platform_device *pdev)
584{ 591{
585 struct resource *res; 592 struct resource *res;
586 struct imx_ssi *ssi; 593 struct imx_ssi *ssi;
587 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; 594 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data;
588 struct snd_soc_platform *platform;
589 int ret = 0; 595 int ret = 0;
590 unsigned int val; 596 struct snd_soc_dai_driver *dai;
591 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
592
593 if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai))
594 return -EINVAL;
595 597
596 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); 598 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
597 if (!ssi) 599 if (!ssi)
598 return -ENOMEM; 600 return -ENOMEM;
601 dev_set_drvdata(&pdev->dev, ssi);
599 602
600 if (pdata) { 603 if (pdata) {
601 ssi->ac97_reset = pdata->ac97_reset; 604 ssi->ac97_reset = pdata->ac97_reset;
@@ -640,9 +643,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
640 } 643 }
641 ac97_ssi = ssi; 644 ac97_ssi = ssi;
642 setup_channel_to_ac97(ssi); 645 setup_channel_to_ac97(ssi);
643 memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); 646 dai = &imx_ac97_dai;
644 } else 647 } else
645 memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); 648 dai = &imx_ssi_dai;
646 649
647 writel(0x0, ssi->base + SSI_SIER); 650 writel(0x0, ssi->base + SSI_SIER);
648 651
@@ -657,37 +660,36 @@ static int imx_ssi_probe(struct platform_device *pdev)
657 if (res) 660 if (res)
658 ssi->dma_params_rx.dma = res->start; 661 ssi->dma_params_rx.dma = res->start;
659 662
660 dai->id = pdev->id;
661 dai->dev = &pdev->dev;
662 dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id);
663 dai->private_data = ssi;
664
665 if ((cpu_is_mx27() || cpu_is_mx21()) && 663 if ((cpu_is_mx27() || cpu_is_mx21()) &&
666 !(ssi->flags & IMX_SSI_USE_AC97) && 664 !(ssi->flags & IMX_SSI_USE_AC97) &&
667 (ssi->flags & IMX_SSI_DMA)) { 665 (ssi->flags & IMX_SSI_DMA)) {
668 ssi->flags |= IMX_SSI_DMA; 666 ssi->flags |= IMX_SSI_DMA;
669 platform = imx_ssi_dma_mx2_init(pdev, ssi); 667 }
670 } else
671 platform = imx_ssi_fiq_init(pdev, ssi);
672
673 imx_soc_platform.pcm_ops = platform->pcm_ops;
674 imx_soc_platform.pcm_new = platform->pcm_new;
675 imx_soc_platform.pcm_free = platform->pcm_free;
676 668
677 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | 669 platform_set_drvdata(pdev, ssi);
678 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
679 writel(val, ssi->base + SSI_SFCSR);
680 670
681 ret = snd_soc_register_dai(dai); 671 ret = snd_soc_register_dai(&pdev->dev, dai);
682 if (ret) { 672 if (ret) {
683 dev_err(&pdev->dev, "register DAI failed\n"); 673 dev_err(&pdev->dev, "register DAI failed\n");
684 goto failed_register; 674 goto failed_register;
685 } 675 }
686 676
687 platform_set_drvdata(pdev, ssi); 677 ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
678 if (!ssi->soc_platform_pdev)
679 goto failed_pdev_alloc;
680 platform_set_drvdata(ssi->soc_platform_pdev, ssi);
681 ret = platform_device_add(ssi->soc_platform_pdev);
682 if (ret) {
683 dev_err(&pdev->dev, "failed to add platform device\n");
684 goto failed_pdev_add;
685 }
688 686
689 return 0; 687 return 0;
690 688
689failed_pdev_add:
690 platform_device_put(ssi->soc_platform_pdev);
691failed_pdev_alloc:
692 snd_soc_unregister_dai(&pdev->dev);
691failed_register: 693failed_register:
692failed_ac97: 694failed_ac97:
693 iounmap(ssi->base); 695 iounmap(ssi->base);
@@ -706,16 +708,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
706{ 708{
707 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 709 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
708 struct imx_ssi *ssi = platform_get_drvdata(pdev); 710 struct imx_ssi *ssi = platform_get_drvdata(pdev);
709 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
710 711
711 snd_soc_unregister_dai(dai); 712 platform_device_del(ssi->soc_platform_pdev);
713 platform_device_put(ssi->soc_platform_pdev);
714
715 snd_soc_unregister_dai(&pdev->dev);
712 716
713 if (ssi->flags & IMX_SSI_USE_AC97) 717 if (ssi->flags & IMX_SSI_USE_AC97)
714 ac97_ssi = NULL; 718 ac97_ssi = NULL;
715 719
716 if (!(ssi->flags & IMX_SSI_DMA))
717 imx_ssi_fiq_exit(pdev, ssi);
718
719 iounmap(ssi->base); 720 iounmap(ssi->base);
720 release_mem_region(res->start, resource_size(res)); 721 release_mem_region(res->start, resource_size(res));
721 clk_disable(ssi->clk); 722 clk_disable(ssi->clk);
@@ -730,34 +731,19 @@ static struct platform_driver imx_ssi_driver = {
730 .remove = __devexit_p(imx_ssi_remove), 731 .remove = __devexit_p(imx_ssi_remove),
731 732
732 .driver = { 733 .driver = {
733 .name = DRV_NAME, 734 .name = "imx-ssi-dai",
734 .owner = THIS_MODULE, 735 .owner = THIS_MODULE,
735 }, 736 },
736}; 737};
737 738
738static int __init imx_ssi_init(void) 739static int __init imx_ssi_init(void)
739{ 740{
740 int ret; 741 return platform_driver_register(&imx_ssi_driver);
741
742 ret = snd_soc_register_platform(&imx_soc_platform);
743 if (ret) {
744 pr_err("failed to register soc platform: %d\n", ret);
745 return ret;
746 }
747
748 ret = platform_driver_register(&imx_ssi_driver);
749 if (ret) {
750 snd_soc_unregister_platform(&imx_soc_platform);
751 return ret;
752 }
753
754 return 0;
755} 742}
756 743
757static void __exit imx_ssi_exit(void) 744static void __exit imx_ssi_exit(void)
758{ 745{
759 platform_driver_unregister(&imx_ssi_driver); 746 platform_driver_unregister(&imx_ssi_driver);
760 snd_soc_unregister_platform(&imx_soc_platform);
761} 747}
762 748
763module_init(imx_ssi_init); 749module_init(imx_ssi_init);