diff options
author | Barry Song <21cnbao@gmail.com> | 2010-01-26 22:46:18 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-01-27 05:43:09 -0500 |
commit | 994dc4245d3f50329da4ead453a5dfcfbc716a0d (patch) | |
tree | 1523d8129ccf168d953c44e500a01e5f13cb8dbf /sound/soc/codecs/ad1938.c | |
parent | 63b62ab0d52c736b3274b294df962e0a4b7aae79 (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.c | 164 |
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 */ | ||
50 | static 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 | |||
49 | static struct snd_soc_codec *ad1938_codec; | 54 | static struct snd_soc_codec *ad1938_codec; |
50 | struct snd_soc_codec_device soc_codec_dev_ad1938; | 55 | struct snd_soc_codec_device soc_codec_dev_ad1938; |
51 | static int ad1938_register(struct ad1938_priv *ad1938); | 56 | static 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 | |||
314 | static 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 | |||
345 | static 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 | |||
360 | static 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 | |||
387 | static 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) { |