aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorBarry Song <21cnbao@gmail.com>2010-01-26 22:46:17 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-27 05:42:59 -0500
commit63b62ab0d52c736b3274b294df962e0a4b7aae79 (patch)
tree1a26ae8ddc231a1d6061617abe1b5afcb46fc336 /sound
parente473b847424bd215b686cbc1e781e82c904ee967 (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.c92
-rw-r--r--sound/soc/soc-cache.c67
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
186static 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 */
215static 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
227static int ad1836_soc_suspend(struct platform_device *pdev, 175static 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
240static int ad1836_soc_resume(struct platform_device *pdev) 188static 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
18static 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
27static 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)
51static 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
18static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, 80static 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,