aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tlv320aic23.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tlv320aic23.c')
-rw-r--r--sound/soc/codecs/tlv320aic23.c182
1 files changed, 60 insertions, 122 deletions
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 0a4b0fef3355..e8652b1ae326 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -240,7 +240,8 @@ static const struct snd_soc_dapm_route intercon[] = {
240 240
241/* AIC23 driver data */ 241/* AIC23 driver data */
242struct aic23 { 242struct aic23 {
243 struct snd_soc_codec codec; 243 enum snd_soc_control_type control_type;
244 void *control_data;
244 int mclk; 245 int mclk;
245 int requested_adc; 246 int requested_adc;
246 int requested_dac; 247 int requested_dac;
@@ -404,11 +405,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
404 struct snd_soc_dai *dai) 405 struct snd_soc_dai *dai)
405{ 406{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data; 407 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 struct snd_soc_device *socdev = rtd->socdev; 408 struct snd_soc_codec *codec = rtd->codec;
408 struct snd_soc_codec *codec = socdev->card->codec;
409 u16 iface_reg; 409 u16 iface_reg;
410 int ret; 410 int ret;
411 struct aic23 *aic23 = container_of(codec, struct aic23, codec); 411 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
412 u32 sample_rate_adc = aic23->requested_adc; 412 u32 sample_rate_adc = aic23->requested_adc;
413 u32 sample_rate_dac = aic23->requested_dac; 413 u32 sample_rate_dac = aic23->requested_dac;
414 u32 sample_rate = params_rate(params); 414 u32 sample_rate = params_rate(params);
@@ -452,8 +452,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
452 struct snd_soc_dai *dai) 452 struct snd_soc_dai *dai)
453{ 453{
454 struct snd_soc_pcm_runtime *rtd = substream->private_data; 454 struct snd_soc_pcm_runtime *rtd = substream->private_data;
455 struct snd_soc_device *socdev = rtd->socdev; 455 struct snd_soc_codec *codec = rtd->codec;
456 struct snd_soc_codec *codec = socdev->card->codec;
457 456
458 /* set active */ 457 /* set active */
459 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); 458 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -465,9 +464,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
465 struct snd_soc_dai *dai) 464 struct snd_soc_dai *dai)
466{ 465{
467 struct snd_soc_pcm_runtime *rtd = substream->private_data; 466 struct snd_soc_pcm_runtime *rtd = substream->private_data;
468 struct snd_soc_device *socdev = rtd->socdev; 467 struct snd_soc_codec *codec = rtd->codec;
469 struct snd_soc_codec *codec = socdev->card->codec; 468 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
470 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
471 469
472 /* deactivate */ 470 /* deactivate */
473 if (!codec->active) { 471 if (!codec->active) {
@@ -546,8 +544,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
546static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, 544static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
547 int clk_id, unsigned int freq, int dir) 545 int clk_id, unsigned int freq, int dir)
548{ 546{
549 struct snd_soc_codec *codec = codec_dai->codec; 547 struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
550 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
551 aic23->mclk = freq; 548 aic23->mclk = freq;
552 return 0; 549 return 0;
553} 550}
@@ -594,8 +591,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
594 .set_sysclk = tlv320aic23_set_dai_sysclk, 591 .set_sysclk = tlv320aic23_set_dai_sysclk,
595}; 592};
596 593
597struct snd_soc_dai tlv320aic23_dai = { 594static struct snd_soc_dai_driver tlv320aic23_dai = {
598 .name = "tlv320aic23", 595 .name = "tlv320aic23-hifi",
599 .playback = { 596 .playback = {
600 .stream_name = "Playback", 597 .stream_name = "Playback",
601 .channels_min = 2, 598 .channels_min = 2,
@@ -610,23 +607,17 @@ struct snd_soc_dai tlv320aic23_dai = {
610 .formats = AIC23_FORMATS,}, 607 .formats = AIC23_FORMATS,},
611 .ops = &tlv320aic23_dai_ops, 608 .ops = &tlv320aic23_dai_ops,
612}; 609};
613EXPORT_SYMBOL_GPL(tlv320aic23_dai);
614 610
615static int tlv320aic23_suspend(struct platform_device *pdev, 611static int tlv320aic23_suspend(struct snd_soc_codec *codec,
616 pm_message_t state) 612 pm_message_t state)
617{ 613{
618 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
619 struct snd_soc_codec *codec = socdev->card->codec;
620
621 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); 614 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
622 615
623 return 0; 616 return 0;
624} 617}
625 618
626static int tlv320aic23_resume(struct platform_device *pdev) 619static int tlv320aic23_resume(struct snd_soc_codec *codec)
627{ 620{
628 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
629 struct snd_soc_codec *codec = socdev->card->codec;
630 u16 reg; 621 u16 reg;
631 622
632 /* Sync reg_cache with the hardware */ 623 /* Sync reg_cache with the hardware */
@@ -639,39 +630,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)
639 return 0; 630 return 0;
640} 631}
641 632
642/* 633static int tlv320aic23_probe(struct snd_soc_codec *codec)
643 * initialise the AIC23 driver
644 * register the mixer and dsp interfaces with the kernel
645 */
646static int tlv320aic23_init(struct snd_soc_device *socdev)
647{ 634{
648 struct snd_soc_codec *codec = socdev->card->codec; 635 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
649 int ret = 0; 636 int reg;
650 u16 reg;
651 637
652 codec->name = "tlv320aic23"; 638 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
653 codec->owner = THIS_MODULE; 639 codec->control_data = aic23->control_data;
654 codec->read = tlv320aic23_read_reg_cache; 640 codec->hw_write = (hw_write_t)i2c_master_send;
655 codec->write = tlv320aic23_write; 641 codec->hw_read = NULL;
656 codec->set_bias_level = tlv320aic23_set_bias_level;
657 codec->dai = &tlv320aic23_dai;
658 codec->num_dai = 1;
659 codec->reg_cache_size = ARRAY_SIZE(tlv320aic23_reg);
660 codec->reg_cache =
661 kmemdup(tlv320aic23_reg, sizeof(tlv320aic23_reg), GFP_KERNEL);
662 if (codec->reg_cache == NULL)
663 return -ENOMEM;
664 642
665 /* Reset codec */ 643 /* Reset codec */
666 tlv320aic23_write(codec, TLV320AIC23_RESET, 0); 644 tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
667 645
668 /* register pcms */
669 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
670 if (ret < 0) {
671 printk(KERN_ERR "tlv320aic23: failed to create pcms\n");
672 goto pcm_err;
673 }
674
675 /* power on device */ 646 /* power on device */
676 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 647 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
677 648
@@ -707,13 +678,27 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
707 ARRAY_SIZE(tlv320aic23_snd_controls)); 678 ARRAY_SIZE(tlv320aic23_snd_controls));
708 tlv320aic23_add_widgets(codec); 679 tlv320aic23_add_widgets(codec);
709 680
710 return ret; 681 return 0;
682}
711 683
712pcm_err: 684static int tlv320aic23_remove(struct snd_soc_codec *codec)
713 kfree(codec->reg_cache); 685{
714 return ret; 686 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
687 return 0;
715} 688}
716static struct snd_soc_device *tlv320aic23_socdev; 689
690static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
691 .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
692 .reg_word_size = sizeof(u16),
693 .reg_cache_default = tlv320aic23_reg,
694 .probe = tlv320aic23_probe,
695 .remove = tlv320aic23_remove,
696 .suspend = tlv320aic23_suspend,
697 .resume = tlv320aic23_resume,
698 .read = tlv320aic23_read_reg_cache,
699 .write = tlv320aic23_write,
700 .set_bias_level = tlv320aic23_set_bias_level,
701};
717 702
718#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 703#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
719/* 704/*
@@ -723,31 +708,30 @@ static struct snd_soc_device *tlv320aic23_socdev;
723static int tlv320aic23_codec_probe(struct i2c_client *i2c, 708static int tlv320aic23_codec_probe(struct i2c_client *i2c,
724 const struct i2c_device_id *i2c_id) 709 const struct i2c_device_id *i2c_id)
725{ 710{
726 struct snd_soc_device *socdev = tlv320aic23_socdev; 711 struct aic23 *aic23;
727 struct snd_soc_codec *codec = socdev->card->codec;
728 int ret; 712 int ret;
729 713
730 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 714 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
731 return -EINVAL; 715 return -EINVAL;
732 716
733 i2c_set_clientdata(i2c, codec); 717 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
734 codec->control_data = i2c; 718 if (aic23 == NULL)
719 return -ENOMEM;
735 720
736 ret = tlv320aic23_init(socdev); 721 i2c_set_clientdata(i2c, aic23);
737 if (ret < 0) { 722 aic23->control_data = i2c;
738 printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); 723 aic23->control_type = SND_SOC_I2C;
739 goto err;
740 }
741 return ret;
742 724
743err: 725 ret = snd_soc_register_codec(&i2c->dev,
744 kfree(codec); 726 &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
745 kfree(i2c); 727 if (ret < 0)
728 kfree(aic23);
746 return ret; 729 return ret;
747} 730}
748static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) 731static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
749{ 732{
750 put_device(&i2c->dev); 733 snd_soc_unregister_codec(&i2c->dev);
734 kfree(i2c_get_clientdata(i2c));
751 return 0; 735 return 0;
752} 736}
753 737
@@ -760,7 +744,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
760 744
761static struct i2c_driver tlv320aic23_i2c_driver = { 745static struct i2c_driver tlv320aic23_i2c_driver = {
762 .driver = { 746 .driver = {
763 .name = "tlv320aic23", 747 .name = "tlv320aic23-codec",
764 }, 748 },
765 .probe = tlv320aic23_codec_probe, 749 .probe = tlv320aic23_codec_probe,
766 .remove = __exit_p(tlv320aic23_i2c_remove), 750 .remove = __exit_p(tlv320aic23_i2c_remove),
@@ -769,71 +753,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
769 753
770#endif 754#endif
771 755
772static int tlv320aic23_probe(struct platform_device *pdev) 756static int __init tlv320aic23_modinit(void)
773{ 757{
774 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 758 int ret;
775 struct snd_soc_codec *codec;
776 struct aic23 *aic23;
777 int ret = 0;
778
779 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
780
781 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
782 if (aic23 == NULL)
783 return -ENOMEM;
784 codec = &aic23->codec;
785 socdev->card->codec = codec;
786 mutex_init(&codec->mutex);
787 INIT_LIST_HEAD(&codec->dapm_widgets);
788 INIT_LIST_HEAD(&codec->dapm_paths);
789
790 tlv320aic23_socdev = socdev;
791#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 759#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
792 codec->hw_write = (hw_write_t) i2c_master_send;
793 codec->hw_read = NULL;
794 ret = i2c_add_driver(&tlv320aic23_i2c_driver); 760 ret = i2c_add_driver(&tlv320aic23_i2c_driver);
795 if (ret != 0) 761 if (ret != 0) {
796 printk(KERN_ERR "can't add i2c driver"); 762 printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
763 ret);
764 }
797#endif 765#endif
798 return ret; 766 return ret;
799} 767}
768module_init(tlv320aic23_modinit);
800 769
801static int tlv320aic23_remove(struct platform_device *pdev) 770static void __exit tlv320aic23_exit(void)
802{ 771{
803 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
804 struct snd_soc_codec *codec = socdev->card->codec;
805 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
806
807 if (codec->control_data)
808 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
809
810 snd_soc_free_pcms(socdev);
811 snd_soc_dapm_free(socdev);
812#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 772#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
813 i2c_del_driver(&tlv320aic23_i2c_driver); 773 i2c_del_driver(&tlv320aic23_i2c_driver);
814#endif 774#endif
815 kfree(codec->reg_cache);
816 kfree(aic23);
817
818 return 0;
819}
820struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
821 .probe = tlv320aic23_probe,
822 .remove = tlv320aic23_remove,
823 .suspend = tlv320aic23_suspend,
824 .resume = tlv320aic23_resume,
825};
826EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
827
828static int __init tlv320aic23_modinit(void)
829{
830 return snd_soc_register_dai(&tlv320aic23_dai);
831}
832module_init(tlv320aic23_modinit);
833
834static void __exit tlv320aic23_exit(void)
835{
836 snd_soc_unregister_dai(&tlv320aic23_dai);
837} 775}
838module_exit(tlv320aic23_exit); 776module_exit(tlv320aic23_exit);
839 777