aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/uda134x.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/codecs/uda134x.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/codecs/uda134x.c')
-rw-r--r--sound/soc/codecs/uda134x.c154
1 files changed, 59 insertions, 95 deletions
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index f3b4c1d6a82d..7540a509a6f5 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -161,8 +161,7 @@ static int uda134x_startup(struct snd_pcm_substream *substream,
161 struct snd_soc_dai *dai) 161 struct snd_soc_dai *dai)
162{ 162{
163 struct snd_soc_pcm_runtime *rtd = substream->private_data; 163 struct snd_soc_pcm_runtime *rtd = substream->private_data;
164 struct snd_soc_device *socdev = rtd->socdev; 164 struct snd_soc_codec *codec =rtd->codec;
165 struct snd_soc_codec *codec = socdev->card->codec;
166 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 165 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
167 struct snd_pcm_runtime *master_runtime; 166 struct snd_pcm_runtime *master_runtime;
168 167
@@ -194,8 +193,7 @@ static void uda134x_shutdown(struct snd_pcm_substream *substream,
194 struct snd_soc_dai *dai) 193 struct snd_soc_dai *dai)
195{ 194{
196 struct snd_soc_pcm_runtime *rtd = substream->private_data; 195 struct snd_soc_pcm_runtime *rtd = substream->private_data;
197 struct snd_soc_device *socdev = rtd->socdev; 196 struct snd_soc_codec *codec = rtd->codec;
198 struct snd_soc_codec *codec = socdev->card->codec;
199 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 197 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
200 198
201 if (uda134x->master_substream == substream) 199 if (uda134x->master_substream == substream)
@@ -209,8 +207,7 @@ static int uda134x_hw_params(struct snd_pcm_substream *substream,
209 struct snd_soc_dai *dai) 207 struct snd_soc_dai *dai)
210{ 208{
211 struct snd_soc_pcm_runtime *rtd = substream->private_data; 209 struct snd_soc_pcm_runtime *rtd = substream->private_data;
212 struct snd_soc_device *socdev = rtd->socdev; 210 struct snd_soc_codec *codec = rtd->codec;
213 struct snd_soc_codec *codec = socdev->card->codec;
214 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec); 211 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
215 u8 hw_params; 212 u8 hw_params;
216 213
@@ -364,7 +361,7 @@ static int uda134x_set_bias_level(struct snd_soc_codec *codec,
364 pd->power(1); 361 pd->power(1);
365 /* Sync reg_cache with the hardware */ 362 /* Sync reg_cache with the hardware */
366 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++) 363 for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
367 codec->write(codec, i, *cache++); 364 codec->driver->write(codec, i, *cache++);
368 } 365 }
369 break; 366 break;
370 case SND_SOC_BIAS_STANDBY: 367 case SND_SOC_BIAS_STANDBY:
@@ -465,8 +462,8 @@ static struct snd_soc_dai_ops uda134x_dai_ops = {
465 .set_fmt = uda134x_set_dai_fmt, 462 .set_fmt = uda134x_set_dai_fmt,
466}; 463};
467 464
468struct snd_soc_dai uda134x_dai = { 465static struct snd_soc_dai_driver uda134x_dai = {
469 .name = "UDA134X", 466 .name = "uda134x-hifi",
470 /* playback capabilities */ 467 /* playback capabilities */
471 .playback = { 468 .playback = {
472 .stream_name = "Playback", 469 .stream_name = "Playback",
@@ -486,27 +483,21 @@ struct snd_soc_dai uda134x_dai = {
486 /* pcm operations */ 483 /* pcm operations */
487 .ops = &uda134x_dai_ops, 484 .ops = &uda134x_dai_ops,
488}; 485};
489EXPORT_SYMBOL(uda134x_dai);
490 486
491 487static int uda134x_soc_probe(struct snd_soc_codec *codec)
492static int uda134x_soc_probe(struct platform_device *pdev)
493{ 488{
494 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
495 struct snd_soc_codec *codec;
496 struct uda134x_priv *uda134x; 489 struct uda134x_priv *uda134x;
497 void *codec_setup_data = socdev->codec_data; 490 struct uda134x_platform_data *pd = dev_get_drvdata(codec->card->dev);
498 int ret = -ENOMEM; 491 int ret;
499 struct uda134x_platform_data *pd;
500 492
501 printk(KERN_INFO "UDA134X SoC Audio Codec\n"); 493 printk(KERN_INFO "UDA134X SoC Audio Codec\n");
502 494
503 if (!codec_setup_data) { 495 if (!pd) {
504 printk(KERN_ERR "UDA134X SoC codec: " 496 printk(KERN_ERR "UDA134X SoC codec: "
505 "missing L3 bitbang function\n"); 497 "missing L3 bitbang function\n");
506 return -ENODEV; 498 return -ENODEV;
507 } 499 }
508 500
509 pd = codec_setup_data;
510 switch (pd->model) { 501 switch (pd->model) {
511 case UDA134X_UDA1340: 502 case UDA134X_UDA1340:
512 case UDA134X_UDA1341: 503 case UDA134X_UDA1341:
@@ -520,58 +511,22 @@ static int uda134x_soc_probe(struct platform_device *pdev)
520 return -EINVAL; 511 return -EINVAL;
521 } 512 }
522 513
523 socdev->card->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
524 if (socdev->card->codec == NULL)
525 return ret;
526
527 codec = socdev->card->codec;
528
529 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL); 514 uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
530 if (uda134x == NULL) 515 if (uda134x == NULL)
531 goto priv_err; 516 return -ENOMEM;
532 snd_soc_codec_set_drvdata(codec, uda134x); 517 snd_soc_codec_set_drvdata(codec, uda134x);
533 518
534 codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg), 519 codec->control_data = pd;
535 GFP_KERNEL);
536 if (codec->reg_cache == NULL)
537 goto reg_err;
538
539 mutex_init(&codec->mutex);
540
541 codec->reg_cache_size = sizeof(uda134x_reg);
542 codec->reg_cache_step = 1;
543
544 codec->name = "UDA134X";
545 codec->owner = THIS_MODULE;
546 codec->dai = &uda134x_dai;
547 codec->num_dai = 1;
548 codec->read = uda134x_read_reg_cache;
549 codec->write = uda134x_write;
550
551 INIT_LIST_HEAD(&codec->dapm_widgets);
552 INIT_LIST_HEAD(&codec->dapm_paths);
553
554 codec->control_data = codec_setup_data;
555 520
556 if (pd->power) 521 if (pd->power)
557 pd->power(1); 522 pd->power(1);
558 523
559 uda134x_reset(codec); 524 uda134x_reset(codec);
560 525
561 if (pd->is_powered_on_standby) { 526 if (pd->is_powered_on_standby)
562 codec->set_bias_level = NULL;
563 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); 527 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
564 } else { 528 else
565 codec->set_bias_level = uda134x_set_bias_level;
566 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 529 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
567 }
568
569 /* register pcms */
570 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
571 if (ret < 0) {
572 printk(KERN_ERR "UDA134X: failed to register pcms\n");
573 goto pcm_err;
574 }
575 530
576 switch (pd->model) { 531 switch (pd->model) {
577 case UDA134X_UDA1340: 532 case UDA134X_UDA1340:
@@ -590,61 +545,42 @@ static int uda134x_soc_probe(struct platform_device *pdev)
590 default: 545 default:
591 printk(KERN_ERR "%s unknown codec type: %d", 546 printk(KERN_ERR "%s unknown codec type: %d",
592 __func__, pd->model); 547 __func__, pd->model);
593 return -EINVAL; 548 kfree(uda134x);
549 return -EINVAL;
594 } 550 }
595 551
596 if (ret < 0) { 552 if (ret < 0) {
597 printk(KERN_ERR "UDA134X: failed to register controls\n"); 553 printk(KERN_ERR "UDA134X: failed to register controls\n");
598 goto pcm_err; 554 kfree(uda134x);
555 return ret;
599 } 556 }
600 557
601 return 0; 558 return 0;
602
603pcm_err:
604 kfree(codec->reg_cache);
605reg_err:
606 kfree(snd_soc_codec_get_drvdata(codec));
607priv_err:
608 kfree(codec);
609 return ret;
610} 559}
611 560
612/* power down chip */ 561/* power down chip */
613static int uda134x_soc_remove(struct platform_device *pdev) 562static int uda134x_soc_remove(struct snd_soc_codec *codec)
614{ 563{
615 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 564 struct uda134x_priv *uda134x = snd_soc_codec_get_drvdata(codec);
616 struct snd_soc_codec *codec = socdev->card->codec;
617 565
618 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 566 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
619 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); 567 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
620 568
621 snd_soc_free_pcms(socdev); 569 kfree(uda134x);
622 snd_soc_dapm_free(socdev);
623
624 kfree(snd_soc_codec_get_drvdata(codec));
625 kfree(codec->reg_cache);
626 kfree(codec);
627
628 return 0; 570 return 0;
629} 571}
630 572
631#if defined(CONFIG_PM) 573#if defined(CONFIG_PM)
632static int uda134x_soc_suspend(struct platform_device *pdev, 574static int uda134x_soc_suspend(struct snd_soc_codec *codec,
633 pm_message_t state) 575 pm_message_t state)
634{ 576{
635 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
636 struct snd_soc_codec *codec = socdev->card->codec;
637
638 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 577 uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
639 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF); 578 uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
640 return 0; 579 return 0;
641} 580}
642 581
643static int uda134x_soc_resume(struct platform_device *pdev) 582static int uda134x_soc_resume(struct snd_soc_codec *codec)
644{ 583{
645 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
646 struct snd_soc_codec *codec = socdev->card->codec;
647
648 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE); 584 uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
649 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON); 585 uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
650 return 0; 586 return 0;
@@ -654,25 +590,53 @@ static int uda134x_soc_resume(struct platform_device *pdev)
654#define uda134x_soc_resume NULL 590#define uda134x_soc_resume NULL
655#endif /* CONFIG_PM */ 591#endif /* CONFIG_PM */
656 592
657struct snd_soc_codec_device soc_codec_dev_uda134x = { 593static struct snd_soc_codec_driver soc_codec_dev_uda134x = {
658 .probe = uda134x_soc_probe, 594 .probe = uda134x_soc_probe,
659 .remove = uda134x_soc_remove, 595 .remove = uda134x_soc_remove,
660 .suspend = uda134x_soc_suspend, 596 .suspend = uda134x_soc_suspend,
661 .resume = uda134x_soc_resume, 597 .resume = uda134x_soc_resume,
598 .reg_cache_size = sizeof(uda134x_reg),
599 .reg_word_size = sizeof(u8),
600 .reg_cache_step = 1,
601 .read = uda134x_read_reg_cache,
602 .write = uda134x_write,
603#ifdef POWER_OFF_ON_STANDBY
604 .set_bias_level = uda134x_set_bias_level,
605#endif
606};
607
608static int __devinit uda134x_codec_probe(struct platform_device *pdev)
609{
610 return snd_soc_register_codec(&pdev->dev,
611 &soc_codec_dev_uda134x, &uda134x_dai, 1);
612}
613
614static int __devexit uda134x_codec_remove(struct platform_device *pdev)
615{
616 snd_soc_unregister_codec(&pdev->dev);
617 return 0;
618}
619
620static struct platform_driver uda134x_codec_driver = {
621 .driver = {
622 .name = "uda134x-codec",
623 .owner = THIS_MODULE,
624 },
625 .probe = uda134x_codec_probe,
626 .remove = __devexit_p(uda134x_codec_remove),
662}; 627};
663EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
664 628
665static int __init uda134x_init(void) 629static int __init uda134x_codec_init(void)
666{ 630{
667 return snd_soc_register_dai(&uda134x_dai); 631 return platform_driver_register(&uda134x_codec_driver);
668} 632}
669module_init(uda134x_init); 633module_init(uda134x_codec_init);
670 634
671static void __exit uda134x_exit(void) 635static void __exit uda134x_codec_exit(void)
672{ 636{
673 snd_soc_unregister_dai(&uda134x_dai); 637 platform_driver_unregister(&uda134x_codec_driver);
674} 638}
675module_exit(uda134x_exit); 639module_exit(uda134x_codec_exit);
676 640
677MODULE_DESCRIPTION("UDA134X ALSA soc codec driver"); 641MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
678MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>"); 642MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");