aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8955.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm8955.c')
-rw-r--r--sound/soc/codecs/wm8955.c181
1 files changed, 44 insertions, 137 deletions
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 5f025593d84d..f89ad6c9a80b 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -30,9 +30,6 @@
30 30
31#include "wm8955.h" 31#include "wm8955.h"
32 32
33static struct snd_soc_codec *wm8955_codec;
34struct snd_soc_codec_device soc_codec_dev_wm8955;
35
36#define WM8955_NUM_SUPPLIES 4 33#define WM8955_NUM_SUPPLIES 4
37static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = { 34static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
38 "DCVDD", 35 "DCVDD",
@@ -43,7 +40,8 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
43 40
44/* codec private data */ 41/* codec private data */
45struct wm8955_priv { 42struct wm8955_priv {
46 struct snd_soc_codec codec; 43 enum snd_soc_control_type control_type;
44
47 u16 reg_cache[WM8955_MAX_REGISTER + 1]; 45 u16 reg_cache[WM8955_MAX_REGISTER + 1];
48 46
49 unsigned int mclk_rate; 47 unsigned int mclk_rate;
@@ -52,8 +50,6 @@ struct wm8955_priv {
52 int fs; 50 int fs;
53 51
54 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; 52 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
55
56 struct wm8955_pdata *pdata;
57}; 53};
58 54
59static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { 55static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
@@ -870,8 +866,8 @@ static struct snd_soc_dai_ops wm8955_dai_ops = {
870 .digital_mute = wm8955_digital_mute, 866 .digital_mute = wm8955_digital_mute,
871}; 867};
872 868
873struct snd_soc_dai wm8955_dai = { 869static struct snd_soc_dai_driver wm8955_dai = {
874 .name = "WM8955", 870 .name = "wm8955-hifi",
875 .playback = { 871 .playback = {
876 .stream_name = "Playback", 872 .stream_name = "Playback",
877 .channels_min = 2, 873 .channels_min = 2,
@@ -881,24 +877,17 @@ struct snd_soc_dai wm8955_dai = {
881 }, 877 },
882 .ops = &wm8955_dai_ops, 878 .ops = &wm8955_dai_ops,
883}; 879};
884EXPORT_SYMBOL_GPL(wm8955_dai);
885 880
886#ifdef CONFIG_PM 881#ifdef CONFIG_PM
887static int wm8955_suspend(struct platform_device *pdev, pm_message_t state) 882static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
888{ 883{
889 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
890 struct snd_soc_codec *codec = socdev->card->codec;
891
892 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); 884 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
893 885
894 return 0; 886 return 0;
895} 887}
896 888
897static int wm8955_resume(struct platform_device *pdev) 889static int wm8955_resume(struct snd_soc_codec *codec)
898{ 890{
899 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
900 struct snd_soc_codec *codec = socdev->card->codec;
901
902 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 891 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
903 892
904 return 0; 893 return 0;
@@ -908,86 +897,16 @@ static int wm8955_resume(struct platform_device *pdev)
908#define wm8955_resume NULL 897#define wm8955_resume NULL
909#endif 898#endif
910 899
911static int wm8955_probe(struct platform_device *pdev) 900static int wm8955_probe(struct snd_soc_codec *codec)
912{
913 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
914 struct snd_soc_codec *codec;
915 int ret = 0;
916
917 if (wm8955_codec == NULL) {
918 dev_err(&pdev->dev, "Codec device not registered\n");
919 return -ENODEV;
920 }
921
922 socdev->card->codec = wm8955_codec;
923 codec = wm8955_codec;
924
925 /* register pcms */
926 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
927 if (ret < 0) {
928 dev_err(codec->dev, "failed to create pcms: %d\n", ret);
929 goto pcm_err;
930 }
931
932 wm8955_add_widgets(codec);
933
934 return ret;
935
936pcm_err:
937 return ret;
938}
939
940static int wm8955_remove(struct platform_device *pdev)
941{ 901{
942 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 902 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
943 903 struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
944 snd_soc_free_pcms(socdev); 904 int ret, i;
945 snd_soc_dapm_free(socdev);
946
947 return 0;
948}
949
950struct snd_soc_codec_device soc_codec_dev_wm8955 = {
951 .probe = wm8955_probe,
952 .remove = wm8955_remove,
953 .suspend = wm8955_suspend,
954 .resume = wm8955_resume,
955};
956EXPORT_SYMBOL_GPL(soc_codec_dev_wm8955);
957
958static int wm8955_register(struct wm8955_priv *wm8955,
959 enum snd_soc_control_type control)
960{
961 int ret;
962 struct snd_soc_codec *codec = &wm8955->codec;
963 int i;
964
965 if (wm8955_codec) {
966 dev_err(codec->dev, "Another WM8955 is registered\n");
967 ret = -EINVAL;
968 goto err;
969 }
970
971 mutex_init(&codec->mutex);
972 INIT_LIST_HEAD(&codec->dapm_widgets);
973 INIT_LIST_HEAD(&codec->dapm_paths);
974
975 snd_soc_codec_set_drvdata(codec, wm8955);
976 codec->name = "WM8955";
977 codec->owner = THIS_MODULE;
978 codec->bias_level = SND_SOC_BIAS_OFF;
979 codec->set_bias_level = wm8955_set_bias_level;
980 codec->dai = &wm8955_dai;
981 codec->num_dai = 1;
982 codec->reg_cache_size = WM8955_MAX_REGISTER;
983 codec->reg_cache = &wm8955->reg_cache;
984
985 memcpy(codec->reg_cache, wm8955_reg, sizeof(wm8955_reg));
986 905
987 ret = snd_soc_codec_set_cache_io(codec, 7, 9, control); 906 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
988 if (ret != 0) { 907 if (ret != 0) {
989 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 908 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
990 goto err; 909 return ret;
991 } 910 }
992 911
993 for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++) 912 for (i = 0; i < ARRAY_SIZE(wm8955->supplies); i++)
@@ -997,7 +916,7 @@ static int wm8955_register(struct wm8955_priv *wm8955,
997 wm8955->supplies); 916 wm8955->supplies);
998 if (ret != 0) { 917 if (ret != 0) {
999 dev_err(codec->dev, "Failed to request supplies: %d\n", ret); 918 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1000 goto err; 919 return ret;
1001 } 920 }
1002 921
1003 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies), 922 ret = regulator_bulk_enable(ARRAY_SIZE(wm8955->supplies),
@@ -1013,8 +932,6 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1013 goto err_enable; 932 goto err_enable;
1014 } 933 }
1015 934
1016 wm8955_dai.dev = codec->dev;
1017
1018 /* Change some default settings - latch VU and enable ZC */ 935 /* Change some default settings - latch VU and enable ZC */
1019 wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU; 936 wm8955->reg_cache[WM8955_LEFT_DAC_VOLUME] |= WM8955_LDVU;
1020 wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU; 937 wm8955->reg_cache[WM8955_RIGHT_DAC_VOLUME] |= WM8955_RDVU;
@@ -1028,12 +945,12 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1028 wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB; 945 wm8955->reg_cache[WM8955_BASS_CONTROL] |= WM8955_BB;
1029 946
1030 /* Set platform data values */ 947 /* Set platform data values */
1031 if (wm8955->pdata) { 948 if (pdata) {
1032 if (wm8955->pdata->out2_speaker) 949 if (pdata->out2_speaker)
1033 wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2] 950 wm8955->reg_cache[WM8955_ADDITIONAL_CONTROL_2]
1034 |= WM8955_ROUT2INV; 951 |= WM8955_ROUT2INV;
1035 952
1036 if (wm8955->pdata->monoin_diff) 953 if (pdata->monoin_diff)
1037 wm8955->reg_cache[WM8955_MONO_OUT_MIX_1] 954 wm8955->reg_cache[WM8955_MONO_OUT_MIX_1]
1038 |= WM8955_DMEN; 955 |= WM8955_DMEN;
1039 } 956 }
@@ -1043,70 +960,60 @@ static int wm8955_register(struct wm8955_priv *wm8955,
1043 /* Bias level configuration will have done an extra enable */ 960 /* Bias level configuration will have done an extra enable */
1044 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 961 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1045 962
1046 wm8955_codec = codec; 963 wm8955_add_widgets(codec);
1047
1048 ret = snd_soc_register_codec(codec);
1049 if (ret != 0) {
1050 dev_err(codec->dev, "Failed to register codec: %d\n", ret);
1051 goto err_enable;
1052 }
1053
1054 ret = snd_soc_register_dai(&wm8955_dai);
1055 if (ret != 0) {
1056 dev_err(codec->dev, "Failed to register DAI: %d\n", ret);
1057 goto err_codec;
1058 }
1059
1060 return 0; 964 return 0;
1061 965
1062err_codec:
1063 snd_soc_unregister_codec(codec);
1064err_enable: 966err_enable:
1065 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 967 regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1066err_get: 968err_get:
1067 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 969 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1068err:
1069 kfree(wm8955);
1070 return ret; 970 return ret;
1071} 971}
1072 972
1073static void wm8955_unregister(struct wm8955_priv *wm8955) 973static int wm8955_remove(struct snd_soc_codec *codec)
1074{ 974{
1075 wm8955_set_bias_level(&wm8955->codec, SND_SOC_BIAS_OFF); 975 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
976
977 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
1076 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies); 978 regulator_bulk_free(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
1077 snd_soc_unregister_dai(&wm8955_dai); 979 return 0;
1078 snd_soc_unregister_codec(&wm8955->codec);
1079 kfree(wm8955);
1080 wm8955_codec = NULL;
1081} 980}
1082 981
982static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
983 .probe = wm8955_probe,
984 .remove = wm8955_remove,
985 .suspend = wm8955_suspend,
986 .resume = wm8955_resume,
987 .set_bias_level = wm8955_set_bias_level,
988 .reg_cache_size = ARRAY_SIZE(wm8955_reg),
989 .reg_word_size = sizeof(u16),
990 .reg_cache_default = wm8955_reg,
991};
992
1083#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 993#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1084static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, 994static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
1085 const struct i2c_device_id *id) 995 const struct i2c_device_id *id)
1086{ 996{
1087 struct wm8955_priv *wm8955; 997 struct wm8955_priv *wm8955;
1088 struct snd_soc_codec *codec; 998 int ret;
1089 999
1090 wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL); 1000 wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
1091 if (wm8955 == NULL) 1001 if (wm8955 == NULL)
1092 return -ENOMEM; 1002 return -ENOMEM;
1093 1003
1094 codec = &wm8955->codec;
1095 codec->hw_write = (hw_write_t)i2c_master_send;
1096
1097 i2c_set_clientdata(i2c, wm8955); 1004 i2c_set_clientdata(i2c, wm8955);
1098 codec->control_data = i2c;
1099 wm8955->pdata = i2c->dev.platform_data;
1100
1101 codec->dev = &i2c->dev;
1102 1005
1103 return wm8955_register(wm8955, SND_SOC_I2C); 1006 ret = snd_soc_register_codec(&i2c->dev,
1007 &soc_codec_dev_wm8955, &wm8955_dai, 1);
1008 if (ret < 0)
1009 kfree(wm8955);
1010 return ret;
1104} 1011}
1105 1012
1106static __devexit int wm8955_i2c_remove(struct i2c_client *client) 1013static __devexit int wm8955_i2c_remove(struct i2c_client *client)
1107{ 1014{
1108 struct wm8955_priv *wm8955 = i2c_get_clientdata(client); 1015 snd_soc_unregister_codec(&client->dev);
1109 wm8955_unregister(wm8955); 1016 kfree(i2c_get_clientdata(client));
1110 return 0; 1017 return 0;
1111} 1018}
1112 1019
@@ -1118,7 +1025,7 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
1118 1025
1119static struct i2c_driver wm8955_i2c_driver = { 1026static struct i2c_driver wm8955_i2c_driver = {
1120 .driver = { 1027 .driver = {
1121 .name = "wm8955", 1028 .name = "wm8955-codec",
1122 .owner = THIS_MODULE, 1029 .owner = THIS_MODULE,
1123 }, 1030 },
1124 .probe = wm8955_i2c_probe, 1031 .probe = wm8955_i2c_probe,
@@ -1129,7 +1036,7 @@ static struct i2c_driver wm8955_i2c_driver = {
1129 1036
1130static int __init wm8955_modinit(void) 1037static int __init wm8955_modinit(void)
1131{ 1038{
1132 int ret; 1039 int ret = 0;
1133#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) 1040#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
1134 ret = i2c_add_driver(&wm8955_i2c_driver); 1041 ret = i2c_add_driver(&wm8955_i2c_driver);
1135 if (ret != 0) { 1042 if (ret != 0) {
@@ -1137,7 +1044,7 @@ static int __init wm8955_modinit(void)
1137 ret); 1044 ret);
1138 } 1045 }
1139#endif 1046#endif
1140 return 0; 1047 return ret;
1141} 1048}
1142module_init(wm8955_modinit); 1049module_init(wm8955_modinit);
1143 1050