diff options
author | Barry Song <21cnbao@gmail.com> | 2010-01-26 22:46:17 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-01-27 05:42:59 -0500 |
commit | 63b62ab0d52c736b3274b294df962e0a4b7aae79 (patch) | |
tree | 1a26ae8ddc231a1d6061617abe1b5afcb46fc336 /sound | |
parent | e473b847424bd215b686cbc1e781e82c904ee967 (diff) |
ASoC: ad1836: use soc-cache framework for codec registers access
Signed-off-by: Barry Song <Barry.Song@analog.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/codecs/ad1836.c | 92 | ||||
-rw-r--r-- | sound/soc/soc-cache.c | 67 |
2 files changed, 90 insertions, 69 deletions
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index 83add2f3afba..3c80137d5938 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -171,58 +171,6 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream, | |||
171 | return 0; | 171 | return 0; |
172 | } | 172 | } |
173 | 173 | ||
174 | |||
175 | /* | ||
176 | * interface to read/write ad1836 register | ||
177 | */ | ||
178 | #define AD1836_SPI_REG_SHFT 12 | ||
179 | #define AD1836_SPI_READ (1 << 11) | ||
180 | #define AD1836_SPI_VAL_MSK 0x3FF | ||
181 | |||
182 | /* | ||
183 | * write to the ad1836 register space | ||
184 | */ | ||
185 | |||
186 | static int ad1836_write_reg(struct snd_soc_codec *codec, unsigned int reg, | ||
187 | unsigned int value) | ||
188 | { | ||
189 | u16 *reg_cache = codec->reg_cache; | ||
190 | int ret = 0; | ||
191 | |||
192 | if (value != reg_cache[reg]) { | ||
193 | unsigned short buf; | ||
194 | struct spi_transfer t = { | ||
195 | .tx_buf = &buf, | ||
196 | .len = 2, | ||
197 | }; | ||
198 | struct spi_message m; | ||
199 | |||
200 | buf = (reg << AD1836_SPI_REG_SHFT) | | ||
201 | (value & AD1836_SPI_VAL_MSK); | ||
202 | spi_message_init(&m); | ||
203 | spi_message_add_tail(&t, &m); | ||
204 | ret = spi_sync(codec->control_data, &m); | ||
205 | if (ret == 0) | ||
206 | reg_cache[reg] = value; | ||
207 | } | ||
208 | |||
209 | return ret; | ||
210 | } | ||
211 | |||
212 | /* | ||
213 | * read from the ad1836 register space cache | ||
214 | */ | ||
215 | static unsigned int ad1836_read_reg_cache(struct snd_soc_codec *codec, | ||
216 | unsigned int reg) | ||
217 | { | ||
218 | u16 *reg_cache = codec->reg_cache; | ||
219 | |||
220 | if (reg >= codec->reg_cache_size) | ||
221 | return -EINVAL; | ||
222 | |||
223 | return reg_cache[reg]; | ||
224 | } | ||
225 | |||
226 | #ifdef CONFIG_PM | 174 | #ifdef CONFIG_PM |
227 | static int ad1836_soc_suspend(struct platform_device *pdev, | 175 | static int ad1836_soc_suspend(struct platform_device *pdev, |
228 | pm_message_t state) | 176 | pm_message_t state) |
@@ -231,10 +179,10 @@ static int ad1836_soc_suspend(struct platform_device *pdev, | |||
231 | struct snd_soc_codec *codec = socdev->card->codec; | 179 | struct snd_soc_codec *codec = socdev->card->codec; |
232 | 180 | ||
233 | /* reset clock control mode */ | 181 | /* reset clock control mode */ |
234 | u16 adc_ctrl2 = codec->read(codec, AD1836_ADC_CTRL2); | 182 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
235 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; | 183 | adc_ctrl2 &= ~AD1836_ADC_SERFMT_MASK; |
236 | 184 | ||
237 | return codec->write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | 185 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
238 | } | 186 | } |
239 | 187 | ||
240 | static int ad1836_soc_resume(struct platform_device *pdev) | 188 | static int ad1836_soc_resume(struct platform_device *pdev) |
@@ -243,10 +191,10 @@ static int ad1836_soc_resume(struct platform_device *pdev) | |||
243 | struct snd_soc_codec *codec = socdev->card->codec; | 191 | struct snd_soc_codec *codec = socdev->card->codec; |
244 | 192 | ||
245 | /* restore clock control mode */ | 193 | /* restore clock control mode */ |
246 | u16 adc_ctrl2 = codec->read(codec, AD1836_ADC_CTRL2); | 194 | u16 adc_ctrl2 = snd_soc_read(codec, AD1836_ADC_CTRL2); |
247 | adc_ctrl2 |= AD1836_ADC_AUX; | 195 | adc_ctrl2 |= AD1836_ADC_AUX; |
248 | 196 | ||
249 | return codec->write(codec, AD1836_ADC_CTRL2, adc_ctrl2); | 197 | return snd_soc_write(codec, AD1836_ADC_CTRL2, adc_ctrl2); |
250 | } | 198 | } |
251 | #else | 199 | #else |
252 | #define ad1836_soc_suspend NULL | 200 | #define ad1836_soc_suspend NULL |
@@ -336,32 +284,38 @@ static int ad1836_register(struct ad1836_priv *ad1836) | |||
336 | codec->owner = THIS_MODULE; | 284 | codec->owner = THIS_MODULE; |
337 | codec->dai = &ad1836_dai; | 285 | codec->dai = &ad1836_dai; |
338 | codec->num_dai = 1; | 286 | codec->num_dai = 1; |
339 | codec->write = ad1836_write_reg; | ||
340 | codec->read = ad1836_read_reg_cache; | ||
341 | INIT_LIST_HEAD(&codec->dapm_widgets); | 287 | INIT_LIST_HEAD(&codec->dapm_widgets); |
342 | INIT_LIST_HEAD(&codec->dapm_paths); | 288 | INIT_LIST_HEAD(&codec->dapm_paths); |
343 | 289 | ||
344 | ad1836_dai.dev = codec->dev; | 290 | ad1836_dai.dev = codec->dev; |
345 | ad1836_codec = codec; | 291 | ad1836_codec = codec; |
346 | 292 | ||
293 | ret = snd_soc_codec_set_cache_io(codec, 4, 12, SND_SOC_SPI); | ||
294 | if (ret < 0) { | ||
295 | dev_err(codec->dev, "failed to set cache I/O: %d\n", | ||
296 | ret); | ||
297 | kfree(ad1836); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
347 | /* default setting for ad1836 */ | 301 | /* default setting for ad1836 */ |
348 | /* de-emphasis: 48kHz, power-on dac */ | 302 | /* de-emphasis: 48kHz, power-on dac */ |
349 | codec->write(codec, AD1836_DAC_CTRL1, 0x300); | 303 | snd_soc_write(codec, AD1836_DAC_CTRL1, 0x300); |
350 | /* unmute dac channels */ | 304 | /* unmute dac channels */ |
351 | codec->write(codec, AD1836_DAC_CTRL2, 0x0); | 305 | snd_soc_write(codec, AD1836_DAC_CTRL2, 0x0); |
352 | /* high-pass filter enable, power-on adc */ | 306 | /* high-pass filter enable, power-on adc */ |
353 | codec->write(codec, AD1836_ADC_CTRL1, 0x100); | 307 | snd_soc_write(codec, AD1836_ADC_CTRL1, 0x100); |
354 | /* unmute adc channles, adc aux mode */ | 308 | /* unmute adc channles, adc aux mode */ |
355 | codec->write(codec, AD1836_ADC_CTRL2, 0x180); | 309 | snd_soc_write(codec, AD1836_ADC_CTRL2, 0x180); |
356 | /* left/right diff:PGA/MUX */ | 310 | /* left/right diff:PGA/MUX */ |
357 | codec->write(codec, AD1836_ADC_CTRL3, 0x3A); | 311 | snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A); |
358 | /* volume */ | 312 | /* volume */ |
359 | codec->write(codec, AD1836_DAC_L1_VOL, 0x3FF); | 313 | snd_soc_write(codec, AD1836_DAC_L1_VOL, 0x3FF); |
360 | codec->write(codec, AD1836_DAC_R1_VOL, 0x3FF); | 314 | snd_soc_write(codec, AD1836_DAC_R1_VOL, 0x3FF); |
361 | codec->write(codec, AD1836_DAC_L2_VOL, 0x3FF); | 315 | snd_soc_write(codec, AD1836_DAC_L2_VOL, 0x3FF); |
362 | codec->write(codec, AD1836_DAC_R2_VOL, 0x3FF); | 316 | snd_soc_write(codec, AD1836_DAC_R2_VOL, 0x3FF); |
363 | codec->write(codec, AD1836_DAC_L3_VOL, 0x3FF); | 317 | snd_soc_write(codec, AD1836_DAC_L3_VOL, 0x3FF); |
364 | codec->write(codec, AD1836_DAC_R3_VOL, 0x3FF); | 318 | snd_soc_write(codec, AD1836_DAC_R3_VOL, 0x3FF); |
365 | 319 | ||
366 | ret = snd_soc_register_codec(codec); | 320 | ret = snd_soc_register_codec(codec); |
367 | if (ret != 0) { | 321 | if (ret != 0) { |
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c index 02c235711bb8..cde7b63de113 100644 --- a/sound/soc/soc-cache.c +++ b/sound/soc/soc-cache.c | |||
@@ -15,6 +15,68 @@ | |||
15 | #include <linux/spi/spi.h> | 15 | #include <linux/spi/spi.h> |
16 | #include <sound/soc.h> | 16 | #include <sound/soc.h> |
17 | 17 | ||
18 | static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, | ||
19 | unsigned int reg) | ||
20 | { | ||
21 | u16 *cache = codec->reg_cache; | ||
22 | if (reg >= codec->reg_cache_size) | ||
23 | return -1; | ||
24 | return cache[reg]; | ||
25 | } | ||
26 | |||
27 | static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, | ||
28 | unsigned int value) | ||
29 | { | ||
30 | u16 *cache = codec->reg_cache; | ||
31 | u8 data[2]; | ||
32 | int ret; | ||
33 | |||
34 | BUG_ON(codec->volatile_register); | ||
35 | |||
36 | data[0] = (reg << 4) | ((value >> 8) & 0x000f); | ||
37 | data[1] = value & 0x00ff; | ||
38 | |||
39 | if (reg < codec->reg_cache_size) | ||
40 | cache[reg] = value; | ||
41 | ret = codec->hw_write(codec->control_data, data, 2); | ||
42 | if (ret == 2) | ||
43 | return 0; | ||
44 | if (ret < 0) | ||
45 | return ret; | ||
46 | else | ||
47 | return -EIO; | ||
48 | } | ||
49 | |||
50 | #if defined(CONFIG_SPI_MASTER) | ||
51 | static int snd_soc_4_12_spi_write(void *control_data, const char *data, | ||
52 | int len) | ||
53 | { | ||
54 | struct spi_device *spi = control_data; | ||
55 | struct spi_transfer t; | ||
56 | struct spi_message m; | ||
57 | u8 msg[2]; | ||
58 | |||
59 | if (len <= 0) | ||
60 | return 0; | ||
61 | |||
62 | msg[0] = data[1]; | ||
63 | msg[1] = data[0]; | ||
64 | |||
65 | spi_message_init(&m); | ||
66 | memset(&t, 0, (sizeof t)); | ||
67 | |||
68 | t.tx_buf = &msg[0]; | ||
69 | t.len = len; | ||
70 | |||
71 | spi_message_add_tail(&t, &m); | ||
72 | spi_sync(spi, &m); | ||
73 | |||
74 | return len; | ||
75 | } | ||
76 | #else | ||
77 | #define snd_soc_4_12_spi_write NULL | ||
78 | #endif | ||
79 | |||
18 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, | 80 | static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, |
19 | unsigned int reg) | 81 | unsigned int reg) |
20 | { | 82 | { |
@@ -180,6 +242,11 @@ static struct { | |||
180 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); | 242 | unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int); |
181 | } io_types[] = { | 243 | } io_types[] = { |
182 | { | 244 | { |
245 | .addr_bits = 4, .data_bits = 12, | ||
246 | .write = snd_soc_4_12_write, .read = snd_soc_4_12_read, | ||
247 | .spi_write = snd_soc_4_12_spi_write, | ||
248 | }, | ||
249 | { | ||
183 | .addr_bits = 7, .data_bits = 9, | 250 | .addr_bits = 7, .data_bits = 9, |
184 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, | 251 | .write = snd_soc_7_9_write, .read = snd_soc_7_9_read, |
185 | .spi_write = snd_soc_7_9_spi_write, | 252 | .spi_write = snd_soc_7_9_spi_write, |