aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa-ssp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r--sound/soc/pxa/pxa-ssp.c174
1 files changed, 64 insertions, 110 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a1fd23e0e3d0..b439eee462cb 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -35,7 +35,7 @@
35#include <mach/audio.h> 35#include <mach/audio.h>
36#include <plat/ssp.h> 36#include <plat/ssp.h>
37 37
38#include "pxa2xx-pcm.h" 38#include "../../arm/pxa2xx-pcm.h"
39#include "pxa-ssp.h" 39#include "pxa-ssp.h"
40 40
41/* 41/*
@@ -108,11 +108,9 @@ pxa_ssp_get_dma_params(struct ssp_device *ssp, int width4, int out)
108} 108}
109 109
110static int pxa_ssp_startup(struct snd_pcm_substream *substream, 110static int pxa_ssp_startup(struct snd_pcm_substream *substream,
111 struct snd_soc_dai *dai) 111 struct snd_soc_dai *cpu_dai)
112{ 112{
113 struct snd_soc_pcm_runtime *rtd = substream->private_data; 113 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
114 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
115 struct ssp_priv *priv = cpu_dai->private_data;
116 struct ssp_device *ssp = priv->ssp; 114 struct ssp_device *ssp = priv->ssp;
117 int ret = 0; 115 int ret = 0;
118 116
@@ -128,11 +126,9 @@ static int pxa_ssp_startup(struct snd_pcm_substream *substream,
128} 126}
129 127
130static void pxa_ssp_shutdown(struct snd_pcm_substream *substream, 128static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
131 struct snd_soc_dai *dai) 129 struct snd_soc_dai *cpu_dai)
132{ 130{
133 struct snd_soc_pcm_runtime *rtd = substream->private_data; 131 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
134 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
135 struct ssp_priv *priv = cpu_dai->private_data;
136 struct ssp_device *ssp = priv->ssp; 132 struct ssp_device *ssp = priv->ssp;
137 133
138 if (!cpu_dai->active) { 134 if (!cpu_dai->active) {
@@ -148,7 +144,7 @@ static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
148 144
149static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai) 145static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
150{ 146{
151 struct ssp_priv *priv = cpu_dai->private_data; 147 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
152 struct ssp_device *ssp = priv->ssp; 148 struct ssp_device *ssp = priv->ssp;
153 149
154 if (!cpu_dai->active) 150 if (!cpu_dai->active)
@@ -166,7 +162,7 @@ static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
166 162
167static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai) 163static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
168{ 164{
169 struct ssp_priv *priv = cpu_dai->private_data; 165 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
170 struct ssp_device *ssp = priv->ssp; 166 struct ssp_device *ssp = priv->ssp;
171 uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE; 167 uint32_t sssr = SSSR_ROR | SSSR_TUR | SSSR_BCE;
172 168
@@ -230,7 +226,7 @@ static u32 pxa_ssp_get_scr(struct ssp_device *ssp)
230static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai, 226static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
231 int clk_id, unsigned int freq, int dir) 227 int clk_id, unsigned int freq, int dir)
232{ 228{
233 struct ssp_priv *priv = cpu_dai->private_data; 229 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
234 struct ssp_device *ssp = priv->ssp; 230 struct ssp_device *ssp = priv->ssp;
235 int val; 231 int val;
236 232
@@ -287,7 +283,7 @@ static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
287static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai, 283static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
288 int div_id, int div) 284 int div_id, int div)
289{ 285{
290 struct ssp_priv *priv = cpu_dai->private_data; 286 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
291 struct ssp_device *ssp = priv->ssp; 287 struct ssp_device *ssp = priv->ssp;
292 int val; 288 int val;
293 289
@@ -338,7 +334,7 @@ static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
338static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id, 334static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
339 int source, unsigned int freq_in, unsigned int freq_out) 335 int source, unsigned int freq_in, unsigned int freq_out)
340{ 336{
341 struct ssp_priv *priv = cpu_dai->private_data; 337 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
342 struct ssp_device *ssp = priv->ssp; 338 struct ssp_device *ssp = priv->ssp;
343 u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70; 339 u32 ssacd = pxa_ssp_read_reg(ssp, SSACD) & ~0x70;
344 340
@@ -407,7 +403,7 @@ static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai, int pll_id,
407static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai, 403static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
408 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width) 404 unsigned int tx_mask, unsigned int rx_mask, int slots, int slot_width)
409{ 405{
410 struct ssp_priv *priv = cpu_dai->private_data; 406 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
411 struct ssp_device *ssp = priv->ssp; 407 struct ssp_device *ssp = priv->ssp;
412 u32 sscr0; 408 u32 sscr0;
413 409
@@ -442,7 +438,7 @@ static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
442static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai, 438static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
443 int tristate) 439 int tristate)
444{ 440{
445 struct ssp_priv *priv = cpu_dai->private_data; 441 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
446 struct ssp_device *ssp = priv->ssp; 442 struct ssp_device *ssp = priv->ssp;
447 u32 sscr1; 443 u32 sscr1;
448 444
@@ -464,11 +460,9 @@ static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
464static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai, 460static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
465 unsigned int fmt) 461 unsigned int fmt)
466{ 462{
467 struct ssp_priv *priv = cpu_dai->private_data; 463 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
468 struct ssp_device *ssp = priv->ssp; 464 struct ssp_device *ssp = priv->ssp;
469 u32 sscr0; 465 u32 sscr0, sscr1, sspsp, scfr;
470 u32 sscr1;
471 u32 sspsp;
472 466
473 /* check if we need to change anything at all */ 467 /* check if we need to change anything at all */
474 if (priv->dai_fmt == fmt) 468 if (priv->dai_fmt == fmt)
@@ -483,16 +477,16 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
483 477
484 /* reset port settings */ 478 /* reset port settings */
485 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & 479 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) &
486 (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS); 480 ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ACS);
487 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7); 481 sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
488 sspsp = 0; 482 sspsp = 0;
489 483
490 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 484 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
491 case SND_SOC_DAIFMT_CBM_CFM: 485 case SND_SOC_DAIFMT_CBM_CFM:
492 sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; 486 sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR | SSCR1_SCFR;
493 break; 487 break;
494 case SND_SOC_DAIFMT_CBM_CFS: 488 case SND_SOC_DAIFMT_CBM_CFS:
495 sscr1 |= SSCR1_SCLKDIR; 489 sscr1 |= SSCR1_SCLKDIR | SSCR1_SCFR;
496 break; 490 break;
497 case SND_SOC_DAIFMT_CBS_CFS: 491 case SND_SOC_DAIFMT_CBS_CFS:
498 break; 492 break;
@@ -538,6 +532,17 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
538 pxa_ssp_write_reg(ssp, SSCR1, sscr1); 532 pxa_ssp_write_reg(ssp, SSCR1, sscr1);
539 pxa_ssp_write_reg(ssp, SSPSP, sspsp); 533 pxa_ssp_write_reg(ssp, SSPSP, sspsp);
540 534
535 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
536 case SND_SOC_DAIFMT_CBM_CFM:
537 case SND_SOC_DAIFMT_CBM_CFS:
538 scfr = pxa_ssp_read_reg(ssp, SSCR1) | SSCR1_SCFR;
539 pxa_ssp_write_reg(ssp, SSCR1, scfr);
540
541 while (pxa_ssp_read_reg(ssp, SSSR) & SSSR_BSY)
542 cpu_relax();
543 break;
544 }
545
541 dump_registers(ssp); 546 dump_registers(ssp);
542 547
543 /* Since we are configuring the timings for the format by hand 548 /* Since we are configuring the timings for the format by hand
@@ -555,11 +560,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
555 */ 560 */
556static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, 561static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
557 struct snd_pcm_hw_params *params, 562 struct snd_pcm_hw_params *params,
558 struct snd_soc_dai *dai) 563 struct snd_soc_dai *cpu_dai)
559{ 564{
560 struct snd_soc_pcm_runtime *rtd = substream->private_data; 565 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
561 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
562 struct ssp_priv *priv = cpu_dai->private_data;
563 struct ssp_device *ssp = priv->ssp; 566 struct ssp_device *ssp = priv->ssp;
564 int chn = params_channels(params); 567 int chn = params_channels(params);
565 u32 sscr0; 568 u32 sscr0;
@@ -568,7 +571,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
568 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; 571 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;
569 struct pxa2xx_pcm_dma_params *dma_data; 572 struct pxa2xx_pcm_dma_params *dma_data;
570 573
571 dma_data = snd_soc_dai_get_dma_data(dai, substream); 574 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
572 575
573 /* generate correct DMA params */ 576 /* generate correct DMA params */
574 kfree(dma_data); 577 kfree(dma_data);
@@ -581,7 +584,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
581 ((chn == 2) && (ttsa != 1)) || (width == 32), 584 ((chn == 2) && (ttsa != 1)) || (width == 32),
582 substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 585 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
583 586
584 snd_soc_dai_set_dma_data(dai, substream, dma_data); 587 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
585 588
586 /* we can only change the settings if the port is not in use */ 589 /* we can only change the settings if the port is not in use */
587 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 590 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
@@ -589,10 +592,8 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
589 592
590 /* clear selected SSP bits */ 593 /* clear selected SSP bits */
591 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS); 594 sscr0 = pxa_ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
592 pxa_ssp_write_reg(ssp, SSCR0, sscr0);
593 595
594 /* bit size */ 596 /* bit size */
595 sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
596 switch (params_format(params)) { 597 switch (params_format(params)) {
597 case SNDRV_PCM_FORMAT_S16_LE: 598 case SNDRV_PCM_FORMAT_S16_LE:
598#ifdef CONFIG_PXA3xx 599#ifdef CONFIG_PXA3xx
@@ -668,12 +669,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
668} 669}
669 670
670static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, 671static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
671 struct snd_soc_dai *dai) 672 struct snd_soc_dai *cpu_dai)
672{ 673{
673 struct snd_soc_pcm_runtime *rtd = substream->private_data;
674 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
675 int ret = 0; 674 int ret = 0;
676 struct ssp_priv *priv = cpu_dai->private_data; 675 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
677 struct ssp_device *ssp = priv->ssp; 676 struct ssp_device *ssp = priv->ssp;
678 int val; 677 int val;
679 678
@@ -729,8 +728,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
729 return ret; 728 return ret;
730} 729}
731 730
732static int pxa_ssp_probe(struct platform_device *pdev, 731static int pxa_ssp_probe(struct snd_soc_dai *dai)
733 struct snd_soc_dai *dai)
734{ 732{
735 struct ssp_priv *priv; 733 struct ssp_priv *priv;
736 int ret; 734 int ret;
@@ -746,7 +744,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
746 } 744 }
747 745
748 priv->dai_fmt = (unsigned int) -1; 746 priv->dai_fmt = (unsigned int) -1;
749 dai->private_data = priv; 747 snd_soc_dai_set_drvdata(dai, priv);
750 748
751 return 0; 749 return 0;
752 750
@@ -755,11 +753,13 @@ err_priv:
755 return ret; 753 return ret;
756} 754}
757 755
758static void pxa_ssp_remove(struct platform_device *pdev, 756static int pxa_ssp_remove(struct snd_soc_dai *dai)
759 struct snd_soc_dai *dai)
760{ 757{
761 struct ssp_priv *priv = dai->private_data; 758 struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai);
759
762 pxa_ssp_free(priv->ssp); 760 pxa_ssp_free(priv->ssp);
761 kfree(priv);
762 return 0;
763} 763}
764 764
765#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 765#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -784,10 +784,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
784 .set_tristate = pxa_ssp_set_dai_tristate, 784 .set_tristate = pxa_ssp_set_dai_tristate,
785}; 785};
786 786
787struct snd_soc_dai pxa_ssp_dai[] = { 787static struct snd_soc_dai_driver pxa_ssp_dai = {
788 {
789 .name = "pxa2xx-ssp1",
790 .id = 0,
791 .probe = pxa_ssp_probe, 788 .probe = pxa_ssp_probe,
792 .remove = pxa_ssp_remove, 789 .remove = pxa_ssp_remove,
793 .suspend = pxa_ssp_suspend, 790 .suspend = pxa_ssp_suspend,
@@ -805,81 +802,38 @@ struct snd_soc_dai pxa_ssp_dai[] = {
805 .formats = PXA_SSP_FORMATS, 802 .formats = PXA_SSP_FORMATS,
806 }, 803 },
807 .ops = &pxa_ssp_dai_ops, 804 .ops = &pxa_ssp_dai_ops,
805};
806
807static __devinit int asoc_ssp_probe(struct platform_device *pdev)
808{
809 return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
810}
811
812static int __devexit asoc_ssp_remove(struct platform_device *pdev)
813{
814 snd_soc_unregister_dai(&pdev->dev);
815 return 0;
816}
817
818static struct platform_driver asoc_ssp_driver = {
819 .driver = {
820 .name = "pxa-ssp-dai",
821 .owner = THIS_MODULE,
808 }, 822 },
809 { .name = "pxa2xx-ssp2", 823
810 .id = 1, 824 .probe = asoc_ssp_probe,
811 .probe = pxa_ssp_probe, 825 .remove = __devexit_p(asoc_ssp_remove),
812 .remove = pxa_ssp_remove,
813 .suspend = pxa_ssp_suspend,
814 .resume = pxa_ssp_resume,
815 .playback = {
816 .channels_min = 1,
817 .channels_max = 8,
818 .rates = PXA_SSP_RATES,
819 .formats = PXA_SSP_FORMATS,
820 },
821 .capture = {
822 .channels_min = 1,
823 .channels_max = 8,
824 .rates = PXA_SSP_RATES,
825 .formats = PXA_SSP_FORMATS,
826 },
827 .ops = &pxa_ssp_dai_ops,
828 },
829 {
830 .name = "pxa2xx-ssp3",
831 .id = 2,
832 .probe = pxa_ssp_probe,
833 .remove = pxa_ssp_remove,
834 .suspend = pxa_ssp_suspend,
835 .resume = pxa_ssp_resume,
836 .playback = {
837 .channels_min = 1,
838 .channels_max = 8,
839 .rates = PXA_SSP_RATES,
840 .formats = PXA_SSP_FORMATS,
841 },
842 .capture = {
843 .channels_min = 1,
844 .channels_max = 8,
845 .rates = PXA_SSP_RATES,
846 .formats = PXA_SSP_FORMATS,
847 },
848 .ops = &pxa_ssp_dai_ops,
849 },
850 {
851 .name = "pxa2xx-ssp4",
852 .id = 3,
853 .probe = pxa_ssp_probe,
854 .remove = pxa_ssp_remove,
855 .suspend = pxa_ssp_suspend,
856 .resume = pxa_ssp_resume,
857 .playback = {
858 .channels_min = 1,
859 .channels_max = 8,
860 .rates = PXA_SSP_RATES,
861 .formats = PXA_SSP_FORMATS,
862 },
863 .capture = {
864 .channels_min = 1,
865 .channels_max = 8,
866 .rates = PXA_SSP_RATES,
867 .formats = PXA_SSP_FORMATS,
868 },
869 .ops = &pxa_ssp_dai_ops,
870 },
871}; 826};
872EXPORT_SYMBOL_GPL(pxa_ssp_dai);
873 827
874static int __init pxa_ssp_init(void) 828static int __init pxa_ssp_init(void)
875{ 829{
876 return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 830 return platform_driver_register(&asoc_ssp_driver);
877} 831}
878module_init(pxa_ssp_init); 832module_init(pxa_ssp_init);
879 833
880static void __exit pxa_ssp_exit(void) 834static void __exit pxa_ssp_exit(void)
881{ 835{
882 snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 836 platform_driver_unregister(&asoc_ssp_driver);
883} 837}
884module_exit(pxa_ssp_exit); 838module_exit(pxa_ssp_exit);
885 839