diff options
Diffstat (limited to 'sound/soc/codecs/wm8750.c')
-rw-r--r-- | sound/soc/codecs/wm8750.c | 178 |
1 files changed, 123 insertions, 55 deletions
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index dd1f55404b29..9b7296ee5b08 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/pm.h> | 19 | #include <linux/pm.h> |
20 | #include <linux/i2c.h> | 20 | #include <linux/i2c.h> |
21 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -28,7 +29,6 @@ | |||
28 | 29 | ||
29 | #include "wm8750.h" | 30 | #include "wm8750.h" |
30 | 31 | ||
31 | #define AUDIO_NAME "WM8750" | ||
32 | #define WM8750_VERSION "0.12" | 32 | #define WM8750_VERSION "0.12" |
33 | 33 | ||
34 | /* codec private data */ | 34 | /* codec private data */ |
@@ -841,88 +841,147 @@ static struct snd_soc_device *wm8750_socdev; | |||
841 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 841 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
842 | 842 | ||
843 | /* | 843 | /* |
844 | * WM8731 2 wire address is determined by GPIO5 | 844 | * WM8750 2 wire address is determined by GPIO5 |
845 | * state during powerup. | 845 | * state during powerup. |
846 | * low = 0x1a | 846 | * low = 0x1a |
847 | * high = 0x1b | 847 | * high = 0x1b |
848 | */ | 848 | */ |
849 | static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END }; | ||
850 | 849 | ||
851 | /* Magic definition of all other variables and things */ | 850 | static int wm8750_i2c_probe(struct i2c_client *i2c, |
852 | I2C_CLIENT_INSMOD; | 851 | const struct i2c_device_id *id) |
853 | |||
854 | static struct i2c_driver wm8750_i2c_driver; | ||
855 | static struct i2c_client client_template; | ||
856 | |||
857 | static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind) | ||
858 | { | 852 | { |
859 | struct snd_soc_device *socdev = wm8750_socdev; | 853 | struct snd_soc_device *socdev = wm8750_socdev; |
860 | struct wm8750_setup_data *setup = socdev->codec_data; | ||
861 | struct snd_soc_codec *codec = socdev->codec; | 854 | struct snd_soc_codec *codec = socdev->codec; |
862 | struct i2c_client *i2c; | ||
863 | int ret; | 855 | int ret; |
864 | 856 | ||
865 | if (addr != setup->i2c_address) | ||
866 | return -ENODEV; | ||
867 | |||
868 | client_template.adapter = adap; | ||
869 | client_template.addr = addr; | ||
870 | |||
871 | i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL); | ||
872 | if (i2c == NULL) | ||
873 | return -ENOMEM; | ||
874 | |||
875 | i2c_set_clientdata(i2c, codec); | 857 | i2c_set_clientdata(i2c, codec); |
876 | codec->control_data = i2c; | 858 | codec->control_data = i2c; |
877 | 859 | ||
878 | ret = i2c_attach_client(i2c); | ||
879 | if (ret < 0) { | ||
880 | pr_err("failed to attach codec at addr %x\n", addr); | ||
881 | goto err; | ||
882 | } | ||
883 | |||
884 | ret = wm8750_init(socdev); | 860 | ret = wm8750_init(socdev); |
885 | if (ret < 0) { | 861 | if (ret < 0) |
886 | pr_err("failed to initialise WM8750\n"); | 862 | pr_err("failed to initialise WM8750\n"); |
887 | goto err; | ||
888 | } | ||
889 | return ret; | ||
890 | 863 | ||
891 | err: | ||
892 | kfree(i2c); | ||
893 | return ret; | 864 | return ret; |
894 | } | 865 | } |
895 | 866 | ||
896 | static int wm8750_i2c_detach(struct i2c_client *client) | 867 | static int wm8750_i2c_remove(struct i2c_client *client) |
897 | { | 868 | { |
898 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | 869 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
899 | i2c_detach_client(client); | ||
900 | kfree(codec->reg_cache); | 870 | kfree(codec->reg_cache); |
901 | kfree(client); | ||
902 | return 0; | 871 | return 0; |
903 | } | 872 | } |
904 | 873 | ||
905 | static int wm8750_i2c_attach(struct i2c_adapter *adap) | 874 | static const struct i2c_device_id wm8750_i2c_id[] = { |
906 | { | 875 | { "wm8750", 0 }, |
907 | return i2c_probe(adap, &addr_data, wm8750_codec_probe); | 876 | { } |
908 | } | 877 | }; |
878 | MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | ||
909 | 879 | ||
910 | /* corgi i2c codec control layer */ | ||
911 | static struct i2c_driver wm8750_i2c_driver = { | 880 | static struct i2c_driver wm8750_i2c_driver = { |
912 | .driver = { | 881 | .driver = { |
913 | .name = "WM8750 I2C Codec", | 882 | .name = "WM8750 I2C Codec", |
914 | .owner = THIS_MODULE, | 883 | .owner = THIS_MODULE, |
915 | }, | 884 | }, |
916 | .id = I2C_DRIVERID_WM8750, | 885 | .probe = wm8750_i2c_probe, |
917 | .attach_adapter = wm8750_i2c_attach, | 886 | .remove = wm8750_i2c_remove, |
918 | .detach_client = wm8750_i2c_detach, | 887 | .id_table = wm8750_i2c_id, |
919 | .command = NULL, | ||
920 | }; | 888 | }; |
921 | 889 | ||
922 | static struct i2c_client client_template = { | 890 | static int wm8750_add_i2c_device(struct platform_device *pdev, |
923 | .name = "WM8750", | 891 | const struct wm8750_setup_data *setup) |
924 | .driver = &wm8750_i2c_driver, | 892 | { |
893 | struct i2c_board_info info; | ||
894 | struct i2c_adapter *adapter; | ||
895 | struct i2c_client *client; | ||
896 | int ret; | ||
897 | |||
898 | ret = i2c_add_driver(&wm8750_i2c_driver); | ||
899 | if (ret != 0) { | ||
900 | dev_err(&pdev->dev, "can't add i2c driver\n"); | ||
901 | return ret; | ||
902 | } | ||
903 | |||
904 | memset(&info, 0, sizeof(struct i2c_board_info)); | ||
905 | info.addr = setup->i2c_address; | ||
906 | strlcpy(info.type, "wm8750", I2C_NAME_SIZE); | ||
907 | |||
908 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
909 | if (!adapter) { | ||
910 | dev_err(&pdev->dev, "can't get i2c adapter %d\n", | ||
911 | setup->i2c_bus); | ||
912 | goto err_driver; | ||
913 | } | ||
914 | |||
915 | client = i2c_new_device(adapter, &info); | ||
916 | i2c_put_adapter(adapter); | ||
917 | if (!client) { | ||
918 | dev_err(&pdev->dev, "can't add i2c device at 0x%x\n", | ||
919 | (unsigned int)info.addr); | ||
920 | goto err_driver; | ||
921 | } | ||
922 | |||
923 | return 0; | ||
924 | |||
925 | err_driver: | ||
926 | i2c_del_driver(&wm8750_i2c_driver); | ||
927 | return -ENODEV; | ||
928 | } | ||
929 | #endif | ||
930 | |||
931 | #if defined(CONFIG_SPI_MASTER) | ||
932 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | ||
933 | { | ||
934 | struct snd_soc_device *socdev = wm8750_socdev; | ||
935 | struct snd_soc_codec *codec = socdev->codec; | ||
936 | int ret; | ||
937 | |||
938 | codec->control_data = spi; | ||
939 | |||
940 | ret = wm8750_init(socdev); | ||
941 | if (ret < 0) | ||
942 | dev_err(&spi->dev, "failed to initialise WM8750\n"); | ||
943 | |||
944 | return ret; | ||
945 | } | ||
946 | |||
947 | static int __devexit wm8750_spi_remove(struct spi_device *spi) | ||
948 | { | ||
949 | return 0; | ||
950 | } | ||
951 | |||
952 | static struct spi_driver wm8750_spi_driver = { | ||
953 | .driver = { | ||
954 | .name = "wm8750", | ||
955 | .bus = &spi_bus_type, | ||
956 | .owner = THIS_MODULE, | ||
957 | }, | ||
958 | .probe = wm8750_spi_probe, | ||
959 | .remove = __devexit_p(wm8750_spi_remove), | ||
925 | }; | 960 | }; |
961 | |||
962 | static int wm8750_spi_write(struct spi_device *spi, const char *data, int len) | ||
963 | { | ||
964 | struct spi_transfer t; | ||
965 | struct spi_message m; | ||
966 | u8 msg[2]; | ||
967 | |||
968 | if (len <= 0) | ||
969 | return 0; | ||
970 | |||
971 | msg[0] = data[0]; | ||
972 | msg[1] = data[1]; | ||
973 | |||
974 | spi_message_init(&m); | ||
975 | memset(&t, 0, (sizeof t)); | ||
976 | |||
977 | t.tx_buf = &msg[0]; | ||
978 | t.len = len; | ||
979 | |||
980 | spi_message_add_tail(&t, &m); | ||
981 | spi_sync(spi, &m); | ||
982 | |||
983 | return len; | ||
984 | } | ||
926 | #endif | 985 | #endif |
927 | 986 | ||
928 | static int wm8750_probe(struct platform_device *pdev) | 987 | static int wm8750_probe(struct platform_device *pdev) |
@@ -931,7 +990,7 @@ static int wm8750_probe(struct platform_device *pdev) | |||
931 | struct wm8750_setup_data *setup = socdev->codec_data; | 990 | struct wm8750_setup_data *setup = socdev->codec_data; |
932 | struct snd_soc_codec *codec; | 991 | struct snd_soc_codec *codec; |
933 | struct wm8750_priv *wm8750; | 992 | struct wm8750_priv *wm8750; |
934 | int ret = 0; | 993 | int ret; |
935 | 994 | ||
936 | pr_info("WM8750 Audio Codec %s", WM8750_VERSION); | 995 | pr_info("WM8750 Audio Codec %s", WM8750_VERSION); |
937 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 996 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); |
@@ -952,16 +1011,21 @@ static int wm8750_probe(struct platform_device *pdev) | |||
952 | wm8750_socdev = socdev; | 1011 | wm8750_socdev = socdev; |
953 | INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work); | 1012 | INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work); |
954 | 1013 | ||
1014 | ret = -ENODEV; | ||
1015 | |||
955 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1016 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
956 | if (setup->i2c_address) { | 1017 | if (setup->i2c_address) { |
957 | normal_i2c[0] = setup->i2c_address; | ||
958 | codec->hw_write = (hw_write_t)i2c_master_send; | 1018 | codec->hw_write = (hw_write_t)i2c_master_send; |
959 | ret = i2c_add_driver(&wm8750_i2c_driver); | 1019 | ret = wm8750_add_i2c_device(pdev, setup); |
1020 | } | ||
1021 | #endif | ||
1022 | #if defined(CONFIG_SPI_MASTER) | ||
1023 | if (setup->spi) { | ||
1024 | codec->hw_write = (hw_write_t)wm8750_spi_write; | ||
1025 | ret = spi_register_driver(&wm8750_spi_driver); | ||
960 | if (ret != 0) | 1026 | if (ret != 0) |
961 | printk(KERN_ERR "can't add i2c driver"); | 1027 | printk(KERN_ERR "can't add spi driver"); |
962 | } | 1028 | } |
963 | #else | ||
964 | /* Add other interfaces here */ | ||
965 | #endif | 1029 | #endif |
966 | 1030 | ||
967 | if (ret != 0) { | 1031 | if (ret != 0) { |
@@ -1002,8 +1066,12 @@ static int wm8750_remove(struct platform_device *pdev) | |||
1002 | snd_soc_free_pcms(socdev); | 1066 | snd_soc_free_pcms(socdev); |
1003 | snd_soc_dapm_free(socdev); | 1067 | snd_soc_dapm_free(socdev); |
1004 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 1068 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
1069 | i2c_unregister_device(codec->control_data); | ||
1005 | i2c_del_driver(&wm8750_i2c_driver); | 1070 | i2c_del_driver(&wm8750_i2c_driver); |
1006 | #endif | 1071 | #endif |
1072 | #if defined(CONFIG_SPI_MASTER) | ||
1073 | spi_unregister_driver(&wm8750_spi_driver); | ||
1074 | #endif | ||
1007 | kfree(codec->private_data); | 1075 | kfree(codec->private_data); |
1008 | kfree(codec); | 1076 | kfree(codec); |
1009 | 1077 | ||