aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2009-01-23 17:31:19 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-01-23 18:00:39 -0500
commit0db4d0705260dd4bddf1e5a5441c58bdf08bdc9f (patch)
tree573e721a97a56d3ca923436393a1435d3d5ef159 /sound/soc/codecs/cs4270.c
parent070504ade7a95a0f4395673717f3bb7d41793ca8 (diff)
ASoC: improve I2C initialization code in CS4270 driver
Further improvements in the I2C initialization sequence of the CS4270 driver. All ASoC initialization is now done in the I2C probe function. 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.c252
1 files changed, 113 insertions, 139 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index e2130d7b1e41..2aa12fdbd2ca 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -31,12 +31,6 @@
31 31
32#include "cs4270.h" 32#include "cs4270.h"
33 33
34/* Private data for the CS4270 */
35struct cs4270_private {
36 unsigned int mclk; /* Input frequency of the MCLK pin */
37 unsigned int mode; /* The mode (I2S or left-justified) */
38};
39
40/* 34/*
41 * The codec isn't really big-endian or little-endian, since the I2S 35 * The codec isn't really big-endian or little-endian, since the I2S
42 * interface requires data to be sent serially with the MSbit first. 36 * interface requires data to be sent serially with the MSbit first.
@@ -109,6 +103,14 @@ struct cs4270_private {
109#define CS4270_MUTE_DAC_A 0x01 103#define CS4270_MUTE_DAC_A 0x01
110#define CS4270_MUTE_DAC_B 0x02 104#define CS4270_MUTE_DAC_B 0x02
111 105
106/* Private data for the CS4270 */
107struct cs4270_private {
108 struct snd_soc_codec codec;
109 u8 reg_cache[CS4270_NUMREGS];
110 unsigned int mclk; /* Input frequency of the MCLK pin */
111 unsigned int mode; /* The mode (I2S or left-justified) */
112};
113
112/* 114/*
113 * Clock Ratio Selection for Master Mode with I2C enabled 115 * Clock Ratio Selection for Master Mode with I2C enabled
114 * 116 *
@@ -504,6 +506,31 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
504 */ 506 */
505static struct snd_soc_device *cs4270_socdev; 507static struct snd_soc_device *cs4270_socdev;
506 508
509struct snd_soc_dai cs4270_dai = {
510 .name = "cs4270",
511 .playback = {
512 .stream_name = "Playback",
513 .channels_min = 1,
514 .channels_max = 2,
515 .rates = 0,
516 .formats = CS4270_FORMATS,
517 },
518 .capture = {
519 .stream_name = "Capture",
520 .channels_min = 1,
521 .channels_max = 2,
522 .rates = 0,
523 .formats = CS4270_FORMATS,
524 },
525 .ops = {
526 .hw_params = cs4270_hw_params,
527 .set_sysclk = cs4270_set_dai_sysclk,
528 .set_fmt = cs4270_set_dai_fmt,
529 .digital_mute = cs4270_mute,
530 },
531};
532EXPORT_SYMBOL_GPL(cs4270_dai);
533
507/* 534/*
508 * Initialize the I2C interface of the CS4270 535 * Initialize the I2C interface of the CS4270
509 * 536 *
@@ -517,47 +544,52 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
517 const struct i2c_device_id *id) 544 const struct i2c_device_id *id)
518{ 545{
519 struct snd_soc_device *socdev = cs4270_socdev; 546 struct snd_soc_device *socdev = cs4270_socdev;
520 struct snd_soc_codec *codec = socdev->codec; 547 struct snd_soc_codec *codec;
548 struct cs4270_private *cs4270;
521 int i; 549 int i;
522 int ret = 0; 550 int ret = 0;
523 551
524 /* Probing all possible addresses has one drawback: if there are
525 multiple CS4270s on the bus, then you cannot specify which
526 socdev is matched with which CS4270. For now, we just reject
527 this I2C device if the socdev already has one attached. */
528 if (codec->control_data)
529 return -ENODEV;
530
531 /* Note: codec_dai->codec is NULL here */
532
533 codec->reg_cache = kzalloc(CS4270_NUMREGS, GFP_KERNEL);
534 if (!codec->reg_cache) {
535 printk(KERN_ERR "cs4270: could not allocate register cache\n");
536 ret = -ENOMEM;
537 goto error;
538 }
539
540 /* Verify that we have a CS4270 */ 552 /* Verify that we have a CS4270 */
541 553
542 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); 554 ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID);
543 if (ret < 0) { 555 if (ret < 0) {
544 printk(KERN_ERR "cs4270: failed to read I2C\n"); 556 printk(KERN_ERR "cs4270: failed to read I2C\n");
545 goto error; 557 return ret;
546 } 558 }
547 /* The top four bits of the chip ID should be 1100. */ 559 /* The top four bits of the chip ID should be 1100. */
548 if ((ret & 0xF0) != 0xC0) { 560 if ((ret & 0xF0) != 0xC0) {
549 /* The device at this address is not a CS4270 codec */ 561 printk(KERN_ERR "cs4270: device at addr %X is not a CS4270\n",
550 ret = -ENODEV; 562 i2c_client->addr);
551 goto error; 563 return -ENODEV;
552 } 564 }
553 565
554 printk(KERN_INFO "cs4270: found device at I2C address %X\n", 566 printk(KERN_INFO "cs4270: found device at I2C address %X\n",
555 i2c_client->addr); 567 i2c_client->addr);
556 printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF); 568 printk(KERN_INFO "cs4270: hardware revision %X\n", ret & 0xF);
557 569
570 /* Allocate enough space for the snd_soc_codec structure
571 and our private data together. */
572 cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
573 if (!cs4270) {
574 printk(KERN_ERR "cs4270: Could not allocate codec structure\n");
575 return -ENOMEM;
576 }
577 codec = &cs4270->codec;
578 socdev->codec = codec;
579
580 mutex_init(&codec->mutex);
581 INIT_LIST_HEAD(&codec->dapm_widgets);
582 INIT_LIST_HEAD(&codec->dapm_paths);
583
584 codec->name = "CS4270";
585 codec->owner = THIS_MODULE;
586 codec->dai = &cs4270_dai;
587 codec->num_dai = 1;
588 codec->private_data = cs4270;
558 codec->control_data = i2c_client; 589 codec->control_data = i2c_client;
559 codec->read = cs4270_read_reg_cache; 590 codec->read = cs4270_read_reg_cache;
560 codec->write = cs4270_i2c_write; 591 codec->write = cs4270_i2c_write;
592 codec->reg_cache = cs4270->reg_cache;
561 codec->reg_cache_size = CS4270_NUMREGS; 593 codec->reg_cache_size = CS4270_NUMREGS;
562 594
563 /* The I2C interface is set up, so pre-fill our register cache */ 595 /* The I2C interface is set up, so pre-fill our register cache */
@@ -565,35 +597,72 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
565 ret = cs4270_fill_cache(codec); 597 ret = cs4270_fill_cache(codec);
566 if (ret < 0) { 598 if (ret < 0) {
567 printk(KERN_ERR "cs4270: failed to fill register cache\n"); 599 printk(KERN_ERR "cs4270: failed to fill register cache\n");
568 goto error; 600 goto error_free_codec;
601 }
602
603 /* Register PCMs */
604
605 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
606 if (ret < 0) {
607 printk(KERN_ERR "cs4270: failed to create PCMs\n");
608 goto error_free_codec;
569 } 609 }
570 610
571 /* Add the non-DAPM controls */ 611 /* Add the non-DAPM controls */
572 612
573 for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) { 613 for (i = 0; i < ARRAY_SIZE(cs4270_snd_controls); i++) {
574 struct snd_kcontrol *kctrl = 614 struct snd_kcontrol *kctrl;
575 snd_soc_cnew(&cs4270_snd_controls[i], codec, NULL); 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 }
576 623
577 ret = snd_ctl_add(codec->card, kctrl); 624 ret = snd_ctl_add(codec->card, kctrl);
578 if (ret < 0) 625 if (ret < 0) {
579 goto error; 626 printk(KERN_ERR "cs4270: error adding control '%s'\n",
627 cs4270_snd_controls[i].name);
628 goto error_free_pcms;
629 }
580 } 630 }
581 631
582 i2c_set_clientdata(i2c_client, codec); 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);
583 641
584 return 0; 642 return 0;
585 643
586error: 644error_free_pcms:
587 codec->control_data = NULL; 645 snd_soc_free_pcms(socdev);
588 646
589 kfree(codec->reg_cache); 647error_free_codec:
590 codec->reg_cache = NULL; 648 kfree(cs4270);
591 codec->reg_cache_size = 0;
592 649
593 return ret; 650 return ret;
594} 651}
595 652
596static const struct i2c_device_id cs4270_id[] = { 653static int cs4270_i2c_remove(struct i2c_client *i2c_client)
654{
655 struct snd_soc_device *socdev = i2c_get_clientdata(i2c_client);
656 struct snd_soc_codec *codec = socdev->codec;
657 struct cs4270_private *cs4270 = codec->private_data;
658
659 snd_soc_free_pcms(socdev);
660 kfree(cs4270);
661
662 return 0;
663}
664
665static struct i2c_device_id cs4270_id[] = {
597 {"cs4270", 0}, 666 {"cs4270", 0},
598 {} 667 {}
599}; 668};
@@ -606,27 +675,9 @@ static struct i2c_driver cs4270_i2c_driver = {
606 }, 675 },
607 .id_table = cs4270_id, 676 .id_table = cs4270_id,
608 .probe = cs4270_i2c_probe, 677 .probe = cs4270_i2c_probe,
678 .remove = cs4270_i2c_remove,
609}; 679};
610 680
611struct snd_soc_dai cs4270_dai = {
612 .name = "CS4270",
613 .playback = {
614 .stream_name = "Playback",
615 .channels_min = 1,
616 .channels_max = 2,
617 .rates = 0,
618 .formats = CS4270_FORMATS,
619 },
620 .capture = {
621 .stream_name = "Capture",
622 .channels_min = 1,
623 .channels_max = 2,
624 .rates = 0,
625 .formats = CS4270_FORMATS,
626 },
627};
628EXPORT_SYMBOL_GPL(cs4270_dai);
629
630/* 681/*
631 * ASoC probe function 682 * ASoC probe function
632 * 683 *
@@ -635,94 +686,15 @@ EXPORT_SYMBOL_GPL(cs4270_dai);
635 */ 686 */
636static int cs4270_probe(struct platform_device *pdev) 687static int cs4270_probe(struct platform_device *pdev)
637{ 688{
638 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 689 cs4270_socdev = platform_get_drvdata(pdev);;
639 struct snd_soc_codec *codec;
640 int ret = 0;
641
642 printk(KERN_INFO "CS4270 ALSA SoC Codec\n");
643
644 /* Allocate enough space for the snd_soc_codec structure
645 and our private data together. */
646 codec = kzalloc(ALIGN(sizeof(struct snd_soc_codec), 4) +
647 sizeof(struct cs4270_private), GFP_KERNEL);
648 if (!codec) {
649 printk(KERN_ERR "cs4270: Could not allocate codec structure\n");
650 return -ENOMEM;
651 }
652
653 mutex_init(&codec->mutex);
654 INIT_LIST_HEAD(&codec->dapm_widgets);
655 INIT_LIST_HEAD(&codec->dapm_paths);
656
657 codec->name = "CS4270";
658 codec->owner = THIS_MODULE;
659 codec->dai = &cs4270_dai;
660 codec->num_dai = 1;
661 codec->private_data = (void *) codec +
662 ALIGN(sizeof(struct snd_soc_codec), 4);
663
664 socdev->codec = codec;
665
666 /* Register PCMs */
667
668 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
669 if (ret < 0) {
670 printk(KERN_ERR "cs4270: failed to create PCMs\n");
671 goto error_free_codec;
672 }
673
674 cs4270_socdev = socdev;
675
676 ret = i2c_add_driver(&cs4270_i2c_driver);
677 if (ret) {
678 printk(KERN_ERR "cs4270: failed to attach driver");
679 goto error_free_pcms;
680 }
681
682 /* Did we find a CS4270 on the I2C bus? */
683 if (!codec->control_data) {
684 printk(KERN_ERR "cs4270: failed to attach driver");
685 goto error_del_driver;
686 }
687 690
688 /* Initialize codec ops */ 691 return i2c_add_driver(&cs4270_i2c_driver);
689 cs4270_dai.ops.hw_params = cs4270_hw_params;
690 cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
691 cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
692 cs4270_dai.ops.digital_mute = cs4270_mute;
693
694 ret = snd_soc_init_card(socdev);
695 if (ret < 0) {
696 printk(KERN_ERR "cs4270: failed to register card\n");
697 goto error_del_driver;
698 }
699
700 return 0;
701
702error_del_driver:
703 i2c_del_driver(&cs4270_i2c_driver);
704
705error_free_pcms:
706 snd_soc_free_pcms(socdev);
707
708error_free_codec:
709 kfree(socdev->codec);
710 socdev->codec = NULL;
711
712 return ret;
713} 692}
714 693
715static int cs4270_remove(struct platform_device *pdev) 694static int cs4270_remove(struct platform_device *pdev)
716{ 695{
717 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
718
719 snd_soc_free_pcms(socdev);
720
721 i2c_del_driver(&cs4270_i2c_driver); 696 i2c_del_driver(&cs4270_i2c_driver);
722 697
723 kfree(socdev->codec);
724 socdev->codec = NULL;
725
726 return 0; 698 return 0;
727} 699}
728 700
@@ -740,6 +712,8 @@ EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
740 712
741static int __init cs4270_init(void) 713static int __init cs4270_init(void)
742{ 714{
715 printk(KERN_INFO "Cirrus Logic CS4270 ALSA SoC Codec Driver\n");
716
743 return snd_soc_register_dai(&cs4270_dai); 717 return snd_soc_register_dai(&cs4270_dai);
744} 718}
745module_init(cs4270_init); 719module_init(cs4270_init);