diff options
author | Marek Vasut <marek.vasut@gmail.com> | 2010-04-08 14:48:51 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-09 07:17:42 -0400 |
commit | 6ca0c22ef8a4e988e2487d25964d55e6c37c5785 (patch) | |
tree | 81d76373c822209b0e69559a472cf5ca9f2c239d /sound/soc/codecs/wm8750.c | |
parent | 53a61d967a480307db4c8f7950ddb8bb1a0fda9b (diff) |
ASoC: WM8750: Convert to new API
Register the WM8750 as a SPI or I2C device. This patch mostly shuffles code
around. Hugely inspired by WM8753 which was already converted.
Also, this patch fixes the Jive and Spitz machine.
Signed-off-by: Marek Vasut <marek.vasut@gmail.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8750.c')
-rw-r--r-- | sound/soc/codecs/wm8750.c | 295 |
1 files changed, 139 insertions, 156 deletions
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index ee084083a49d..4bbc512c0836 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -29,11 +29,6 @@ | |||
29 | 29 | ||
30 | #include "wm8750.h" | 30 | #include "wm8750.h" |
31 | 31 | ||
32 | /* codec private data */ | ||
33 | struct wm8750_priv { | ||
34 | unsigned int sysclk; | ||
35 | }; | ||
36 | |||
37 | /* | 32 | /* |
38 | * wm8750 register cache | 33 | * wm8750 register cache |
39 | * We can't read the WM8750 register space when we | 34 | * We can't read the WM8750 register space when we |
@@ -53,6 +48,13 @@ static const u16 wm8750_reg[] = { | |||
53 | 0x0079, 0x0079, 0x0079, /* 40 */ | 48 | 0x0079, 0x0079, 0x0079, /* 40 */ |
54 | }; | 49 | }; |
55 | 50 | ||
51 | /* codec private data */ | ||
52 | struct wm8750_priv { | ||
53 | unsigned int sysclk; | ||
54 | struct snd_soc_codec codec; | ||
55 | u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; | ||
56 | }; | ||
57 | |||
56 | #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) | 58 | #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) |
57 | 59 | ||
58 | /* | 60 | /* |
@@ -695,25 +697,90 @@ static int wm8750_resume(struct platform_device *pdev) | |||
695 | return 0; | 697 | return 0; |
696 | } | 698 | } |
697 | 699 | ||
700 | static struct snd_soc_codec *wm8750_codec; | ||
701 | |||
702 | static int wm8750_probe(struct platform_device *pdev) | ||
703 | { | ||
704 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
705 | struct snd_soc_codec *codec; | ||
706 | int ret = 0; | ||
707 | |||
708 | if (!wm8750_codec) { | ||
709 | dev_err(&pdev->dev, "WM8750 codec not yet registered\n"); | ||
710 | return -EINVAL; | ||
711 | } | ||
712 | |||
713 | socdev->card->codec = wm8750_codec; | ||
714 | codec = wm8750_codec; | ||
715 | |||
716 | /* register pcms */ | ||
717 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
718 | if (ret < 0) { | ||
719 | printk(KERN_ERR "wm8750: failed to create pcms\n"); | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | snd_soc_add_controls(codec, wm8750_snd_controls, | ||
724 | ARRAY_SIZE(wm8750_snd_controls)); | ||
725 | wm8750_add_widgets(codec); | ||
726 | |||
727 | return 0; | ||
728 | |||
729 | err: | ||
730 | return ret; | ||
731 | } | ||
732 | |||
733 | /* power down chip */ | ||
734 | static int wm8750_remove(struct platform_device *pdev) | ||
735 | { | ||
736 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
737 | |||
738 | snd_soc_free_pcms(socdev); | ||
739 | snd_soc_dapm_free(socdev); | ||
740 | |||
741 | return 0; | ||
742 | } | ||
743 | |||
744 | struct snd_soc_codec_device soc_codec_dev_wm8750 = { | ||
745 | .probe = wm8750_probe, | ||
746 | .remove = wm8750_remove, | ||
747 | .suspend = wm8750_suspend, | ||
748 | .resume = wm8750_resume, | ||
749 | }; | ||
750 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); | ||
751 | |||
698 | /* | 752 | /* |
699 | * initialise the WM8750 driver | 753 | * initialise the WM8750 driver |
700 | * register the mixer and dsp interfaces with the kernel | 754 | * register the mixer and dsp interfaces with the kernel |
701 | */ | 755 | */ |
702 | static int wm8750_init(struct snd_soc_device *socdev, | 756 | static int wm8750_register(struct wm8750_priv *wm8750, |
703 | enum snd_soc_control_type control) | 757 | enum snd_soc_control_type control) |
704 | { | 758 | { |
705 | struct snd_soc_codec *codec = socdev->card->codec; | 759 | struct snd_soc_codec *codec = &wm8750->codec; |
706 | int reg, ret = 0; | 760 | int reg, ret = 0; |
707 | 761 | ||
762 | if (wm8750_codec) { | ||
763 | dev_err(codec->dev, "Multiple WM8750 devices not supported\n"); | ||
764 | ret = -EINVAL; | ||
765 | goto err; | ||
766 | } | ||
767 | |||
768 | mutex_init(&codec->mutex); | ||
769 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
770 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
771 | |||
708 | codec->name = "WM8750"; | 772 | codec->name = "WM8750"; |
709 | codec->owner = THIS_MODULE; | 773 | codec->owner = THIS_MODULE; |
774 | codec->bias_level = SND_SOC_BIAS_STANDBY; | ||
710 | codec->set_bias_level = wm8750_set_bias_level; | 775 | codec->set_bias_level = wm8750_set_bias_level; |
711 | codec->dai = &wm8750_dai; | 776 | codec->dai = &wm8750_dai; |
712 | codec->num_dai = 1; | 777 | codec->num_dai = 1; |
713 | codec->reg_cache_size = ARRAY_SIZE(wm8750_reg); | 778 | codec->private_data = wm8750; |
714 | codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KERNEL); | 779 | codec->reg_cache_size = ARRAY_SIZE(wm8750->reg_cache) + 1; |
715 | if (codec->reg_cache == NULL) | 780 | codec->reg_cache = &wm8750->reg_cache; |
716 | return -ENOMEM; | 781 | codec->private_data = wm8750; |
782 | |||
783 | memcpy(codec->reg_cache, wm8750_reg, sizeof(wm8750->reg_cache)); | ||
717 | 784 | ||
718 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); | 785 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); |
719 | if (ret < 0) { | 786 | if (ret < 0) { |
@@ -727,13 +794,6 @@ static int wm8750_init(struct snd_soc_device *socdev, | |||
727 | goto err; | 794 | goto err; |
728 | } | 795 | } |
729 | 796 | ||
730 | /* register pcms */ | ||
731 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
732 | if (ret < 0) { | ||
733 | printk(KERN_ERR "wm8750: failed to create pcms\n"); | ||
734 | goto err; | ||
735 | } | ||
736 | |||
737 | /* charge output caps */ | 797 | /* charge output caps */ |
738 | wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 798 | wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
739 | 799 | ||
@@ -755,19 +815,37 @@ static int wm8750_init(struct snd_soc_device *socdev, | |||
755 | reg = snd_soc_read(codec, WM8750_RINVOL); | 815 | reg = snd_soc_read(codec, WM8750_RINVOL); |
756 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); | 816 | snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100); |
757 | 817 | ||
758 | snd_soc_add_controls(codec, wm8750_snd_controls, | 818 | wm8750_codec = codec; |
759 | ARRAY_SIZE(wm8750_snd_controls)); | ||
760 | wm8750_add_widgets(codec); | ||
761 | return ret; | ||
762 | 819 | ||
820 | ret = snd_soc_register_codec(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 | |||
834 | err_codec: | ||
835 | snd_soc_unregister_codec(codec); | ||
763 | err: | 836 | err: |
764 | kfree(codec->reg_cache); | 837 | kfree(wm8750); |
765 | return ret; | 838 | return ret; |
766 | } | 839 | } |
767 | 840 | ||
768 | /* If the i2c layer weren't so broken, we could pass this kind of data | 841 | static void wm8750_unregister(struct wm8750_priv *wm8750) |
769 | around */ | 842 | { |
770 | static struct snd_soc_device *wm8750_socdev; | 843 | wm8750_set_bias_level(&wm8750->codec, SND_SOC_BIAS_OFF); |
844 | snd_soc_unregister_dais(&wm8750_dai, 1); | ||
845 | snd_soc_unregister_codec(&wm8750->codec); | ||
846 | kfree(wm8750); | ||
847 | wm8750_codec = NULL; | ||
848 | } | ||
771 | 849 | ||
772 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 850 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
773 | 851 | ||
@@ -781,24 +859,26 @@ static struct snd_soc_device *wm8750_socdev; | |||
781 | static int wm8750_i2c_probe(struct i2c_client *i2c, | 859 | static int wm8750_i2c_probe(struct i2c_client *i2c, |
782 | const struct i2c_device_id *id) | 860 | const struct i2c_device_id *id) |
783 | { | 861 | { |
784 | struct snd_soc_device *socdev = wm8750_socdev; | 862 | struct snd_soc_codec *codec; |
785 | struct snd_soc_codec *codec = socdev->card->codec; | 863 | struct wm8750_priv *wm8750; |
786 | int ret; | ||
787 | 864 | ||
788 | i2c_set_clientdata(i2c, codec); | 865 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); |
866 | if (wm8750 == NULL) | ||
867 | return -ENOMEM; | ||
868 | |||
869 | codec = &wm8750->codec; | ||
789 | codec->control_data = i2c; | 870 | codec->control_data = i2c; |
871 | i2c_set_clientdata(i2c, wm8750); | ||
790 | 872 | ||
791 | ret = wm8750_init(socdev, SND_SOC_I2C); | 873 | codec->dev = &i2c->dev; |
792 | if (ret < 0) | ||
793 | pr_err("failed to initialise WM8750\n"); | ||
794 | 874 | ||
795 | return ret; | 875 | return wm8750_register(wm8750, SND_SOC_I2C); |
796 | } | 876 | } |
797 | 877 | ||
798 | static int wm8750_i2c_remove(struct i2c_client *client) | 878 | static int wm8750_i2c_remove(struct i2c_client *client) |
799 | { | 879 | { |
800 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 880 | struct wm8750_priv *wm8750 = i2c_get_clientdata(client); |
801 | kfree(codec->reg_cache); | 881 | wm8750_unregister(wm8750); |
802 | return 0; | 882 | return 0; |
803 | } | 883 | } |
804 | 884 | ||
@@ -817,66 +897,31 @@ static struct i2c_driver wm8750_i2c_driver = { | |||
817 | .remove = wm8750_i2c_remove, | 897 | .remove = wm8750_i2c_remove, |
818 | .id_table = wm8750_i2c_id, | 898 | .id_table = wm8750_i2c_id, |
819 | }; | 899 | }; |
820 | |||
821 | static int wm8750_add_i2c_device(struct platform_device *pdev, | ||
822 | const struct wm8750_setup_data *setup) | ||
823 | { | ||
824 | struct i2c_board_info info; | ||
825 | struct i2c_adapter *adapter; | ||
826 | struct i2c_client *client; | ||
827 | int ret; | ||
828 | |||
829 | ret = i2c_add_driver(&wm8750_i2c_driver); | ||
830 | if (ret != 0) { | ||
831 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
832 | return ret; | ||
833 | } | ||
834 | |||
835 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
836 | info.addr = setup->i2c_address; | ||
837 | strlcpy(info.type, "wm8750", I2C_NAME_SIZE); | ||
838 | |||
839 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
840 | if (!adapter) { | ||
841 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
842 | setup->i2c_bus); | ||
843 | goto err_driver; | ||
844 | } | ||
845 | |||
846 | client = i2c_new_device(adapter, &info); | ||
847 | i2c_put_adapter(adapter); | ||
848 | if (!client) { | ||
849 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
850 | (unsigned int)info.addr); | ||
851 | goto err_driver; | ||
852 | } | ||
853 | |||
854 | return 0; | ||
855 | |||
856 | err_driver: | ||
857 | i2c_del_driver(&wm8750_i2c_driver); | ||
858 | return -ENODEV; | ||
859 | } | ||
860 | #endif | 900 | #endif |
861 | 901 | ||
862 | #if defined(CONFIG_SPI_MASTER) | 902 | #if defined(CONFIG_SPI_MASTER) |
863 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 903 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
864 | { | 904 | { |
865 | struct snd_soc_device *socdev = wm8750_socdev; | 905 | struct snd_soc_codec *codec; |
866 | struct snd_soc_codec *codec = socdev->card->codec; | 906 | struct wm8750_priv *wm8750; |
867 | int ret; | ||
868 | 907 | ||
908 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | ||
909 | if (wm8750 == NULL) | ||
910 | return -ENOMEM; | ||
911 | |||
912 | codec = &wm8750->codec; | ||
869 | codec->control_data = spi; | 913 | codec->control_data = spi; |
914 | codec->dev = &spi->dev; | ||
870 | 915 | ||
871 | ret = wm8750_init(socdev, SND_SOC_SPI); | 916 | dev_set_drvdata(&spi->dev, wm8750); |
872 | if (ret < 0) | ||
873 | dev_err(&spi->dev, "failed to initialise WM8750\n"); | ||
874 | 917 | ||
875 | return ret; | 918 | return wm8750_register(wm8750, SND_SOC_SPI); |
876 | } | 919 | } |
877 | 920 | ||
878 | static int __devexit wm8750_spi_remove(struct spi_device *spi) | 921 | static int __devexit wm8750_spi_remove(struct spi_device *spi) |
879 | { | 922 | { |
923 | struct wm8750_priv *wm8750 = dev_get_drvdata(&spi->dev); | ||
924 | wm8750_unregister(wm8750); | ||
880 | return 0; | 925 | return 0; |
881 | } | 926 | } |
882 | 927 | ||
@@ -891,93 +936,31 @@ static struct spi_driver wm8750_spi_driver = { | |||
891 | }; | 936 | }; |
892 | #endif | 937 | #endif |
893 | 938 | ||
894 | static int wm8750_probe(struct platform_device *pdev) | 939 | static int __init wm8750_modinit(void) |
895 | { | 940 | { |
896 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
897 | struct wm8750_setup_data *setup = socdev->codec_data; | ||
898 | struct snd_soc_codec *codec; | ||
899 | struct wm8750_priv *wm8750; | ||
900 | int ret; | 941 | int ret; |
901 | |||
902 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | ||
903 | if (codec == NULL) | ||
904 | return -ENOMEM; | ||
905 | |||
906 | wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL); | ||
907 | if (wm8750 == NULL) { | ||
908 | kfree(codec); | ||
909 | return -ENOMEM; | ||
910 | } | ||
911 | |||
912 | codec->private_data = wm8750; | ||
913 | socdev->card->codec = codec; | ||
914 | mutex_init(&codec->mutex); | ||
915 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
916 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
917 | wm8750_socdev = socdev; | ||
918 | |||
919 | ret = -ENODEV; | ||
920 | |||
921 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 942 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
922 | if (setup->i2c_address) { | 943 | ret = i2c_add_driver(&wm8750_i2c_driver); |
923 | ret = wm8750_add_i2c_device(pdev, setup); | 944 | if (ret != 0) |
924 | } | 945 | pr_err("Failed to register WM8750 I2C driver: %d\n", ret); |
925 | #endif | 946 | #endif |
926 | #if defined(CONFIG_SPI_MASTER) | 947 | #if defined(CONFIG_SPI_MASTER) |
927 | if (setup->spi) { | 948 | ret = spi_register_driver(&wm8750_spi_driver); |
928 | ret = spi_register_driver(&wm8750_spi_driver); | 949 | if (ret != 0) |
929 | if (ret != 0) | 950 | pr_err("Failed to register WM8750 SPI driver: %d\n", ret); |
930 | printk(KERN_ERR "can't add spi driver"); | ||
931 | } | ||
932 | #endif | 951 | #endif |
933 | 952 | return 0; | |
934 | if (ret != 0) { | ||
935 | kfree(codec->private_data); | ||
936 | kfree(codec); | ||
937 | } | ||
938 | return ret; | ||
939 | } | 953 | } |
954 | module_init(wm8750_modinit); | ||
940 | 955 | ||
941 | /* power down chip */ | 956 | static void __exit wm8750_exit(void) |
942 | static int wm8750_remove(struct platform_device *pdev) | ||
943 | { | 957 | { |
944 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
945 | struct snd_soc_codec *codec = socdev->card->codec; | ||
946 | |||
947 | if (codec->control_data) | ||
948 | wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
949 | snd_soc_free_pcms(socdev); | ||
950 | snd_soc_dapm_free(socdev); | ||
951 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 958 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
952 | i2c_unregister_device(codec->control_data); | ||
953 | i2c_del_driver(&wm8750_i2c_driver); | 959 | i2c_del_driver(&wm8750_i2c_driver); |
954 | #endif | 960 | #endif |
955 | #if defined(CONFIG_SPI_MASTER) | 961 | #if defined(CONFIG_SPI_MASTER) |
956 | spi_unregister_driver(&wm8750_spi_driver); | 962 | spi_unregister_driver(&wm8750_spi_driver); |
957 | #endif | 963 | #endif |
958 | kfree(codec->private_data); | ||
959 | kfree(codec); | ||
960 | |||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | struct snd_soc_codec_device soc_codec_dev_wm8750 = { | ||
965 | .probe = wm8750_probe, | ||
966 | .remove = wm8750_remove, | ||
967 | .suspend = wm8750_suspend, | ||
968 | .resume = wm8750_resume, | ||
969 | }; | ||
970 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750); | ||
971 | |||
972 | static int __init wm8750_modinit(void) | ||
973 | { | ||
974 | return snd_soc_register_dai(&wm8750_dai); | ||
975 | } | ||
976 | module_init(wm8750_modinit); | ||
977 | |||
978 | static void __exit wm8750_exit(void) | ||
979 | { | ||
980 | snd_soc_unregister_dai(&wm8750_dai); | ||
981 | } | 964 | } |
982 | module_exit(wm8750_exit); | 965 | module_exit(wm8750_exit); |
983 | 966 | ||