aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2009-01-29 15:28:37 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-30 06:58:50 -0500
commit04eb093c7c81d118efeb96228f69bc0179f71897 (patch)
tree1d3b7eaa25c652e60ea2634c1d5c463565a0b661 /sound/soc/codecs/cs4270.c
parent7393958f630ac91e591e62058f2bdb61523ec60c (diff)
ASoC: fix initialization order of the CS4270 codec driver
ASoC codec drivers typically serve two masters: the I2C bus and ASoC itself. When a codec driver registers with ASoC, a probe function is called. Most codec drivers call ASoC first, and then register with the I2C bus in the ASoC probe function. However, in order to support multiple codecs on one board, it's easier if the codec driver is probed via the I2C bus first. This is because the call to i2c_add_driver() can result in the I2C probe function being called multiple times - once for each codec. In the current design, the driver registers once with ASoC, and in the ASoC probe function, it calls i2c_add_driver(). The results in the I2C probe function being called multiple times before the driver can register with ASoC again. The new design has the driver call i2c_add_driver() first. In the I2C probe function, the driver registers with ASoC. This allows the ASoC probe function to be called once per I2C device. Also add code to check if the I2C probe function is called more than once, since that is not supported with the current ASoC design. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c177
1 files changed, 97 insertions, 80 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 21253b48289f..adc1150ddb00 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -490,21 +490,17 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
490}; 490};
491 491
492/* 492/*
493 * Global variable to store socdev for i2c probe function. 493 * Global variable to store codec for the ASoC probe function.
494 * 494 *
495 * If struct i2c_driver had a private_data field, we wouldn't need to use 495 * If struct i2c_driver had a private_data field, we wouldn't need to use
496 * cs4270_socdec. This is the only way to pass the socdev structure to 496 * cs4270_codec. This is the only way to pass the codec structure from
497 * cs4270_i2c_probe(). 497 * cs4270_i2c_probe() to cs4270_probe(). Unfortunately, there is no good
498 * 498 * way to synchronize these two functions. cs4270_i2c_probe() can be called
499 * The real solution to cs4270_socdev is to create a mechanism 499 * multiple times before cs4270_probe() is called even once. So for now, we
500 * that maps I2C addresses to snd_soc_device structures. Perhaps the 500 * also only allow cs4270_i2c_probe() to be run once. That means that we do
501 * creation of the snd_soc_device object should be moved out of 501 * not support more than one cs4270 device in the system, at least for now.
502 * cs4270_probe() and into cs4270_i2c_probe(), but that would make this
503 * driver dependent on I2C. The CS4270 supports "stand-alone" mode, whereby
504 * the chip is *not* connected to the I2C bus, but is instead configured via
505 * input pins.
506 */ 502 */
507static struct snd_soc_device *cs4270_socdev; 503static struct snd_soc_codec *cs4270_codec;
508 504
509struct snd_soc_dai cs4270_dai = { 505struct snd_soc_dai cs4270_dai = {
510 .name = "cs4270", 506 .name = "cs4270",
@@ -532,6 +528,70 @@ struct snd_soc_dai cs4270_dai = {
532EXPORT_SYMBOL_GPL(cs4270_dai); 528EXPORT_SYMBOL_GPL(cs4270_dai);
533 529
534/* 530/*
531 * ASoC probe function
532 */
533static int cs4270_probe(struct platform_device *pdev)
534{
535 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
536 struct snd_soc_codec *codec = cs4270_codec;
537 unsigned int i;
538 int ret;
539
540 /* Connect the codec to the socdev. snd_soc_new_pcms() needs this. */
541 socdev->card->codec = codec;
542
543 /* Register PCMs */
544 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
545 if (ret < 0) {
546 printk(KERN_ERR "cs4270: failed to create PCMs\n");
547 return ret;
548 }
549
550 /* Add the non-DAPM controls */
551 for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
552 struct snd_kcontrol *kctrl;
553
554 kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL);
555 if (!kctrl) {
556 printk(KERN_ERR "cs4270: error creating control '%s'\n",
557 cs4270_snd_controls[i].name);
558 ret = -ENOMEM;
559 goto error_free_pcms;
560 }
561
562 ret = snd_ctl_add(codec->card, kctrl);
563 if (ret < 0) {
564 printk(KERN_ERR "cs4270: error adding control '%s'\n",
565 cs4270_snd_controls[i].name);
566 goto error_free_pcms;
567 }
568 }
569
570 /* And finally, register the socdev */
571 ret = snd_soc_init_card(socdev);
572 if (ret < 0) {
573 printk(KERN_ERR "cs4270: failed to register card\n");
574 goto error_free_pcms;
575 }
576
577 return 0;
578
579error_free_pcms:
580 snd_soc_free_pcms(socdev);
581
582 return ret;
583}
584
585static int cs4270_remove(struct platform_device *pdev)
586{
587 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
588
589 snd_soc_free_pcms(socdev);
590
591 return 0;
592};
593
594/*
535 * Initialize the I2C interface of the CS4270 595 * Initialize the I2C interface of the CS4270
536 * 596 *
537 * This function is called for whenever the I2C subsystem finds a device 597 * This function is called for whenever the I2C subsystem finds a device
@@ -543,17 +603,27 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
543static int cs4270_i2c_probe(struct i2c_client *i2c_client, 603static int cs4270_i2c_probe(struct i2c_client *i2c_client,
544 const struct i2c_device_id *id) 604 const struct i2c_device_id *id)
545{ 605{
546 struct snd_soc_device *socdev = cs4270_socdev;
547 struct snd_soc_codec *codec; 606 struct snd_soc_codec *codec;
548 struct cs4270_private *cs4270; 607 struct cs4270_private *cs4270;
549 int i; 608 int ret;
550 int ret = 0; 609
610 /* For now, we only support one cs4270 device in the system. See the
611 * comment for cs4270_codec.
612 */
613 if (cs4270_codec) {
614 printk(KERN_ERR "cs4270: ignoring CS4270 at addr %X\n",
615 i2c_client->addr);
616 printk(KERN_ERR "cs4270: only one CS4270 per board allowed\n");
617 /* Should we return something other than ENODEV here? */
618 return -ENODEV;
619 }
551 620
552 /* Verify that we have a CS4270 */ 621 /* Verify that we have a CS4270 */
553 622
554 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); 623 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
555 if (ret < 0) { 624 if (ret < 0) {
556 printk(KERN_ERR "cs4270: failed to read I2C\n"); 625 printk(KERN_ERR "cs4270: failed to read I2C at addr %X\n",
626 i2c_client->addr);
557 return ret; 627 return ret;
558 } 628 }
559 /* The top four bits of the chip ID should be 1100. */ 629 /* The top four bits of the chip ID should be 1100. */
@@ -575,7 +645,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
575 return -ENOMEM; 645 return -ENOMEM;
576 } 646 }
577 codec = &cs4270->codec; 647 codec = &cs4270->codec;
578 socdev->card->codec = codec; 648 cs4270_codec = codec;
579 649
580 mutex_init(&codec->mutex); 650 mutex_init(&codec->mutex);
581 INIT_LIST_HEAD(&codec->dapm_widgets); 651 INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -600,50 +670,20 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
600 goto error_free_codec; 670 goto error_free_codec;
601 } 671 }
602 672
603 /* Register PCMs */ 673 /* Register the DAI. If all the other ASoC driver have already
604 674 * registered, then this will call our probe function, so
605 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 675 * cs4270_codec needs to be ready.
676 */
677 ret = snd_soc_register_dai(&cs4270_dai);
606 if (ret < 0) { 678 if (ret < 0) {
607 printk(KERN_ERR "cs4270: failed to create PCMs\n"); 679 printk(KERN_ERR "cs4270: failed to register DAIe\n");
608 goto error_free_codec; 680 goto error_free_codec;
609 } 681 }
610 682
611 /* Add the non-DAPM controls */ 683 i2c_set_clientdata(i2c_client, cs4270);
612
613 for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
614 struct snd_kcontrol *kctrl;
615
616 kctrl = snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL);
617 if (!kctrl) {
618 printk(KERN_ERR "cs4270: error creating control '%s'\n",
619 cs4270_snd_controls[i].name);
620 ret = -ENOMEM;
621 goto error_free_pcms;
622 }
623
624 ret = snd_ctl_add(codec->card, kctrl);
625 if (ret < 0) {
626 printk(KERN_ERR "cs4270: error adding control '%s'\n",
627 cs4270_snd_controls[i].name);
628 goto error_free_pcms;
629 }
630 }
631
632 /* Initialize the SOC device */
633
634 ret = snd_soc_init_card(socdev);
635 if (ret < 0) {
636 printk(KERN_ERR "cs4270: failed to register card\n");
637 goto error_free_pcms;;
638 }
639
640 i2c_set_clientdata(i2c_client, socdev);
641 684
642 return 0; 685 return 0;
643 686
644error_free_pcms:
645 snd_soc_free_pcms(socdev);
646
647error_free_codec: 687error_free_codec:
648 kfree(cs4270); 688 kfree(cs4270);
649 689
@@ -652,11 +692,8 @@ error_free_codec:
652 692
653static int cs4270_i2c_remove(struct i2c_client *i2c_client) 693static int cs4270_i2c_remove(struct i2c_client *i2c_client)
654{ 694{
655 struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client); 695 struct cs4270_private *cs4270 = i2c_get_clientdata(i2c_client);
656 struct snd_soc_codec *codec = socdev->card->codec;
657 struct cs4270_private *cs4270 = codec->private_data;
658 696
659 snd_soc_free_pcms(socdev);
660 kfree(cs4270); 697 kfree(cs4270);
661 698
662 return 0; 699 return 0;
@@ -679,26 +716,6 @@ static struct i2c_driver cs4270_i2c_driver = {
679}; 716};
680 717
681/* 718/*
682 * ASoC probe function
683 *
684 * This function is called when the machine driver calls
685 * platform_device_add().
686 */
687static int cs4270_probe(struct platform_device *pdev)
688{
689 cs4270_socdev = platform_get_drvdata(pdev);;
690
691 return i2c_add_driver(&cs4270_i2c_driver);
692}
693
694static int cs4270_remove(struct platform_device *pdev)
695{
696 i2c_del_driver(&cs4270_i2c_driver);
697
698 return 0;
699}
700
701/*
702 * ASoC codec device structure 719 * ASoC codec device structure
703 * 720 *
704 * Assign this variable to the codec_dev field of the machine driver's 721 * Assign this variable to the codec_dev field of the machine driver's
@@ -714,13 +731,13 @@ static int __init cs4270_init(void)
714{ 731{
715 printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n"); 732 printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
716 733
717 return snd_soc_register_dai(&cs4270_dai); 734 return i2c_add_driver(&cs4270_i2c_driver);
718} 735}
719module_init(cs4270_init); 736module_init(cs4270_init);
720 737
721static void __exit cs4270_exit(void) 738static void __exit cs4270_exit(void)
722{ 739{
723 snd_soc_unregister_dai(&cs4270_dai); 740 i2c_del_driver(&cs4270_i2c_driver);
724} 741}
725module_exit(cs4270_exit); 742module_exit(cs4270_exit);
726 743