aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/ad1938.c
diff options
context:
space:
mode:
authorBarry Song <21cnbao@gmail.com>2010-01-26 22:46:18 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-01-27 05:43:09 -0500
commit994dc4245d3f50329da4ead453a5dfcfbc716a0d (patch)
tree1523d8129ccf168d953c44e500a01e5f13cb8dbf /sound/soc/codecs/ad1938.c
parent63b62ab0d52c736b3274b294df962e0a4b7aae79 (diff)
ASoC: ad1938: 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/soc/codecs/ad1938.c')
-rw-r--r--sound/soc/codecs/ad1938.c164
1 files changed, 36 insertions, 128 deletions
diff --git a/sound/soc/codecs/ad1938.c b/sound/soc/codecs/ad1938.c
index 47d9ac0ec9d9..c233810d463d 100644
--- a/sound/soc/codecs/ad1938.c
+++ b/sound/soc/codecs/ad1938.c
@@ -46,6 +46,11 @@ struct ad1938_priv {
46 u8 reg_cache[AD1938_NUM_REGS]; 46 u8 reg_cache[AD1938_NUM_REGS];
47}; 47};
48 48
49/* ad1938 register cache & default register settings */
50static const u8 ad1938_reg[AD1938_NUM_REGS] = {
51 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0, 0,
52};
53
49static struct snd_soc_codec *ad1938_codec; 54static struct snd_soc_codec *ad1938_codec;
50struct snd_soc_codec_device soc_codec_dev_ad1938; 55struct snd_soc_codec_device soc_codec_dev_ad1938;
51static int ad1938_register(struct ad1938_priv *ad1938); 56static int ad1938_register(struct ad1938_priv *ad1938);
@@ -129,10 +134,10 @@ static int ad1938_mute(struct snd_soc_dai *dai, int mute)
129 struct snd_soc_codec *codec = dai->codec; 134 struct snd_soc_codec *codec = dai->codec;
130 int reg; 135 int reg;
131 136
132 reg = codec->read(codec, AD1938_DAC_CTRL2); 137 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
133 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg & 138 reg = (mute > 0) ? reg | AD1938_DAC_MASTER_MUTE : reg &
134 (~AD1938_DAC_MASTER_MUTE); 139 (~AD1938_DAC_MASTER_MUTE);
135 codec->write(codec, AD1938_DAC_CTRL2, reg); 140 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
136 141
137 return 0; 142 return 0;
138} 143}
@@ -141,8 +146,8 @@ static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
141 unsigned int rx_mask, int slots, int width) 146 unsigned int rx_mask, int slots, int width)
142{ 147{
143 struct snd_soc_codec *codec = dai->codec; 148 struct snd_soc_codec *codec = dai->codec;
144 int dac_reg = codec->read(codec, AD1938_DAC_CTRL1); 149 int dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
145 int adc_reg = codec->read(codec, AD1938_ADC_CTRL2); 150 int adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
146 151
147 dac_reg &= ~AD1938_DAC_CHAN_MASK; 152 dac_reg &= ~AD1938_DAC_CHAN_MASK;
148 adc_reg &= ~AD1938_ADC_CHAN_MASK; 153 adc_reg &= ~AD1938_ADC_CHAN_MASK;
@@ -168,8 +173,8 @@ static int ad1938_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
168 return -EINVAL; 173 return -EINVAL;
169 } 174 }
170 175
171 codec->write(codec, AD1938_DAC_CTRL1, dac_reg); 176 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
172 codec->write(codec, AD1938_ADC_CTRL2, adc_reg); 177 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
173 178
174 return 0; 179 return 0;
175} 180}
@@ -180,8 +185,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
180 struct snd_soc_codec *codec = codec_dai->codec; 185 struct snd_soc_codec *codec = codec_dai->codec;
181 int adc_reg, dac_reg; 186 int adc_reg, dac_reg;
182 187
183 adc_reg = codec->read(codec, AD1938_ADC_CTRL2); 188 adc_reg = snd_soc_read(codec, AD1938_ADC_CTRL2);
184 dac_reg = codec->read(codec, AD1938_DAC_CTRL1); 189 dac_reg = snd_soc_read(codec, AD1938_DAC_CTRL1);
185 190
186 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S 191 /* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
187 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A) 192 * with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
@@ -258,8 +263,8 @@ static int ad1938_set_dai_fmt(struct snd_soc_dai *codec_dai,
258 return -EINVAL; 263 return -EINVAL;
259 } 264 }
260 265
261 codec->write(codec, AD1938_ADC_CTRL2, adc_reg); 266 snd_soc_write(codec, AD1938_ADC_CTRL2, adc_reg);
262 codec->write(codec, AD1938_DAC_CTRL1, dac_reg); 267 snd_soc_write(codec, AD1938_DAC_CTRL1, dac_reg);
263 268
264 return 0; 269 return 0;
265} 270}
@@ -288,116 +293,13 @@ static int ad1938_hw_params(struct snd_pcm_substream *substream,
288 break; 293 break;
289 } 294 }
290 295
291 reg = codec->read(codec, AD1938_DAC_CTRL2); 296 reg = snd_soc_read(codec, AD1938_DAC_CTRL2);
292 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len; 297 reg = (reg & (~AD1938_DAC_WORD_LEN_MASK)) | word_len;
293 codec->write(codec, AD1938_DAC_CTRL2, reg); 298 snd_soc_write(codec, AD1938_DAC_CTRL2, reg);
294 299
295 reg = codec->read(codec, AD1938_ADC_CTRL1); 300 reg = snd_soc_read(codec, AD1938_ADC_CTRL1);
296 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len; 301 reg = (reg & (~AD1938_ADC_WORD_LEN_MASK)) | word_len;
297 codec->write(codec, AD1938_ADC_CTRL1, reg); 302 snd_soc_write(codec, AD1938_ADC_CTRL1, reg);
298
299 return 0;
300}
301
302/*
303 * interface to read/write ad1938 register
304 */
305
306#define AD1938_SPI_ADDR 0x4
307#define AD1938_SPI_READ 0x1
308#define AD1938_SPI_BUFLEN 3
309
310/*
311 * write to the ad1938 register space
312 */
313
314static int ad1938_write_reg(struct snd_soc_codec *codec, unsigned int reg,
315 unsigned int value)
316{
317 u8 *reg_cache = codec->reg_cache;
318 int ret = 0;
319
320 if (value != reg_cache[reg]) {
321 uint8_t buf[AD1938_SPI_BUFLEN];
322 struct spi_transfer t = {
323 .tx_buf = buf,
324 .len = AD1938_SPI_BUFLEN,
325 };
326 struct spi_message m;
327
328 buf[0] = AD1938_SPI_ADDR << 1;
329 buf[1] = reg;
330 buf[2] = value;
331 spi_message_init(&m);
332 spi_message_add_tail(&t, &m);
333 ret = spi_sync(codec->control_data, &m);
334 if (ret == 0)
335 reg_cache[reg] = value;
336 }
337
338 return ret;
339}
340
341/*
342 * read from the ad1938 register space cache
343 */
344
345static unsigned int ad1938_read_reg_cache(struct snd_soc_codec *codec,
346 unsigned int reg)
347{
348 u8 *reg_cache = codec->reg_cache;
349
350 if (reg >= codec->reg_cache_size)
351 return -EINVAL;
352
353 return reg_cache[reg];
354}
355
356/*
357 * read from the ad1938 register space
358 */
359
360static unsigned int ad1938_read_reg(struct snd_soc_codec *codec,
361 unsigned int reg)
362{
363 char w_buf[AD1938_SPI_BUFLEN];
364 char r_buf[AD1938_SPI_BUFLEN];
365 int ret;
366
367 struct spi_transfer t = {
368 .tx_buf = w_buf,
369 .rx_buf = r_buf,
370 .len = AD1938_SPI_BUFLEN,
371 };
372 struct spi_message m;
373
374 w_buf[0] = (AD1938_SPI_ADDR << 1) | AD1938_SPI_READ;
375 w_buf[1] = reg;
376 w_buf[2] = 0;
377
378 spi_message_init(&m);
379 spi_message_add_tail(&t, &m);
380 ret = spi_sync(codec->control_data, &m);
381 if (ret == 0)
382 return r_buf[2];
383 else
384 return -EIO;
385}
386
387static int ad1938_fill_cache(struct snd_soc_codec *codec)
388{
389 int i;
390 u8 *reg_cache = codec->reg_cache;
391 struct spi_device *spi = codec->control_data;
392
393 for (i = 0; i < codec->reg_cache_size; i++) {
394 int ret = ad1938_read_reg(codec, i);
395 if (ret == -EIO) {
396 dev_err(&spi->dev, "AD1938 SPI read failure\n");
397 return ret;
398 }
399 reg_cache[i] = ret;
400 }
401 303
402 return 0; 304 return 0;
403} 305}
@@ -487,31 +389,37 @@ static int ad1938_register(struct ad1938_priv *ad1938)
487 codec->owner = THIS_MODULE; 389 codec->owner = THIS_MODULE;
488 codec->dai = &ad1938_dai; 390 codec->dai = &ad1938_dai;
489 codec->num_dai = 1; 391 codec->num_dai = 1;
490 codec->write = ad1938_write_reg;
491 codec->read = ad1938_read_reg_cache;
492 INIT_LIST_HEAD(&codec->dapm_widgets); 392 INIT_LIST_HEAD(&codec->dapm_widgets);
493 INIT_LIST_HEAD(&codec->dapm_paths); 393 INIT_LIST_HEAD(&codec->dapm_paths);
494 394
495 ad1938_dai.dev = codec->dev; 395 ad1938_dai.dev = codec->dev;
496 ad1938_codec = codec; 396 ad1938_codec = codec;
497 397
398 memcpy(codec->reg_cache, ad1938_reg, AD1938_NUM_REGS);
399
400 ret = snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_SPI);
401 if (ret < 0) {
402 dev_err(codec->dev, "failed to set cache I/O: %d\n",
403 ret);
404 kfree(ad1938);
405 return ret;
406 }
407
498 /* default setting for ad1938 */ 408 /* default setting for ad1938 */
499 409
500 /* unmute dac channels */ 410 /* unmute dac channels */
501 codec->write(codec, AD1938_DAC_CHNL_MUTE, 0x0); 411 snd_soc_write(codec, AD1938_DAC_CHNL_MUTE, 0x0);
502 /* de-emphasis: 48kHz, powedown dac */ 412 /* de-emphasis: 48kHz, powedown dac */
503 codec->write(codec, AD1938_DAC_CTRL2, 0x1A); 413 snd_soc_write(codec, AD1938_DAC_CTRL2, 0x1A);
504 /* powerdown dac, dac in tdm mode */ 414 /* powerdown dac, dac in tdm mode */
505 codec->write(codec, AD1938_DAC_CTRL0, 0x41); 415 snd_soc_write(codec, AD1938_DAC_CTRL0, 0x41);
506 /* high-pass filter enable */ 416 /* high-pass filter enable */
507 codec->write(codec, AD1938_ADC_CTRL0, 0x3); 417 snd_soc_write(codec, AD1938_ADC_CTRL0, 0x3);
508 /* sata delay=1, adc aux mode */ 418 /* sata delay=1, adc aux mode */
509 codec->write(codec, AD1938_ADC_CTRL1, 0x43); 419 snd_soc_write(codec, AD1938_ADC_CTRL1, 0x43);
510 /* pll input: mclki/xi */ 420 /* pll input: mclki/xi */
511 codec->write(codec, AD1938_PLL_CLK_CTRL0, 0x9D); 421 snd_soc_write(codec, AD1938_PLL_CLK_CTRL0, 0x9D);
512 codec->write(codec, AD1938_PLL_CLK_CTRL1, 0x04); 422 snd_soc_write(codec, AD1938_PLL_CLK_CTRL1, 0x04);
513
514 ad1938_fill_cache(codec);
515 423
516 ret = snd_soc_register_codec(codec); 424 ret = snd_soc_register_codec(codec);
517 if (ret != 0) { 425 if (ret != 0) {