aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/pxa/pxa-ssp.c
diff options
context:
space:
mode:
authorLiam Girdwood <lrg@slimlogic.co.uk>2010-03-17 16:15:21 -0400
committerLiam Girdwood <lrg@slimlogic.co.uk>2010-08-12 09:00:00 -0400
commitf0fba2ad1b6b53d5360125c41953b7afcd6deff0 (patch)
treef6ad50905f8daa616593c978d7ae992e73241180 /sound/soc/pxa/pxa-ssp.c
parentbda7d2a862e6b788bca2d02d38a07966a9c92e48 (diff)
ASoC: multi-component - ASoC Multi-Component Support
This patch extends the ASoC API to allow sound cards to have more than one CODEC and more than one platform DMA controller. This is achieved by dividing some current ASoC structures that contain both driver data and device data into structures that only either contain device data or driver data. i.e. struct snd_soc_codec ---> struct snd_soc_codec (device data) +-> struct snd_soc_codec_driver (driver data) struct snd_soc_platform ---> struct snd_soc_platform (device data) +-> struct snd_soc_platform_driver (driver data) struct snd_soc_dai ---> struct snd_soc_dai (device data) +-> struct snd_soc_dai_driver (driver data) struct snd_soc_device ---> deleted This now allows ASoC to be more tightly aligned with the Linux driver model and also means that every ASoC codec, platform and (platform) DAI is a kernel device. ASoC component private data is now stored as device private data. The ASoC sound card struct snd_soc_card has also been updated to store lists of it's components rather than a pointer to a codec and platform. The PCM runtime struct soc_pcm_runtime now has pointers to all its components. This patch adds DAPM support for ASoC multi-component and removes struct snd_soc_socdev from DAPM core. All DAPM calls are now made on a card, codec or runtime PCM level basis rather than using snd_soc_socdev. Other notable multi-component changes:- * Stream operations now de-reference less structures. * close_delayed work() now runs on a DAI basis rather than looping all DAIs in a card. * PM suspend()/resume() operations can now handle N CODECs and Platforms per sound card. * Added soc_bind_dai_link() to bind the component devices to the sound card. * Added soc_dai_link_probe() and soc_dai_link_remove() to probe and remove DAI link components. * sysfs entries can now be registered per component per card. * snd_soc_new_pcms() functionailty rolled into dai_link_probe(). * snd_soc_register_codec() now does all the codec list and mutex init. This patch changes the probe() and remove() of the CODEC drivers as follows:- o Make CODEC driver a platform driver o Moved all struct snd_soc_codec list, mutex, etc initialiasation to core. o Removed all static codec pointers (drivers now support > 1 codec dev) o snd_soc_register_pcms() now done by core. o snd_soc_register_dai() folded into snd_soc_register_codec(). CS4270 portions: Acked-by: Timur Tabi <timur@freescale.com> Some TLV320aic23 and Cirrus platform fixes. Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> TI CODEC and OMAP fixes Signed-off-by: Peter Ujfalusi <peter.ujfalusi@nokia.com> Signed-off-by: Janusz Krzysztofik <jkrzyszt@tis.icnet.pl> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com> Samsung platform and misc fixes :- Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Jassi Brar <jassi.brar@samsung.com> Signed-off-by: Seungwhan Youn <sw.youn@samsung.com> MPC8610 and PPC fixes. Signed-off-by: Timur Tabi <timur@freescale.com> i.MX fixes and some core fixes. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de> J4740 platform fixes:- Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> CC: Tony Lindgren <tony@atomide.com> CC: Nicolas Ferre <nicolas.ferre@atmel.com> CC: Kevin Hilman <khilman@deeprootsystems.com> CC: Sascha Hauer <s.hauer@pengutronix.de> CC: Atsushi Nemoto <anemo@mba.ocn.ne.jp> CC: Kuninori Morimoto <morimoto.kuninori@renesas.com> CC: Daniel Gloeckner <dg@emlix.com> CC: Manuel Lauss <mano@roarinelk.homelinux.net> CC: Mike Frysinger <vapier.adi@gmail.com> CC: Arnaud Patard <apatard@mandriva.com> CC: Wan ZongShun <mcuos.com@gmail.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com> Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
Diffstat (limited to 'sound/soc/pxa/pxa-ssp.c')
-rw-r--r--sound/soc/pxa/pxa-ssp.c148
1 files changed, 47 insertions, 101 deletions
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index a1fd23e0e3d0..99d80e85621c 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -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,7 +460,7 @@ 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;
470 u32 sscr1; 466 u32 sscr1;
@@ -555,11 +551,9 @@ static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
555 */ 551 */
556static int pxa_ssp_hw_params(struct snd_pcm_substream *substream, 552static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
557 struct snd_pcm_hw_params *params, 553 struct snd_pcm_hw_params *params,
558 struct snd_soc_dai *dai) 554 struct snd_soc_dai *cpu_dai)
559{ 555{
560 struct snd_soc_pcm_runtime *rtd = substream->private_data; 556 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; 557 struct ssp_device *ssp = priv->ssp;
564 int chn = params_channels(params); 558 int chn = params_channels(params);
565 u32 sscr0; 559 u32 sscr0;
@@ -568,7 +562,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
568 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf; 562 int ttsa = pxa_ssp_read_reg(ssp, SSTSA) & 0xf;
569 struct pxa2xx_pcm_dma_params *dma_data; 563 struct pxa2xx_pcm_dma_params *dma_data;
570 564
571 dma_data = snd_soc_dai_get_dma_data(dai, substream); 565 dma_data = snd_soc_dai_get_dma_data(cpu_dai, substream);
572 566
573 /* generate correct DMA params */ 567 /* generate correct DMA params */
574 kfree(dma_data); 568 kfree(dma_data);
@@ -581,7 +575,7 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
581 ((chn == 2) && (ttsa != 1)) || (width == 32), 575 ((chn == 2) && (ttsa != 1)) || (width == 32),
582 substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 576 substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
583 577
584 snd_soc_dai_set_dma_data(dai, substream, dma_data); 578 snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
585 579
586 /* we can only change the settings if the port is not in use */ 580 /* we can only change the settings if the port is not in use */
587 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) 581 if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
@@ -668,12 +662,10 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
668} 662}
669 663
670static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd, 664static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
671 struct snd_soc_dai *dai) 665 struct snd_soc_dai *cpu_dai)
672{ 666{
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; 667 int ret = 0;
676 struct ssp_priv *priv = cpu_dai->private_data; 668 struct ssp_priv *priv = snd_soc_dai_get_drvdata(cpu_dai);
677 struct ssp_device *ssp = priv->ssp; 669 struct ssp_device *ssp = priv->ssp;
678 int val; 670 int val;
679 671
@@ -729,8 +721,7 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
729 return ret; 721 return ret;
730} 722}
731 723
732static int pxa_ssp_probe(struct platform_device *pdev, 724static int pxa_ssp_probe(struct snd_soc_dai *dai)
733 struct snd_soc_dai *dai)
734{ 725{
735 struct ssp_priv *priv; 726 struct ssp_priv *priv;
736 int ret; 727 int ret;
@@ -746,7 +737,7 @@ static int pxa_ssp_probe(struct platform_device *pdev,
746 } 737 }
747 738
748 priv->dai_fmt = (unsigned int) -1; 739 priv->dai_fmt = (unsigned int) -1;
749 dai->private_data = priv; 740 snd_soc_dai_set_drvdata(dai, priv);
750 741
751 return 0; 742 return 0;
752 743
@@ -755,11 +746,12 @@ err_priv:
755 return ret; 746 return ret;
756} 747}
757 748
758static void pxa_ssp_remove(struct platform_device *pdev, 749static int pxa_ssp_remove(struct snd_soc_dai *dai)
759 struct snd_soc_dai *dai)
760{ 750{
761 struct ssp_priv *priv = dai->private_data; 751 struct ssp_priv *priv = snd_soc_dai_get_drvdata(dai);
752
762 pxa_ssp_free(priv->ssp); 753 pxa_ssp_free(priv->ssp);
754 return 0;
763} 755}
764 756
765#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ 757#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
@@ -784,10 +776,7 @@ static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
784 .set_tristate = pxa_ssp_set_dai_tristate, 776 .set_tristate = pxa_ssp_set_dai_tristate,
785}; 777};
786 778
787struct snd_soc_dai pxa_ssp_dai[] = { 779static struct snd_soc_dai_driver pxa_ssp_dai = {
788 {
789 .name = "pxa2xx-ssp1",
790 .id = 0,
791 .probe = pxa_ssp_probe, 780 .probe = pxa_ssp_probe,
792 .remove = pxa_ssp_remove, 781 .remove = pxa_ssp_remove,
793 .suspend = pxa_ssp_suspend, 782 .suspend = pxa_ssp_suspend,
@@ -805,81 +794,38 @@ struct snd_soc_dai pxa_ssp_dai[] = {
805 .formats = PXA_SSP_FORMATS, 794 .formats = PXA_SSP_FORMATS,
806 }, 795 },
807 .ops = &pxa_ssp_dai_ops, 796 .ops = &pxa_ssp_dai_ops,
797};
798
799static __devinit int asoc_ssp_probe(struct platform_device *pdev)
800{
801 return snd_soc_register_dai(&pdev->dev, &pxa_ssp_dai);
802}
803
804static int __devexit asoc_ssp_remove(struct platform_device *pdev)
805{
806 snd_soc_unregister_dai(&pdev->dev);
807 return 0;
808}
809
810static struct platform_driver asoc_ssp_driver = {
811 .driver = {
812 .name = "pxa-ssp-dai",
813 .owner = THIS_MODULE,
808 }, 814 },
809 { .name = "pxa2xx-ssp2", 815
810 .id = 1, 816 .probe = asoc_ssp_probe,
811 .probe = pxa_ssp_probe, 817 .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}; 818};
872EXPORT_SYMBOL_GPL(pxa_ssp_dai);
873 819
874static int __init pxa_ssp_init(void) 820static int __init pxa_ssp_init(void)
875{ 821{
876 return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 822 return platform_driver_register(&asoc_ssp_driver);
877} 823}
878module_init(pxa_ssp_init); 824module_init(pxa_ssp_init);
879 825
880static void __exit pxa_ssp_exit(void) 826static void __exit pxa_ssp_exit(void)
881{ 827{
882 snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai)); 828 platform_driver_unregister(&asoc_ssp_driver);
883} 829}
884module_exit(pxa_ssp_exit); 830module_exit(pxa_ssp_exit);
885 831