aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8750.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8750.c')
-rw-r--r--sound/soc/codecs/wm8750.c269
1 files changed, 84 insertions, 185 deletions
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index e2c05e3e323a..89863a5bc830 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -52,7 +52,8 @@ static const u16 wm8750_reg[] = {
52/* codec private data */ 52/* codec private data */
53struct wm8750_priv { 53struct wm8750_priv {
54 unsigned int sysclk; 54 unsigned int sysclk;
55 struct snd_soc_codec codec; 55 enum snd_soc_control_type control_type;
56 void *control_data;
56 u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; 57 u16 reg_cache[ARRAY_SIZE(wm8750_reg)];
57}; 58};
58 59
@@ -560,8 +561,7 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
560 struct snd_soc_dai *dai) 561 struct snd_soc_dai *dai)
561{ 562{
562 struct snd_soc_pcm_runtime *rtd = substream->private_data; 563 struct snd_soc_pcm_runtime *rtd = substream->private_data;
563 struct snd_soc_device *socdev = rtd->socdev; 564 struct snd_soc_codec *codec = rtd->codec;
564 struct snd_soc_codec *codec = socdev->card->codec;
565 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec); 565 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3; 566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0; 567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
@@ -649,8 +649,8 @@ static struct snd_soc_dai_ops wm8750_dai_ops = {
649 .set_sysclk = wm8750_set_dai_sysclk, 649 .set_sysclk = wm8750_set_dai_sysclk,
650}; 650};
651 651
652struct snd_soc_dai wm8750_dai = { 652static struct snd_soc_dai_driver wm8750_dai = {
653 .name = "WM8750", 653 .name = "wm8750-hifi",
654 .playback = { 654 .playback = {
655 .stream_name = "Playback", 655 .stream_name = "Playback",
656 .channels_min = 1, 656 .channels_min = 1,
@@ -665,21 +665,15 @@ struct snd_soc_dai wm8750_dai = {
665 .formats = WM8750_FORMATS,}, 665 .formats = WM8750_FORMATS,},
666 .ops = &wm8750_dai_ops, 666 .ops = &wm8750_dai_ops,
667}; 667};
668EXPORT_SYMBOL_GPL(wm8750_dai);
669 668
670static int wm8750_suspend(struct platform_device *pdev, pm_message_t state) 669static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
671{ 670{
672 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
673 struct snd_soc_codec *codec = socdev->card->codec;
674
675 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); 671 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
676 return 0; 672 return 0;
677} 673}
678 674
679static int wm8750_resume(struct platform_device *pdev) 675static int wm8750_resume(struct snd_soc_codec *codec)
680{ 676{
681 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
682 struct snd_soc_codec *codec = socdev->card->codec;
683 int i; 677 int i;
684 u8 data[2]; 678 u8 data[2];
685 u16 *cache = codec->reg_cache; 679 u16 *cache = codec->reg_cache;
@@ -698,100 +692,22 @@ static int wm8750_resume(struct platform_device *pdev)
698 return 0; 692 return 0;
699} 693}
700 694
701static struct snd_soc_codec *wm8750_codec; 695static int wm8750_probe(struct snd_soc_codec *codec)
702
703static int wm8750_probe(struct platform_device *pdev)
704{ 696{
705 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 697 struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
706 struct snd_soc_codec *codec; 698 int reg, ret;
707 int ret = 0;
708
709 if (!wm8750_codec) {
710 dev_err(&pdev->dev, "WM8750 codec not yet registered\n");
711 return -EINVAL;
712 }
713
714 socdev->card->codec = wm8750_codec;
715 codec = wm8750_codec;
716
717 /* register pcms */
718 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
719 if (ret < 0) {
720 printk(KERN_ERR "wm8750: failed to create pcms\n");
721 goto err;
722 }
723
724 snd_soc_add_controls(codec, wm8750_snd_controls,
725 ARRAY_SIZE(wm8750_snd_controls));
726 wm8750_add_widgets(codec);
727
728 return 0;
729
730err:
731 return ret;
732}
733
734/* power down chip */
735static int wm8750_remove(struct platform_device *pdev)
736{
737 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
738
739 snd_soc_free_pcms(socdev);
740 snd_soc_dapm_free(socdev);
741
742 return 0;
743}
744
745struct snd_soc_codec_device soc_codec_dev_wm8750 = {
746 .probe = wm8750_probe,
747 .remove = wm8750_remove,
748 .suspend = wm8750_suspend,
749 .resume = wm8750_resume,
750};
751EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
752
753/*
754 * initialise the WM8750 driver
755 * register the mixer and dsp interfaces with the kernel
756 */
757static int wm8750_register(struct wm8750_priv *wm8750,
758 enum snd_soc_control_type control)
759{
760 struct snd_soc_codec *codec = &wm8750->codec;
761 int reg, ret = 0;
762
763 if (wm8750_codec) {
764 dev_err(codec->dev, "Multiple WM8750 devices not supported\n");
765 ret = -EINVAL;
766 goto err;
767 }
768
769 mutex_init(&codec->mutex);
770 INIT_LIST_HEAD(&codec->dapm_widgets);
771 INIT_LIST_HEAD(&codec->dapm_paths);
772
773 codec->name = "WM8750";
774 codec->owner = THIS_MODULE;
775 codec->bias_level = SND_SOC_BIAS_STANDBY;
776 codec->set_bias_level = wm8750_set_bias_level;
777 codec->dai = &wm8750_dai;
778 codec->num_dai = 1;
779 codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1;
780 codec->reg_cache = &wm8750->reg_cache;
781 snd_soc_codec_set_drvdata(codec, wm8750);
782
783 memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache));
784 699
785 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 700 codec->control_data = wm8750->control_data;
701 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
786 if (ret < 0) { 702 if (ret < 0) {
787 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret); 703 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
788 goto err; 704 return ret;
789 } 705 }
790 706
791 ret = wm8750_reset(codec); 707 ret = wm8750_reset(codec);
792 if (ret < 0) { 708 if (ret < 0) {
793 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret); 709 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
794 goto err; 710 return ret;
795 } 711 }
796 712
797 /* charge output caps */ 713 /* charge output caps */
@@ -815,150 +731,133 @@ static int wm8750_register(struct wm8750_priv *wm8750,
815 reg = snd_soc_read(codec, WM8750_RINVOL); 731 reg = snd_soc_read(codec, WM8750_RINVOL);
816 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); 732 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
817 733
818 wm8750_codec = codec; 734 snd_soc_add_controls(codec, wm8750_snd_controls,
819 735 ARRAY_SIZE(wm8750_snd_controls));
820 ret = snd_soc_register_codec(codec); 736 wm8750_add_widgets(codec);
821 if (ret != 0) {
822 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
823 goto err;
824 }
825
826 ret = snd_soc_register_dais(&wm8750_dai, 1);
827 if (ret != 0) {
828 dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
829 goto err_codec;
830 }
831
832 return 0;
833
834err_codec:
835 snd_soc_unregister_codec(codec);
836err:
837 kfree(wm8750);
838 return ret; 737 return ret;
839} 738}
840 739
841static void wm8750_unregister(struct wm8750_priv *wm8750) 740static int wm8750_remove(struct snd_soc_codec *codec)
842{ 741{
843 wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); 742 wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
844 snd_soc_unregister_dais(&wm8750_dai, 1); 743 return 0;
845 snd_soc_unregister_codec(&wm8750->codec);
846 kfree(wm8750);
847 wm8750_codec = NULL;
848} 744}
849 745
850#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 746static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
851 747 .probe = wm8750_probe,
852/* 748 .remove = wm8750_remove,
853 * WM8750 2 wire address is determined by GPIO5 749 .suspend = wm8750_suspend,
854 * state during powerup. 750 .resume = wm8750_resume,
855 * low = 0x1a 751 .set_bias_level = wm8750_set_bias_level,
856 * high = 0x1b 752 .reg_cache_size = sizeof(wm8750_reg),
857 */ 753 .reg_word_size = sizeof(u16),
754 .reg_cache_default = wm8750_reg,
755};
858 756
859static int wm8750_i2c_probe(struct i2c_client *i2c, 757#if defined(CONFIG_SPI_MASTER)
860 const struct i2c_device_id *id) 758static int __devinit wm8750_spi_probe(struct spi_device *spi)
861{ 759{
862 struct snd_soc_codec *codec;
863 struct wm8750_priv *wm8750; 760 struct wm8750_priv *wm8750;
761 int ret;
864 762
865 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); 763 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
866 if (wm8750 == NULL) 764 if (wm8750 == NULL)
867 return -ENOMEM; 765 return -ENOMEM;
868 766
869 codec = &wm8750->codec; 767 wm8750->control_data = spi;
870 codec->control_data = i2c; 768 wm8750->control_type = SND_SOC_SPI;
871 i2c_set_clientdata(i2c, wm8750); 769 spi_set_drvdata(spi, wm8750);
872
873 codec->dev = &i2c->dev;
874 770
875 return wm8750_register(wm8750, SND_SOC_I2C); 771 ret = snd_soc_register_codec(&spi->dev,
772 &soc_codec_dev_wm8750, &wm8750_dai, 1);
773 if (ret < 0)
774 kfree(wm8750);
775 return ret;
876} 776}
877 777
878static int wm8750_i2c_remove(struct i2c_client *client) 778static int __devexit wm8750_spi_remove(struct spi_device *spi)
879{ 779{
880 struct wm8750_priv *wm8750 = i2c_get_clientdata(client); 780 snd_soc_unregister_codec(&spi->dev);
881 wm8750_unregister(wm8750); 781 kfree(spi_get_drvdata(spi));
882 return 0; 782 return 0;
883} 783}
884 784
885static const struct i2c_device_id wm8750_i2c_id[] = { 785static struct spi_driver wm8750_spi_driver = {
886 { "wm8750", 0 },
887 { "wm8987", 0 }, /* WM8987 is register compatible with WM8750 */
888 { }
889};
890MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
891
892static struct i2c_driver wm8750_i2c_driver = {
893 .driver = { 786 .driver = {
894 .name = "WM8750 I2C Codec", 787 .name = "wm8750-codec",
895 .owner = THIS_MODULE, 788 .bus = &spi_bus_type,
789 .owner = THIS_MODULE,
896 }, 790 },
897 .probe = wm8750_i2c_probe, 791 .probe = wm8750_spi_probe,
898 .remove = wm8750_i2c_remove, 792 .remove = __devexit_p(wm8750_spi_remove),
899 .id_table = wm8750_i2c_id,
900}; 793};
901#endif 794#endif /* CONFIG_SPI_MASTER */
902 795
903#if defined(CONFIG_SPI_MASTER) 796#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
904static int __devinit wm8750_spi_probe(struct spi_device *spi) 797static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
798 const struct i2c_device_id *id)
905{ 799{
906 struct snd_soc_codec *codec;
907 struct wm8750_priv *wm8750; 800 struct wm8750_priv *wm8750;
801 int ret;
908 802
909 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); 803 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
910 if (wm8750 == NULL) 804 if (wm8750 == NULL)
911 return -ENOMEM; 805 return -ENOMEM;
912 806
913 codec = &wm8750->codec; 807 i2c_set_clientdata(i2c, wm8750);
914 codec->control_data = spi; 808 wm8750->control_data = i2c;
915 codec->dev = &spi->dev; 809 wm8750->control_type = SND_SOC_I2C;
916
917 dev_set_drvdata(&spi->dev, wm8750);
918 810
919 return wm8750_register(wm8750, SND_SOC_SPI); 811 ret = snd_soc_register_codec(&i2c->dev,
812 &soc_codec_dev_wm8750, &wm8750_dai, 1);
813 if (ret < 0)
814 kfree(wm8750);
815 return ret;
920} 816}
921 817
922static int __devexit wm8750_spi_remove(struct spi_device *spi) 818static __devexit int wm8750_i2c_remove(struct i2c_client *client)
923{ 819{
924 struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); 820 snd_soc_unregister_codec(&client->dev);
925 wm8750_unregister(wm8750); 821 kfree(i2c_get_clientdata(client));
926 return 0; 822 return 0;
927} 823}
928 824
929static const struct spi_device_id wm8750_spi_id[] = { 825static const struct i2c_device_id wm8750_i2c_id[] = {
930 { "wm8750", 0 }, 826 { "wm8750", 0 },
931 { "wm8987", 0 }, 827 { "wm8987", 0 },
932 { } 828 { }
933}; 829};
934MODULE_DEVICE_TABLE(spi, wm8750_spi_id); 830MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
935 831
936static struct spi_driver wm8750_spi_driver = { 832static struct i2c_driver wm8750_i2c_driver = {
937 .driver = { 833 .driver = {
938 .name = "WM8750 SPI Codec", 834 .name = "wm8750-codec",
939 .bus = &spi_bus_type, 835 .owner = THIS_MODULE,
940 .owner = THIS_MODULE,
941 }, 836 },
942 .probe = wm8750_spi_probe, 837 .probe = wm8750_i2c_probe,
943 .remove = __devexit_p(wm8750_spi_remove), 838 .remove = __devexit_p(wm8750_i2c_remove),
944 .id_table = wm8750_spi_id, 839 .id_table = wm8750_i2c_id,
945}; 840};
946#endif 841#endif
947 842
948static int __init wm8750_modinit(void) 843static int __init wm8750_modinit(void)
949{ 844{
950 int ret; 845 int ret = 0;
951#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 846#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
952 ret = i2c_add_driver(&wm8750_i2c_driver); 847 ret = i2c_add_driver(&wm8750_i2c_driver);
953 if (ret != 0) 848 if (ret != 0) {
954 pr_err("Failed to register WM8750 I2C driver: %d\n", ret); 849 printk(KERN_ERR "Failed to register wm8750 I2C driver: %d\n",
850 ret);
851 }
955#endif 852#endif
956#if defined(CONFIG_SPI_MASTER) 853#if defined(CONFIG_SPI_MASTER)
957 ret = spi_register_driver(&wm8750_spi_driver); 854 ret = spi_register_driver(&wm8750_spi_driver);
958 if (ret != 0) 855 if (ret != 0) {
959 pr_err("Failed to register WM8750 SPI driver: %d\n", ret); 856 printk(KERN_ERR "Failed to register wm8750 SPI driver: %d\n",
857 ret);
858 }
960#endif 859#endif
961 return 0; 860 return ret;
962} 861}
963module_init(wm8750_modinit); 862module_init(wm8750_modinit);
964 863