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