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.c203
1 files changed, 66 insertions, 137 deletions
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 0a4b0fef3355..33bb52f3f683 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -30,7 +30,6 @@
30#include <sound/pcm.h> 30#include <sound/pcm.h>
31#include <sound/pcm_params.h> 31#include <sound/pcm_params.h>
32#include <sound/soc.h> 32#include <sound/soc.h>
33#include <sound/soc-dapm.h>
34#include <sound/tlv.h> 33#include <sound/tlv.h>
35#include <sound/initval.h> 34#include <sound/initval.h>
36 35
@@ -213,7 +212,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
213 SND_SOC_DAPM_INPUT("MICIN"), 212 SND_SOC_DAPM_INPUT("MICIN"),
214}; 213};
215 214
216static const struct snd_soc_dapm_route intercon[] = { 215static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
217 /* Output Mixer */ 216 /* Output Mixer */
218 {"Output Mixer", "Line Bypass Switch", "Line Input"}, 217 {"Output Mixer", "Line Bypass Switch", "Line Input"},
219 {"Output Mixer", "Playback Switch", "DAC"}, 218 {"Output Mixer", "Playback Switch", "DAC"},
@@ -240,7 +239,8 @@ static const struct snd_soc_dapm_route intercon[] = {
240 239
241/* AIC23 driver data */ 240/* AIC23 driver data */
242struct aic23 { 241struct aic23 {
243 struct snd_soc_codec codec; 242 enum snd_soc_control_type control_type;
243 void *control_data;
244 int mclk; 244 int mclk;
245 int requested_adc; 245 int requested_adc;
246 int requested_dac; 246 int requested_dac;
@@ -388,27 +388,15 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
388 return 0; 388 return 0;
389} 389}
390 390
391static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
392{
393 snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
394 ARRAY_SIZE(tlv320aic23_dapm_widgets));
395
396 /* set up audio path interconnects */
397 snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
398
399 return 0;
400}
401
402static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, 391static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
403 struct snd_pcm_hw_params *params, 392 struct snd_pcm_hw_params *params,
404 struct snd_soc_dai *dai) 393 struct snd_soc_dai *dai)
405{ 394{
406 struct snd_soc_pcm_runtime *rtd = substream->private_data; 395 struct snd_soc_pcm_runtime *rtd = substream->private_data;
407 struct snd_soc_device *socdev = rtd->socdev; 396 struct snd_soc_codec *codec = rtd->codec;
408 struct snd_soc_codec *codec = socdev->card->codec;
409 u16 iface_reg; 397 u16 iface_reg;
410 int ret; 398 int ret;
411 struct aic23 *aic23 = container_of(codec, struct aic23, codec); 399 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
412 u32 sample_rate_adc = aic23->requested_adc; 400 u32 sample_rate_adc = aic23->requested_adc;
413 u32 sample_rate_dac = aic23->requested_dac; 401 u32 sample_rate_dac = aic23->requested_dac;
414 u32 sample_rate = params_rate(params); 402 u32 sample_rate = params_rate(params);
@@ -452,8 +440,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
452 struct snd_soc_dai *dai) 440 struct snd_soc_dai *dai)
453{ 441{
454 struct snd_soc_pcm_runtime *rtd = substream->private_data; 442 struct snd_soc_pcm_runtime *rtd = substream->private_data;
455 struct snd_soc_device *socdev = rtd->socdev; 443 struct snd_soc_codec *codec = rtd->codec;
456 struct snd_soc_codec *codec = socdev->card->codec;
457 444
458 /* set active */ 445 /* set active */
459 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); 446 tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
@@ -465,9 +452,8 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
465 struct snd_soc_dai *dai) 452 struct snd_soc_dai *dai)
466{ 453{
467 struct snd_soc_pcm_runtime *rtd = substream->private_data; 454 struct snd_soc_pcm_runtime *rtd = substream->private_data;
468 struct snd_soc_device *socdev = rtd->socdev; 455 struct snd_soc_codec *codec = rtd->codec;
469 struct snd_soc_codec *codec = socdev->card->codec; 456 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
470 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
471 457
472 /* deactivate */ 458 /* deactivate */
473 if (!codec->active) { 459 if (!codec->active) {
@@ -546,8 +532,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, 532static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
547 int clk_id, unsigned int freq, int dir) 533 int clk_id, unsigned int freq, int dir)
548{ 534{
549 struct snd_soc_codec *codec = codec_dai->codec; 535 struct aic23 *aic23 = snd_soc_dai_get_drvdata(codec_dai);
550 struct aic23 *aic23 = container_of(codec, struct aic23, codec);
551 aic23->mclk = freq; 536 aic23->mclk = freq;
552 return 0; 537 return 0;
553} 538}
@@ -577,7 +562,7 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
577 tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff); 562 tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
578 break; 563 break;
579 } 564 }
580 codec->bias_level = level; 565 codec->dapm.bias_level = level;
581 return 0; 566 return 0;
582} 567}
583 568
@@ -594,8 +579,8 @@ static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
594 .set_sysclk = tlv320aic23_set_dai_sysclk, 579 .set_sysclk = tlv320aic23_set_dai_sysclk,
595}; 580};
596 581
597struct snd_soc_dai tlv320aic23_dai = { 582static struct snd_soc_dai_driver tlv320aic23_dai = {
598 .name = "tlv320aic23", 583 .name = "tlv320aic23-hifi",
599 .playback = { 584 .playback = {
600 .stream_name = "Playback", 585 .stream_name = "Playback",
601 .channels_min = 2, 586 .channels_min = 2,
@@ -610,23 +595,17 @@ struct snd_soc_dai tlv320aic23_dai = {
610 .formats = AIC23_FORMATS,}, 595 .formats = AIC23_FORMATS,},
611 .ops = &tlv320aic23_dai_ops, 596 .ops = &tlv320aic23_dai_ops,
612}; 597};
613EXPORT_SYMBOL_GPL(tlv320aic23_dai);
614 598
615static int tlv320aic23_suspend(struct platform_device *pdev, 599static int tlv320aic23_suspend(struct snd_soc_codec *codec,
616 pm_message_t state) 600 pm_message_t state)
617{ 601{
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); 602 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
622 603
623 return 0; 604 return 0;
624} 605}
625 606
626static int tlv320aic23_resume(struct platform_device *pdev) 607static int tlv320aic23_resume(struct snd_soc_codec *codec)
627{ 608{
628 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
629 struct snd_soc_codec *codec = socdev->card->codec;
630 u16 reg; 609 u16 reg;
631 610
632 /* Sync reg_cache with the hardware */ 611 /* Sync reg_cache with the hardware */
@@ -639,39 +618,19 @@ static int tlv320aic23_resume(struct platform_device *pdev)
639 return 0; 618 return 0;
640} 619}
641 620
642/* 621static 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{ 622{
648 struct snd_soc_codec *codec = socdev->card->codec; 623 struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
649 int ret = 0; 624 int reg;
650 u16 reg;
651 625
652 codec->name = "tlv320aic23"; 626 printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
653 codec->owner = THIS_MODULE; 627 codec->control_data = aic23->control_data;
654 codec->read = tlv320aic23_read_reg_cache; 628 codec->hw_write = (hw_write_t)i2c_master_send;
655 codec->write = tlv320aic23_write; 629 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 630
665 /* Reset codec */ 631 /* Reset codec */
666 tlv320aic23_write(codec, TLV320AIC23_RESET, 0); 632 tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
667 633
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 */ 634 /* power on device */
676 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 635 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
677 636
@@ -705,15 +664,32 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
705 664
706 snd_soc_add_controls(codec, tlv320aic23_snd_controls, 665 snd_soc_add_controls(codec, tlv320aic23_snd_controls,
707 ARRAY_SIZE(tlv320aic23_snd_controls)); 666 ARRAY_SIZE(tlv320aic23_snd_controls));
708 tlv320aic23_add_widgets(codec);
709 667
710 return ret; 668 return 0;
669}
711 670
712pcm_err: 671static int tlv320aic23_remove(struct snd_soc_codec *codec)
713 kfree(codec->reg_cache); 672{
714 return ret; 673 tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
674 return 0;
715} 675}
716static struct snd_soc_device *tlv320aic23_socdev; 676
677static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
678 .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg),
679 .reg_word_size = sizeof(u16),
680 .reg_cache_default = tlv320aic23_reg,
681 .probe = tlv320aic23_probe,
682 .remove = tlv320aic23_remove,
683 .suspend = tlv320aic23_suspend,
684 .resume = tlv320aic23_resume,
685 .read = tlv320aic23_read_reg_cache,
686 .write = tlv320aic23_write,
687 .set_bias_level = tlv320aic23_set_bias_level,
688 .dapm_widgets = tlv320aic23_dapm_widgets,
689 .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
690 .dapm_routes = tlv320aic23_intercon,
691 .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon),
692};
717 693
718#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 694#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
719/* 695/*
@@ -723,31 +699,30 @@ static struct snd_soc_device *tlv320aic23_socdev;
723static int tlv320aic23_codec_probe(struct i2c_client *i2c, 699static int tlv320aic23_codec_probe(struct i2c_client *i2c,
724 const struct i2c_device_id *i2c_id) 700 const struct i2c_device_id *i2c_id)
725{ 701{
726 struct snd_soc_device *socdev = tlv320aic23_socdev; 702 struct aic23 *aic23;
727 struct snd_soc_codec *codec = socdev->card->codec;
728 int ret; 703 int ret;
729 704
730 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) 705 if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
731 return -EINVAL; 706 return -EINVAL;
732 707
733 i2c_set_clientdata(i2c, codec); 708 aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
734 codec->control_data = i2c; 709 if (aic23 == NULL)
710 return -ENOMEM;
735 711
736 ret = tlv320aic23_init(socdev); 712 i2c_set_clientdata(i2c, aic23);
737 if (ret < 0) { 713 aic23->control_data = i2c;
738 printk(KERN_ERR "tlv320aic23: failed to initialise AIC23\n"); 714 aic23->control_type = SND_SOC_I2C;
739 goto err;
740 }
741 return ret;
742 715
743err: 716 ret = snd_soc_register_codec(&i2c->dev,
744 kfree(codec); 717 &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
745 kfree(i2c); 718 if (ret < 0)
719 kfree(aic23);
746 return ret; 720 return ret;
747} 721}
748static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) 722static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
749{ 723{
750 put_device(&i2c->dev); 724 snd_soc_unregister_codec(&i2c->dev);
725 kfree(i2c_get_clientdata(i2c));
751 return 0; 726 return 0;
752} 727}
753 728
@@ -760,7 +735,7 @@ MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
760 735
761static struct i2c_driver tlv320aic23_i2c_driver = { 736static struct i2c_driver tlv320aic23_i2c_driver = {
762 .driver = { 737 .driver = {
763 .name = "tlv320aic23", 738 .name = "tlv320aic23-codec",
764 }, 739 },
765 .probe = tlv320aic23_codec_probe, 740 .probe = tlv320aic23_codec_probe,
766 .remove = __exit_p(tlv320aic23_i2c_remove), 741 .remove = __exit_p(tlv320aic23_i2c_remove),
@@ -769,71 +744,25 @@ static struct i2c_driver tlv320aic23_i2c_driver = {
769 744
770#endif 745#endif
771 746
772static int tlv320aic23_probe(struct platform_device *pdev) 747static int __init tlv320aic23_modinit(void)
773{ 748{
774 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 749 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) 750#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); 751 ret = i2c_add_driver(&tlv320aic23_i2c_driver);
795 if (ret != 0) 752 if (ret != 0) {
796 printk(KERN_ERR "can't add i2c driver"); 753 printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n",
754 ret);
755 }
797#endif 756#endif
798 return ret; 757 return ret;
799} 758}
759module_init(tlv320aic23_modinit);
800 760
801static int tlv320aic23_remove(struct platform_device *pdev) 761static void __exit tlv320aic23_exit(void)
802{ 762{
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) 763#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
813 i2c_del_driver(&tlv320aic23_i2c_driver); 764 i2c_del_driver(&tlv320aic23_i2c_driver);
814#endif 765#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} 766}
838module_exit(tlv320aic23_exit); 767module_exit(tlv320aic23_exit);
839 768