aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8955.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-12-29 16:42:36 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-01-20 08:58:25 -0500
commit95860fdf0f565f96fc37561b6794177604f89097 (patch)
tree94c4c877fd2a7c1a6a467f0150f5cf5a4f325cd4 /sound/soc/codecs/wm8955.c
parent9887cb9e651da91c5bad2578d71e7ff8410e14b7 (diff)
ASoC: Convert WM8955 to direct regmap API usage
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8955.c')
-rw-r--r--sound/soc/codecs/wm8955.c198
1 files changed, 123 insertions, 75 deletions
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 559c96b656a4..11fb2dd40c5c 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -16,6 +16,7 @@
16#include <linux/delay.h> 16#include <linux/delay.h>
17#include <linux/pm.h> 17#include <linux/pm.h>
18#include <linux/i2c.h> 18#include <linux/i2c.h>
19#include <linux/regmap.h>
19#include <linux/regulator/consumer.h> 20#include <linux/regulator/consumer.h>
20#include <linux/slab.h> 21#include <linux/slab.h>
21#include <sound/core.h> 22#include <sound/core.h>
@@ -38,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
38 39
39/* codec private data */ 40/* codec private data */
40struct wm8955_priv { 41struct wm8955_priv {
41 enum snd_soc_control_type control_type; 42 struct regmap *regmap;
42 43
43 unsigned int mclk_rate; 44 unsigned int mclk_rate;
44 45
@@ -48,69 +49,85 @@ struct wm8955_priv {
48 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES]; 49 struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
49}; 50};
50 51
51static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = { 52static const struct reg_default wm8955_reg_defaults[] = {
52 0x0000, /* R0 */ 53 { 2, 0x0079 }, /* R2 - LOUT1 volume */
53 0x0000, /* R1 */ 54 { 3, 0x0079 }, /* R3 - ROUT1 volume */
54 0x0079, /* R2 - LOUT1 volume */ 55 { 5, 0x0008 }, /* R5 - DAC Control */
55 0x0079, /* R3 - ROUT1 volume */ 56 { 7, 0x000A }, /* R7 - Audio Interface */
56 0x0000, /* R4 */ 57 { 8, 0x0000 }, /* R8 - Sample Rate */
57 0x0008, /* R5 - DAC Control */ 58 { 10, 0x00FF }, /* R10 - Left DAC volume */
58 0x0000, /* R6 */ 59 { 11, 0x00FF }, /* R11 - Right DAC volume */
59 0x000A, /* R7 - Audio Interface */ 60 { 12, 0x000F }, /* R12 - Bass control */
60 0x0000, /* R8 - Sample Rate */ 61 { 13, 0x000F }, /* R13 - Treble control */
61 0x0000, /* R9 */ 62 { 23, 0x00C1 }, /* R23 - Additional control (1) */
62 0x00FF, /* R10 - Left DAC volume */ 63 { 24, 0x0000 }, /* R24 - Additional control (2) */
63 0x00FF, /* R11 - Right DAC volume */ 64 { 25, 0x0000 }, /* R25 - Power Management (1) */
64 0x000F, /* R12 - Bass control */ 65 { 26, 0x0000 }, /* R26 - Power Management (2) */
65 0x000F, /* R13 - Treble control */ 66 { 27, 0x0000 }, /* R27 - Additional Control (3) */
66 0x0000, /* R14 */ 67 { 34, 0x0050 }, /* R34 - Left out Mix (1) */
67 0x0000, /* R15 - Reset */ 68 { 35, 0x0050 }, /* R35 - Left out Mix (2) */
68 0x0000, /* R16 */ 69 { 36, 0x0050 }, /* R36 - Right out Mix (1) */
69 0x0000, /* R17 */ 70 { 37, 0x0050 }, /* R37 - Right Out Mix (2) */
70 0x0000, /* R18 */ 71 { 38, 0x0050 }, /* R38 - Mono out Mix (1) */
71 0x0000, /* R19 */ 72 { 39, 0x0050 }, /* R39 - Mono out Mix (2) */
72 0x0000, /* R20 */ 73 { 40, 0x0079 }, /* R40 - LOUT2 volume */
73 0x0000, /* R21 */ 74 { 41, 0x0079 }, /* R41 - ROUT2 volume */
74 0x0000, /* R22 */ 75 { 42, 0x0079 }, /* R42 - MONOOUT volume */
75 0x00C1, /* R23 - Additional control (1) */ 76 { 43, 0x0000 }, /* R43 - Clocking / PLL */
76 0x0000, /* R24 - Additional control (2) */ 77 { 44, 0x0103 }, /* R44 - PLL Control 1 */
77 0x0000, /* R25 - Power Management (1) */ 78 { 45, 0x0024 }, /* R45 - PLL Control 2 */
78 0x0000, /* R26 - Power Management (2) */ 79 { 46, 0x01BA }, /* R46 - PLL Control 3 */
79 0x0000, /* R27 - Additional Control (3) */ 80 { 59, 0x0000 }, /* R59 - PLL Control 4 */
80 0x0000, /* R28 */
81 0x0000, /* R29 */
82 0x0000, /* R30 */
83 0x0000, /* R31 */
84 0x0000, /* R32 */
85 0x0000, /* R33 */
86 0x0050, /* R34 - Left out Mix (1) */
87 0x0050, /* R35 - Left out Mix (2) */
88 0x0050, /* R36 - Right out Mix (1) */
89 0x0050, /* R37 - Right Out Mix (2) */
90 0x0050, /* R38 - Mono out Mix (1) */
91 0x0050, /* R39 - Mono out Mix (2) */
92 0x0079, /* R40 - LOUT2 volume */
93 0x0079, /* R41 - ROUT2 volume */
94 0x0079, /* R42 - MONOOUT volume */
95 0x0000, /* R43 - Clocking / PLL */
96 0x0103, /* R44 - PLL Control 1 */
97 0x0024, /* R45 - PLL Control 2 */
98 0x01BA, /* R46 - PLL Control 3 */
99 0x0000, /* R47 */
100 0x0000, /* R48 */
101 0x0000, /* R49 */
102 0x0000, /* R50 */
103 0x0000, /* R51 */
104 0x0000, /* R52 */
105 0x0000, /* R53 */
106 0x0000, /* R54 */
107 0x0000, /* R55 */
108 0x0000, /* R56 */
109 0x0000, /* R57 */
110 0x0000, /* R58 */
111 0x0000, /* R59 - PLL Control 4 */
112}; 81};
113 82
83static bool wm8955_writeable(struct device *dev, unsigned int reg)
84{
85 switch (reg) {
86 case WM8955_LOUT1_VOLUME:
87 case WM8955_ROUT1_VOLUME:
88 case WM8955_DAC_CONTROL:
89 case WM8955_AUDIO_INTERFACE:
90 case WM8955_SAMPLE_RATE:
91 case WM8955_LEFT_DAC_VOLUME:
92 case WM8955_RIGHT_DAC_VOLUME:
93 case WM8955_BASS_CONTROL:
94 case WM8955_TREBLE_CONTROL:
95 case WM8955_RESET:
96 case WM8955_ADDITIONAL_CONTROL_1:
97 case WM8955_ADDITIONAL_CONTROL_2:
98 case WM8955_POWER_MANAGEMENT_1:
99 case WM8955_POWER_MANAGEMENT_2:
100 case WM8955_ADDITIONAL_CONTROL_3:
101 case WM8955_LEFT_OUT_MIX_1:
102 case WM8955_LEFT_OUT_MIX_2:
103 case WM8955_RIGHT_OUT_MIX_1:
104 case WM8955_RIGHT_OUT_MIX_2:
105 case WM8955_MONO_OUT_MIX_1:
106 case WM8955_MONO_OUT_MIX_2:
107 case WM8955_LOUT2_VOLUME:
108 case WM8955_ROUT2_VOLUME:
109 case WM8955_MONOOUT_VOLUME:
110 case WM8955_CLOCKING_PLL:
111 case WM8955_PLL_CONTROL_1:
112 case WM8955_PLL_CONTROL_2:
113 case WM8955_PLL_CONTROL_3:
114 case WM8955_PLL_CONTROL_4:
115 return true;
116 default:
117 return false;
118 }
119}
120
121static bool wm8955_volatile(struct device *dev, unsigned int reg)
122{
123 switch (reg) {
124 case WM8955_RESET:
125 return true;
126 default:
127 return false;
128 }
129}
130
114static int wm8955_reset(struct snd_soc_codec *codec) 131static int wm8955_reset(struct snd_soc_codec *codec)
115{ 132{
116 return snd_soc_write(codec, WM8955_RESET, 0); 133 return snd_soc_write(codec, WM8955_RESET, 0);
@@ -765,8 +782,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
765 enum snd_soc_bias_level level) 782 enum snd_soc_bias_level level)
766{ 783{
767 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 784 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
768 u16 *reg_cache = codec->reg_cache; 785 int ret;
769 int ret, i;
770 786
771 switch (level) { 787 switch (level) {
772 case SND_SOC_BIAS_ON: 788 case SND_SOC_BIAS_ON:
@@ -795,7 +811,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
795 return ret; 811 return ret;
796 } 812 }
797 813
798 snd_soc_cache_sync(codec); 814 regcache_sync(wm8955->regmap);
799 815
800 /* Enable VREF and VMID */ 816 /* Enable VREF and VMID */
801 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1, 817 snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
@@ -869,8 +885,12 @@ static struct snd_soc_dai_driver wm8955_dai = {
869#ifdef CONFIG_PM 885#ifdef CONFIG_PM
870static int wm8955_suspend(struct snd_soc_codec *codec) 886static int wm8955_suspend(struct snd_soc_codec *codec)
871{ 887{
888 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
889
872 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF); 890 wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
873 891
892 regcache_mark_dirty(wm8955->regmap);
893
874 return 0; 894 return 0;
875} 895}
876 896
@@ -889,10 +909,11 @@ static int wm8955_probe(struct snd_soc_codec *codec)
889{ 909{
890 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec); 910 struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
891 struct wm8955_pdata *pdata = dev_get_platdata(codec->dev); 911 struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
892 u16 *reg_cache = codec->reg_cache;
893 int ret, i; 912 int ret, i;
894 913
895 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type); 914 codec->control_data = wm8955->regmap;
915
916 ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
896 if (ret != 0) { 917 if (ret != 0) {
897 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); 918 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
898 return ret; 919 return ret;
@@ -947,12 +968,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
947 /* Set platform data values */ 968 /* Set platform data values */
948 if (pdata) { 969 if (pdata) {
949 if (pdata->out2_speaker) 970 if (pdata->out2_speaker)
950 reg_cache[WM8955_ADDITIONAL_CONTROL_2] 971 snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2,
951 |= WM8955_ROUT2INV; 972 WM8955_ROUT2INV, WM8955_ROUT2INV);
952 973
953 if (pdata->monoin_diff) 974 if (pdata->monoin_diff)
954 reg_cache[WM8955_MONO_OUT_MIX_1] 975 snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1,
955 |= WM8955_DMEN; 976 WM8955_DMEN, WM8955_DMEN);
956 } 977 }
957 978
958 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 979 wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -985,9 +1006,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
985 .suspend = wm8955_suspend, 1006 .suspend = wm8955_suspend,
986 .resume = wm8955_resume, 1007 .resume = wm8955_resume,
987 .set_bias_level = wm8955_set_bias_level, 1008 .set_bias_level = wm8955_set_bias_level,
988 .reg_cache_size = ARRAY_SIZE(wm8955_reg), 1009};
989 .reg_word_size = sizeof(u16), 1010
990 .reg_cache_default = wm8955_reg, 1011static const struct regmap_config wm8955_regmap = {
1012 .reg_bits = 7,
1013 .val_bits = 9,
1014
1015 .max_register = WM8955_MAX_REGISTER,
1016 .volatile_reg = wm8955_volatile,
1017 .writeable_reg = wm8955_writeable,
1018
1019 .cache_type = REGCACHE_RBTREE,
1020 .reg_defaults = wm8955_reg_defaults,
1021 .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
991}; 1022};
992 1023
993static __devinit int wm8955_i2c_probe(struct i2c_client *i2c, 1024static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
@@ -1001,18 +1032,35 @@ static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
1001 if (wm8955 == NULL) 1032 if (wm8955 == NULL)
1002 return -ENOMEM; 1033 return -ENOMEM;
1003 1034
1035 wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
1036 if (IS_ERR(wm8955->regmap)) {
1037 ret = PTR_ERR(wm8955->regmap);
1038 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
1039 ret);
1040 return ret;
1041 }
1042
1004 i2c_set_clientdata(i2c, wm8955); 1043 i2c_set_clientdata(i2c, wm8955);
1005 wm8955->control_type = SND_SOC_I2C;
1006 1044
1007 ret = snd_soc_register_codec(&i2c->dev, 1045 ret = snd_soc_register_codec(&i2c->dev,
1008 &soc_codec_dev_wm8955, &wm8955_dai, 1); 1046 &soc_codec_dev_wm8955, &wm8955_dai, 1);
1047 if (ret != 0)
1048 goto err;
1049
1050 return ret;
1009 1051
1052err:
1053 regmap_exit(wm8955->regmap);
1010 return ret; 1054 return ret;
1011} 1055}
1012 1056
1013static __devexit int wm8955_i2c_remove(struct i2c_client *client) 1057static __devexit int wm8955_i2c_remove(struct i2c_client *client)
1014{ 1058{
1059 struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
1060
1015 snd_soc_unregister_codec(&client->dev); 1061 snd_soc_unregister_codec(&client->dev);
1062 regmap_exit(wm8955->regmap);
1063
1016 return 0; 1064 return 0;
1017} 1065}
1018 1066