aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/davinci/davinci-i2s.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/davinci/davinci-i2s.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/davinci/davinci-i2s.c')
-rw-r--r--sound/soc/davinci/davinci-i2s.c44
1 files changed, 21 insertions, 23 deletions
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index 9e8932abf158..9f8b6c556866 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -183,8 +183,7 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
183 struct snd_pcm_substream *substream) 183 struct snd_pcm_substream *substream)
184{ 184{
185 struct snd_soc_pcm_runtime *rtd = substream->private_data; 185 struct snd_soc_pcm_runtime *rtd = substream->private_data;
186 struct snd_soc_device *socdev = rtd->socdev; 186 struct snd_soc_platform *platform = rtd->platform;
187 struct snd_soc_platform *platform = socdev->card->platform;
188 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 187 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
189 u32 spcr; 188 u32 spcr;
190 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST; 189 u32 mask = playback ? DAVINCI_MCBSP_SPCR_XRST : DAVINCI_MCBSP_SPCR_RRST;
@@ -205,8 +204,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
205 if (playback) { 204 if (playback) {
206 /* Stop the DMA to avoid data loss */ 205 /* Stop the DMA to avoid data loss */
207 /* while the transmitter is out of reset to handle XSYNCERR */ 206 /* while the transmitter is out of reset to handle XSYNCERR */
208 if (platform->pcm_ops->trigger) { 207 if (platform->driver->ops->trigger) {
209 int ret = platform->pcm_ops->trigger(substream, 208 int ret = platform->driver->ops->trigger(substream,
210 SNDRV_PCM_TRIGGER_STOP); 209 SNDRV_PCM_TRIGGER_STOP);
211 if (ret < 0) 210 if (ret < 0)
212 printk(KERN_DEBUG "Playback DMA stop failed\n"); 211 printk(KERN_DEBUG "Playback DMA stop failed\n");
@@ -227,8 +226,8 @@ static void davinci_mcbsp_start(struct davinci_mcbsp_dev *dev,
227 toggle_clock(dev, playback); 226 toggle_clock(dev, playback);
228 227
229 /* Restart the DMA */ 228 /* Restart the DMA */
230 if (platform->pcm_ops->trigger) { 229 if (platform->driver->ops->trigger) {
231 int ret = platform->pcm_ops->trigger(substream, 230 int ret = platform->driver->ops->trigger(substream,
232 SNDRV_PCM_TRIGGER_START); 231 SNDRV_PCM_TRIGGER_START);
233 if (ret < 0) 232 if (ret < 0)
234 printk(KERN_DEBUG "Playback DMA start failed\n"); 233 printk(KERN_DEBUG "Playback DMA start failed\n");
@@ -263,7 +262,7 @@ static void davinci_mcbsp_stop(struct davinci_mcbsp_dev *dev, int playback)
263static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai, 262static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
264 unsigned int fmt) 263 unsigned int fmt)
265{ 264{
266 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 265 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
267 unsigned int pcr; 266 unsigned int pcr;
268 unsigned int srgr; 267 unsigned int srgr;
269 /* Attention srgr is updated by hw_params! */ 268 /* Attention srgr is updated by hw_params! */
@@ -404,7 +403,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
404static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai, 403static int davinci_i2s_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
405 int div_id, int div) 404 int div_id, int div)
406{ 405{
407 struct davinci_mcbsp_dev *dev = cpu_dai->private_data; 406 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
408 407
409 if (div_id != DAVINCI_MCBSP_CLKGDV) 408 if (div_id != DAVINCI_MCBSP_CLKGDV)
410 return -ENODEV; 409 return -ENODEV;
@@ -417,7 +416,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
417 struct snd_pcm_hw_params *params, 416 struct snd_pcm_hw_params *params,
418 struct snd_soc_dai *dai) 417 struct snd_soc_dai *dai)
419{ 418{
420 struct davinci_mcbsp_dev *dev = dai->private_data; 419 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
421 struct davinci_pcm_dma_params *dma_params = 420 struct davinci_pcm_dma_params *dma_params =
422 &dev->dma_params[substream->stream]; 421 &dev->dma_params[substream->stream];
423 struct snd_interval *i = NULL; 422 struct snd_interval *i = NULL;
@@ -427,6 +426,9 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
427 snd_pcm_format_t fmt; 426 snd_pcm_format_t fmt;
428 unsigned element_cnt = 1; 427 unsigned element_cnt = 1;
429 428
429 dai->capture_dma_data = dev->dma_params;
430 dai->playback_dma_data = dev->dma_params;
431
430 /* general line settings */ 432 /* general line settings */
431 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG); 433 spcr = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
432 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 434 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
@@ -569,7 +571,7 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
569static int davinci_i2s_prepare(struct snd_pcm_substream *substream, 571static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
570 struct snd_soc_dai *dai) 572 struct snd_soc_dai *dai)
571{ 573{
572 struct davinci_mcbsp_dev *dev = dai->private_data; 574 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
573 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 575 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
574 davinci_mcbsp_stop(dev, playback); 576 davinci_mcbsp_stop(dev, playback);
575 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) { 577 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) {
@@ -582,7 +584,7 @@ static int davinci_i2s_prepare(struct snd_pcm_substream *substream,
582static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd, 584static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
583 struct snd_soc_dai *dai) 585 struct snd_soc_dai *dai)
584{ 586{
585 struct davinci_mcbsp_dev *dev = dai->private_data; 587 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
586 int ret = 0; 588 int ret = 0;
587 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 589 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
588 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0) 590 if ((dev->pcr & DAVINCI_MCBSP_PCR_FSXM) == 0)
@@ -608,7 +610,7 @@ static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
608static void davinci_i2s_shutdown(struct snd_pcm_substream *substream, 610static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
609 struct snd_soc_dai *dai) 611 struct snd_soc_dai *dai)
610{ 612{
611 struct davinci_mcbsp_dev *dev = dai->private_data; 613 struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(dai);
612 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); 614 int playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
613 davinci_mcbsp_stop(dev, playback); 615 davinci_mcbsp_stop(dev, playback);
614} 616}
@@ -625,9 +627,7 @@ static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
625 627
626}; 628};
627 629
628struct snd_soc_dai davinci_i2s_dai = { 630static struct snd_soc_dai_driver davinci_i2s_dai = {
629 .name = "davinci-i2s",
630 .id = 0,
631 .playback = { 631 .playback = {
632 .channels_min = 2, 632 .channels_min = 2,
633 .channels_max = 2, 633 .channels_max = 2,
@@ -641,7 +641,6 @@ struct snd_soc_dai davinci_i2s_dai = {
641 .ops = &davinci_i2s_dai_ops, 641 .ops = &davinci_i2s_dai_ops,
642 642
643}; 643};
644EXPORT_SYMBOL_GPL(davinci_i2s_dai);
645 644
646static int davinci_i2s_probe(struct platform_device *pdev) 645static int davinci_i2s_probe(struct platform_device *pdev)
647{ 646{
@@ -720,10 +719,9 @@ static int davinci_i2s_probe(struct platform_device *pdev)
720 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start; 719 dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
721 dev->dev = &pdev->dev; 720 dev->dev = &pdev->dev;
722 721
723 davinci_i2s_dai.private_data = dev; 722 dev_set_drvdata(&pdev->dev, dev);
724 davinci_i2s_dai.capture.dma_data = dev->dma_params; 723
725 davinci_i2s_dai.playback.dma_data = dev->dma_params; 724 ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
726 ret = snd_soc_register_dai(&davinci_i2s_dai);
727 if (ret != 0) 725 if (ret != 0)
728 goto err_free_mem; 726 goto err_free_mem;
729 727
@@ -739,10 +737,10 @@ err_release_region:
739 737
740static int davinci_i2s_remove(struct platform_device *pdev) 738static int davinci_i2s_remove(struct platform_device *pdev)
741{ 739{
742 struct davinci_mcbsp_dev *dev = davinci_i2s_dai.private_data; 740 struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
743 struct resource *mem; 741 struct resource *mem;
744 742
745 snd_soc_unregister_dai(&davinci_i2s_dai); 743 snd_soc_unregister_dai(&pdev->dev);
746 clk_disable(dev->clk); 744 clk_disable(dev->clk);
747 clk_put(dev->clk); 745 clk_put(dev->clk);
748 dev->clk = NULL; 746 dev->clk = NULL;
@@ -757,7 +755,7 @@ static struct platform_driver davinci_mcbsp_driver = {
757 .probe = davinci_i2s_probe, 755 .probe = davinci_i2s_probe,
758 .remove = davinci_i2s_remove, 756 .remove = davinci_i2s_remove,
759 .driver = { 757 .driver = {
760 .name = "davinci-asp", 758 .name = "davinci-i2s",
761 .owner = THIS_MODULE, 759 .owner = THIS_MODULE,
762 }, 760 },
763}; 761};