diff options
Diffstat (limited to 'sound/soc/codecs/lm4857.c')
-rw-r--r-- | sound/soc/codecs/lm4857.c | 107 |
1 files changed, 31 insertions, 76 deletions
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index 9f9f59573f72..0e5743ea79df 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | 21 | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
@@ -23,12 +24,15 @@ | |||
23 | #include <sound/tlv.h> | 24 | #include <sound/tlv.h> |
24 | 25 | ||
25 | struct lm4857 { | 26 | struct lm4857 { |
26 | struct i2c_client *i2c; | 27 | struct regmap *regmap; |
27 | uint8_t mode; | 28 | uint8_t mode; |
28 | }; | 29 | }; |
29 | 30 | ||
30 | static const uint8_t lm4857_default_regs[] = { | 31 | static const struct reg_default lm4857_default_regs[] = { |
31 | 0x00, 0x00, 0x00, 0x00, | 32 | { 0x0, 0x00 }, |
33 | { 0x1, 0x00 }, | ||
34 | { 0x2, 0x00 }, | ||
35 | { 0x3, 0x00 }, | ||
32 | }; | 36 | }; |
33 | 37 | ||
34 | /* The register offsets in the cache array */ | 38 | /* The register offsets in the cache array */ |
@@ -42,39 +46,6 @@ static const uint8_t lm4857_default_regs[] = { | |||
42 | #define LM4857_WAKEUP 5 | 46 | #define LM4857_WAKEUP 5 |
43 | #define LM4857_EPGAIN 4 | 47 | #define LM4857_EPGAIN 4 |
44 | 48 | ||
45 | static int lm4857_write(struct snd_soc_codec *codec, unsigned int reg, | ||
46 | unsigned int value) | ||
47 | { | ||
48 | uint8_t data; | ||
49 | int ret; | ||
50 | |||
51 | ret = snd_soc_cache_write(codec, reg, value); | ||
52 | if (ret < 0) | ||
53 | return ret; | ||
54 | |||
55 | data = (reg << 6) | value; | ||
56 | ret = i2c_master_send(codec->control_data, &data, 1); | ||
57 | if (ret != 1) { | ||
58 | dev_err(codec->dev, "Failed to write register: %d\n", ret); | ||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static unsigned int lm4857_read(struct snd_soc_codec *codec, | ||
66 | unsigned int reg) | ||
67 | { | ||
68 | unsigned int val; | ||
69 | int ret; | ||
70 | |||
71 | ret = snd_soc_cache_read(codec, reg, &val); | ||
72 | if (ret) | ||
73 | return -1; | ||
74 | |||
75 | return val; | ||
76 | } | ||
77 | |||
78 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, | 49 | static int lm4857_get_mode(struct snd_kcontrol *kcontrol, |
79 | struct snd_ctl_elem_value *ucontrol) | 50 | struct snd_ctl_elem_value *ucontrol) |
80 | { | 51 | { |
@@ -96,7 +67,7 @@ static int lm4857_set_mode(struct snd_kcontrol *kcontrol, | |||
96 | lm4857->mode = value; | 67 | lm4857->mode = value; |
97 | 68 | ||
98 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) | 69 | if (codec->dapm.bias_level == SND_SOC_BIAS_ON) |
99 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, value + 6); | 70 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, value + 6); |
100 | 71 | ||
101 | return 1; | 72 | return 1; |
102 | } | 73 | } |
@@ -108,10 +79,11 @@ static int lm4857_set_bias_level(struct snd_soc_codec *codec, | |||
108 | 79 | ||
109 | switch (level) { | 80 | switch (level) { |
110 | case SND_SOC_BIAS_ON: | 81 | case SND_SOC_BIAS_ON: |
111 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, lm4857->mode + 6); | 82 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, |
83 | lm4857->mode + 6); | ||
112 | break; | 84 | break; |
113 | case SND_SOC_BIAS_STANDBY: | 85 | case SND_SOC_BIAS_STANDBY: |
114 | snd_soc_update_bits(codec, LM4857_CTRL, 0x0F, 0); | 86 | regmap_update_bits(lm4857->regmap, LM4857_CTRL, 0x0F, 0); |
115 | break; | 87 | break; |
116 | default: | 88 | default: |
117 | break; | 89 | break; |
@@ -171,49 +143,32 @@ static const struct snd_soc_dapm_route lm4857_routes[] = { | |||
171 | {"EP", NULL, "IN"}, | 143 | {"EP", NULL, "IN"}, |
172 | }; | 144 | }; |
173 | 145 | ||
174 | static int lm4857_probe(struct snd_soc_codec *codec) | 146 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { |
175 | { | 147 | .set_bias_level = lm4857_set_bias_level, |
176 | struct lm4857 *lm4857 = snd_soc_codec_get_drvdata(codec); | ||
177 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
178 | int ret; | ||
179 | |||
180 | codec->control_data = lm4857->i2c; | ||
181 | |||
182 | ret = snd_soc_add_codec_controls(codec, lm4857_controls, | ||
183 | ARRAY_SIZE(lm4857_controls)); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
187 | ret = snd_soc_dapm_new_controls(dapm, lm4857_dapm_widgets, | ||
188 | ARRAY_SIZE(lm4857_dapm_widgets)); | ||
189 | if (ret) | ||
190 | return ret; | ||
191 | 148 | ||
192 | ret = snd_soc_dapm_add_routes(dapm, lm4857_routes, | 149 | .controls = lm4857_controls, |
193 | ARRAY_SIZE(lm4857_routes)); | 150 | .num_controls = ARRAY_SIZE(lm4857_controls), |
194 | if (ret) | 151 | .dapm_widgets = lm4857_dapm_widgets, |
195 | return ret; | 152 | .num_dapm_widgets = ARRAY_SIZE(lm4857_dapm_widgets), |
153 | .dapm_routes = lm4857_routes, | ||
154 | .num_dapm_routes = ARRAY_SIZE(lm4857_routes), | ||
155 | }; | ||
196 | 156 | ||
197 | snd_soc_dapm_new_widgets(dapm); | 157 | static const struct regmap_config lm4857_regmap_config = { |
158 | .val_bits = 6, | ||
159 | .reg_bits = 2, | ||
198 | 160 | ||
199 | return 0; | 161 | .max_register = LM4857_CTRL, |
200 | } | ||
201 | 162 | ||
202 | static struct snd_soc_codec_driver soc_codec_dev_lm4857 = { | 163 | .cache_type = REGCACHE_FLAT, |
203 | .write = lm4857_write, | 164 | .reg_defaults = lm4857_default_regs, |
204 | .read = lm4857_read, | 165 | .num_reg_defaults = ARRAY_SIZE(lm4857_default_regs), |
205 | .probe = lm4857_probe, | ||
206 | .reg_cache_size = ARRAY_SIZE(lm4857_default_regs), | ||
207 | .reg_word_size = sizeof(uint8_t), | ||
208 | .reg_cache_default = lm4857_default_regs, | ||
209 | .set_bias_level = lm4857_set_bias_level, | ||
210 | }; | 166 | }; |
211 | 167 | ||
212 | static int lm4857_i2c_probe(struct i2c_client *i2c, | 168 | static int lm4857_i2c_probe(struct i2c_client *i2c, |
213 | const struct i2c_device_id *id) | 169 | const struct i2c_device_id *id) |
214 | { | 170 | { |
215 | struct lm4857 *lm4857; | 171 | struct lm4857 *lm4857; |
216 | int ret; | ||
217 | 172 | ||
218 | lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); | 173 | lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL); |
219 | if (!lm4857) | 174 | if (!lm4857) |
@@ -221,11 +176,11 @@ static int lm4857_i2c_probe(struct i2c_client *i2c, | |||
221 | 176 | ||
222 | i2c_set_clientdata(i2c, lm4857); | 177 | i2c_set_clientdata(i2c, lm4857); |
223 | 178 | ||
224 | lm4857->i2c = i2c; | 179 | lm4857->regmap = devm_regmap_init_i2c(i2c, &lm4857_regmap_config); |
225 | 180 | if (IS_ERR(lm4857->regmap)) | |
226 | ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); | 181 | return PTR_ERR(lm4857->regmap); |
227 | 182 | ||
228 | return ret; | 183 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0); |
229 | } | 184 | } |
230 | 185 | ||
231 | static int lm4857_i2c_remove(struct i2c_client *i2c) | 186 | static int lm4857_i2c_remove(struct i2c_client *i2c) |