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 c81da05a4f11..d4bd345b0a8d 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
@@ -282,9 +282,7 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
282static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd, 282static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
283 struct snd_soc_dai *dai) 283 struct snd_soc_dai *dai)
284{ 284{
285 struct snd_soc_pcm_runtime *rtd = substream->private_data; 285 struct imx_ssi *ssi = snd_soc_dai_get_drvdata(dai);
286 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
287 struct imx_ssi *ssi = cpu_dai->private_data;
288 unsigned int sier_bits, sier; 286 unsigned int sier_bits, sier;
289 unsigned int scr; 287 unsigned int scr;
290 288
@@ -353,22 +351,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
353 .trigger = imx_ssi_trigger, 351 .trigger = imx_ssi_trigger,
354}; 352};
355 353
356static struct snd_soc_dai imx_ssi_dai = {
357 .playback = {
358 .channels_min = 2,
359 .channels_max = 2,
360 .rates = SNDRV_PCM_RATE_8000_96000,
361 .formats = SNDRV_PCM_FMTBIT_S16_LE,
362 },
363 .capture = {
364 .channels_min = 2,
365 .channels_max = 2,
366 .rates = SNDRV_PCM_RATE_8000_96000,
367 .formats = SNDRV_PCM_FMTBIT_S16_LE,
368 },
369 .ops = &imx_ssi_pcm_dai_ops,
370};
371
372int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, 354int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
373 struct vm_area_struct *vma) 355 struct vm_area_struct *vma)
374{ 356{
@@ -384,6 +366,7 @@ int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
384 runtime->dma_bytes); 366 runtime->dma_bytes);
385 return ret; 367 return ret;
386} 368}
369EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
387 370
388static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream) 371static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
389{ 372{
@@ -415,14 +398,14 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
415 card->dev->dma_mask = &imx_pcm_dmamask; 398 card->dev->dma_mask = &imx_pcm_dmamask;
416 if (!card->dev->coherent_dma_mask) 399 if (!card->dev->coherent_dma_mask)
417 card->dev->coherent_dma_mask = DMA_BIT_MASK(32); 400 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
418 if (dai->playback.channels_min) { 401 if (dai->driver->playback.channels_min) {
419 ret = imx_pcm_preallocate_dma_buffer(pcm, 402 ret = imx_pcm_preallocate_dma_buffer(pcm,
420 SNDRV_PCM_STREAM_PLAYBACK); 403 SNDRV_PCM_STREAM_PLAYBACK);
421 if (ret) 404 if (ret)
422 goto out; 405 goto out;
423 } 406 }
424 407
425 if (dai->capture.channels_min) { 408 if (dai->driver->capture.channels_min) {
426 ret = imx_pcm_preallocate_dma_buffer(pcm, 409 ret = imx_pcm_preallocate_dma_buffer(pcm,
427 SNDRV_PCM_STREAM_CAPTURE); 410 SNDRV_PCM_STREAM_CAPTURE);
428 if (ret) 411 if (ret)
@@ -432,6 +415,7 @@ int imx_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
432out: 415out:
433 return ret; 416 return ret;
434} 417}
418EXPORT_SYMBOL_GPL(imx_pcm_new);
435 419
436void imx_pcm_free(struct snd_pcm *pcm) 420void imx_pcm_free(struct snd_pcm *pcm)
437{ 421{
@@ -453,14 +437,40 @@ void imx_pcm_free(struct snd_pcm *pcm)
453 buf->area = NULL; 437 buf->area = NULL;
454 } 438 }
455} 439}
440EXPORT_SYMBOL_GPL(imx_pcm_free);
456 441
457struct snd_soc_platform imx_soc_platform = { 442static struct snd_soc_dai_driver imx_ssi_dai = {
458 .name = "imx-audio", 443 .playback = {
444 .channels_min = 2,
445 .channels_max = 2,
446 .rates = SNDRV_PCM_RATE_8000_96000,
447 .formats = SNDRV_PCM_FMTBIT_S16_LE,
448 },
449 .capture = {
450 .channels_min = 2,
451 .channels_max = 2,
452 .rates = SNDRV_PCM_RATE_8000_96000,
453 .formats = SNDRV_PCM_FMTBIT_S16_LE,
454 },
455 .ops = &imx_ssi_pcm_dai_ops,
459}; 456};
460EXPORT_SYMBOL_GPL(imx_soc_platform);
461 457
462static struct snd_soc_dai imx_ac97_dai = { 458static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
463 .name = "AC97", 459{
460 struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
461 uint32_t val;
462
463 snd_soc_dai_set_drvdata(dai, ssi);
464
465 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) |
466 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
467 writel(val, ssi->base + SSI_SFCSR);
468
469 return 0;
470}
471
472static struct snd_soc_dai_driver imx_ac97_dai = {
473 .probe = imx_ssi_dai_probe,
464 .ac97_control = 1, 474 .ac97_control = 1,
465 .playback = { 475 .playback = {
466 .stream_name = "AC97 Playback", 476 .stream_name = "AC97 Playback",
@@ -580,25 +590,18 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
580}; 590};
581EXPORT_SYMBOL_GPL(soc_ac97_ops); 591EXPORT_SYMBOL_GPL(soc_ac97_ops);
582 592
583struct snd_soc_dai imx_ssi_pcm_dai[2];
584EXPORT_SYMBOL_GPL(imx_ssi_pcm_dai);
585
586static int imx_ssi_probe(struct platform_device *pdev) 593static int imx_ssi_probe(struct platform_device *pdev)
587{ 594{
588 struct resource *res; 595 struct resource *res;
589 struct imx_ssi *ssi; 596 struct imx_ssi *ssi;
590 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data; 597 struct imx_ssi_platform_data *pdata = pdev->dev.platform_data;
591 struct snd_soc_platform *platform;
592 int ret = 0; 598 int ret = 0;
593 unsigned int val; 599 struct snd_soc_dai_driver *dai;
594 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
595
596 if (dai->id >= ARRAY_SIZE(imx_ssi_pcm_dai))
597 return -EINVAL;
598 600
599 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); 601 ssi = kzalloc(sizeof(*ssi), GFP_KERNEL);
600 if (!ssi) 602 if (!ssi)
601 return -ENOMEM; 603 return -ENOMEM;
604 dev_set_drvdata(&pdev->dev, ssi);
602 605
603 if (pdata) { 606 if (pdata) {
604 ssi->ac97_reset = pdata->ac97_reset; 607 ssi->ac97_reset = pdata->ac97_reset;
@@ -643,9 +646,9 @@ static int imx_ssi_probe(struct platform_device *pdev)
643 } 646 }
644 ac97_ssi = ssi; 647 ac97_ssi = ssi;
645 setup_channel_to_ac97(ssi); 648 setup_channel_to_ac97(ssi);
646 memcpy(dai, &imx_ac97_dai, sizeof(imx_ac97_dai)); 649 dai = &imx_ac97_dai;
647 } else 650 } else
648 memcpy(dai, &imx_ssi_dai, sizeof(imx_ssi_dai)); 651 dai = &imx_ssi_dai;
649 652
650 writel(0x0, ssi->base + SSI_SIER); 653 writel(0x0, ssi->base + SSI_SIER);
651 654
@@ -660,37 +663,36 @@ static int imx_ssi_probe(struct platform_device *pdev)
660 if (res) 663 if (res)
661 ssi->dma_params_rx.dma = res->start; 664 ssi->dma_params_rx.dma = res->start;
662 665
663 dai->id = pdev->id;
664 dai->dev = &pdev->dev;
665 dai->name = kasprintf(GFP_KERNEL, "imx-ssi.%d", pdev->id);
666 dai->private_data = ssi;
667
668 if ((cpu_is_mx27() || cpu_is_mx21()) && 666 if ((cpu_is_mx27() || cpu_is_mx21()) &&
669 !(ssi->flags & IMX_SSI_USE_AC97) && 667 !(ssi->flags & IMX_SSI_USE_AC97) &&
670 (ssi->flags & IMX_SSI_DMA)) { 668 (ssi->flags & IMX_SSI_DMA)) {
671 ssi->flags |= IMX_SSI_DMA; 669 ssi->flags |= IMX_SSI_DMA;
672 platform = imx_ssi_dma_mx2_init(pdev, ssi); 670 }
673 } else
674 platform = imx_ssi_fiq_init(pdev, ssi);
675
676 imx_soc_platform.pcm_ops = platform->pcm_ops;
677 imx_soc_platform.pcm_new = platform->pcm_new;
678 imx_soc_platform.pcm_free = platform->pcm_free;
679 671
680 val = SSI_SFCSR_TFWM0(ssi->dma_params_tx.burstsize) | 672 platform_set_drvdata(pdev, ssi);
681 SSI_SFCSR_RFWM0(ssi->dma_params_rx.burstsize);
682 writel(val, ssi->base + SSI_SFCSR);
683 673
684 ret = snd_soc_register_dai(dai); 674 ret = snd_soc_register_dai(&pdev->dev, dai);
685 if (ret) { 675 if (ret) {
686 dev_err(&pdev->dev, "register DAI failed\n"); 676 dev_err(&pdev->dev, "register DAI failed\n");
687 goto failed_register; 677 goto failed_register;
688 } 678 }
689 679
690 platform_set_drvdata(pdev, ssi); 680 ssi->soc_platform_pdev = platform_device_alloc("imx-fiq-pcm-audio", pdev->id);
681 if (!ssi->soc_platform_pdev)
682 goto failed_pdev_alloc;
683 platform_set_drvdata(ssi->soc_platform_pdev, ssi);
684 ret = platform_device_add(ssi->soc_platform_pdev);
685 if (ret) {
686 dev_err(&pdev->dev, "failed to add platform device\n");
687 goto failed_pdev_add;
688 }
691 689
692 return 0; 690 return 0;
693 691
692failed_pdev_add:
693 platform_device_put(ssi->soc_platform_pdev);
694failed_pdev_alloc:
695 snd_soc_unregister_dai(&pdev->dev);
694failed_register: 696failed_register:
695failed_ac97: 697failed_ac97:
696 iounmap(ssi->base); 698 iounmap(ssi->base);
@@ -709,16 +711,15 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev)
709{ 711{
710 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 712 struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
711 struct imx_ssi *ssi = platform_get_drvdata(pdev); 713 struct imx_ssi *ssi = platform_get_drvdata(pdev);
712 struct snd_soc_dai *dai = &imx_ssi_pcm_dai[pdev->id];
713 714
714 snd_soc_unregister_dai(dai); 715 platform_device_del(ssi->soc_platform_pdev);
716 platform_device_put(ssi->soc_platform_pdev);
717
718 snd_soc_unregister_dai(&pdev->dev);
715 719
716 if (ssi->flags & IMX_SSI_USE_AC97) 720 if (ssi->flags & IMX_SSI_USE_AC97)
717 ac97_ssi = NULL; 721 ac97_ssi = NULL;
718 722
719 if (!(ssi->flags & IMX_SSI_DMA))
720 imx_ssi_fiq_exit(pdev, ssi);
721
722 iounmap(ssi->base); 723 iounmap(ssi->base);
723 release_mem_region(res->start, resource_size(res)); 724 release_mem_region(res->start, resource_size(res));
724 clk_disable(ssi->clk); 725 clk_disable(ssi->clk);
@@ -733,34 +734,19 @@ static struct platform_driver imx_ssi_driver = {
733 .remove = __devexit_p(imx_ssi_remove), 734 .remove = __devexit_p(imx_ssi_remove),
734 735
735 .driver = { 736 .driver = {
736 .name = DRV_NAME, 737 .name = "imx-ssi",
737 .owner = THIS_MODULE, 738 .owner = THIS_MODULE,
738 }, 739 },
739}; 740};
740 741
741static int __init imx_ssi_init(void) 742static int __init imx_ssi_init(void)
742{ 743{
743 int ret; 744 return platform_driver_register(&imx_ssi_driver);
744
745 ret = snd_soc_register_platform(&imx_soc_platform);
746 if (ret) {
747 pr_err("failed to register soc platform: %d\n", ret);
748 return ret;
749 }
750
751 ret = platform_driver_register(&imx_ssi_driver);
752 if (ret) {
753 snd_soc_unregister_platform(&imx_soc_platform);
754 return ret;
755 }
756
757 return 0;
758} 745}
759 746
760static void __exit imx_ssi_exit(void) 747static void __exit imx_ssi_exit(void)
761{ 748{
762 platform_driver_unregister(&imx_ssi_driver); 749 platform_driver_unregister(&imx_ssi_driver);
763 snd_soc_unregister_platform(&imx_soc_platform);
764} 750}
765 751
766module_init(imx_ssi_init); 752module_init(imx_ssi_init);