aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm8731.c
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2009-07-05 12:24:50 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-07-05 12:24:50 -0400
commit17a52fd60a0a0e617ed94aadb1b19751a8fa219e (patch)
tree2c2fd4526ae219ec9435a0a4b0fc281a5ca62b7c /sound/soc/codecs/wm8731.c
parent5420f30723122012c7bb868a55ff21c7d383b68e (diff)
ASoC: Begin to factor out register cache I/O functions
A lot of CODECs share the same register data formats and therefore replicate the code to manage access to and caching of the register map. In order to reduce code duplication centralised versions of this code will be introduced with drivers able to configure the use of the common code by calling the new snd_soc_codec_set_cache_io() API call during startup. As an initial user the 7 bit address/9 bit data format used by many Wolfson devices is supported for write only CODECs and the drivers with straightforward register cache implementations are converted to use it. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/wm8731.c')
-rw-r--r--sound/soc/codecs/wm8731.c108
1 files changed, 29 insertions, 79 deletions
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index dfbc1bb375f4..4eb84ff691b3 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -50,60 +50,12 @@ static int wm8731_spi_write(struct spi_device *spi, const char *data, int len);
50 * There is no point in caching the reset register 50 * There is no point in caching the reset register
51 */ 51 */
52static const u16 wm8731_reg[WM8731_CACHEREGNUM] = { 52static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
53 0x0097, 0x0097, 0x0079, 0x0079, 53 0x0097, 0x0097, 0x0079, 0x0079,
54 0x000a, 0x0008, 0x009f, 0x000a, 54 0x000a, 0x0008, 0x009f, 0x000a,
55 0x0000, 0x0000 55 0x0000, 0x0000
56}; 56};
57 57
58/* 58#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
59 * read wm8731 register cache
60 */
61static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg == WM8731_RESET)
66 return 0;
67 if (reg >= WM8731_CACHEREGNUM)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8731 register cache
74 */
75static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
76 u16 reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg >= WM8731_CACHEREGNUM)
80 return;
81 cache[reg] = value;
82}
83
84/*
85 * write to the WM8731 register space
86 */
87static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
88 unsigned int value)
89{
90 u8 data[2];
91
92 /* data is
93 * D15..D9 WM8731 register offset
94 * D8...D0 register data
95 */
96 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
97 data[1] = value & 0x00ff;
98
99 wm8731_write_reg_cache(codec, reg, value);
100 if (codec->hw_write(codec->control_data, data, 2) == 2)
101 return 0;
102 else
103 return -EIO;
104}
105
106#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
107 59
108static const char *wm8731_input_select[] = {"Line In", "Mic"}; 60static const char *wm8731_input_select[] = {"Line In", "Mic"};
109static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 61static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -260,12 +212,12 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
260 struct snd_soc_device *socdev = rtd->socdev; 212 struct snd_soc_device *socdev = rtd->socdev;
261 struct snd_soc_codec *codec = socdev->card->codec; 213 struct snd_soc_codec *codec = socdev->card->codec;
262 struct wm8731_priv *wm8731 = codec->private_data; 214 struct wm8731_priv *wm8731 = codec->private_data;
263 u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3; 215 u16 iface = snd_soc_read(codec, WM8731_IFACE) & 0xfff3;
264 int i = get_coeff(wm8731->sysclk, params_rate(params)); 216 int i = get_coeff(wm8731->sysclk, params_rate(params));
265 u16 srate = (coeff_div[i].sr << 2) | 217 u16 srate = (coeff_div[i].sr << 2) |
266 (coeff_div[i].bosr << 1) | coeff_div[i].usb; 218 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
267 219
268 wm8731_write(codec, WM8731_SRATE, srate); 220 snd_soc_write(codec, WM8731_SRATE, srate);
269 221
270 /* bit size */ 222 /* bit size */
271 switch (params_format(params)) { 223 switch (params_format(params)) {
@@ -279,7 +231,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
279 break; 231 break;
280 } 232 }
281 233
282 wm8731_write(codec, WM8731_IFACE, iface); 234 snd_soc_write(codec, WM8731_IFACE, iface);
283 return 0; 235 return 0;
284} 236}
285 237
@@ -291,7 +243,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
291 struct snd_soc_codec *codec = socdev->card->codec; 243 struct snd_soc_codec *codec = socdev->card->codec;
292 244
293 /* set active */ 245 /* set active */
294 wm8731_write(codec, WM8731_ACTIVE, 0x0001); 246 snd_soc_write(codec, WM8731_ACTIVE, 0x0001);
295 247
296 return 0; 248 return 0;
297} 249}
@@ -306,19 +258,19 @@ static void wm8731_shutdown(struct snd_pcm_substream *substream,
306 /* deactivate */ 258 /* deactivate */
307 if (!codec->active) { 259 if (!codec->active) {
308 udelay(50); 260 udelay(50);
309 wm8731_write(codec, WM8731_ACTIVE, 0x0); 261 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
310 } 262 }
311} 263}
312 264
313static int wm8731_mute(struct snd_soc_dai *dai, int mute) 265static int wm8731_mute(struct snd_soc_dai *dai, int mute)
314{ 266{
315 struct snd_soc_codec *codec = dai->codec; 267 struct snd_soc_codec *codec = dai->codec;
316 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7; 268 u16 mute_reg = snd_soc_read(codec, WM8731_APDIGI) & 0xfff7;
317 269
318 if (mute) 270 if (mute)
319 wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8); 271 snd_soc_write(codec, WM8731_APDIGI, mute_reg | 0x8);
320 else 272 else
321 wm8731_write(codec, WM8731_APDIGI, mute_reg); 273 snd_soc_write(codec, WM8731_APDIGI, mute_reg);
322 return 0; 274 return 0;
323} 275}
324 276
@@ -396,7 +348,7 @@ static int wm8731_set_dai_fmt(struct snd_soc_dai *codec_dai,
396 } 348 }
397 349
398 /* set iface */ 350 /* set iface */
399 wm8731_write(codec, WM8731_IFACE, iface); 351 snd_soc_write(codec, WM8731_IFACE, iface);
400 return 0; 352 return 0;
401} 353}
402 354
@@ -412,12 +364,12 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
412 break; 364 break;
413 case SND_SOC_BIAS_STANDBY: 365 case SND_SOC_BIAS_STANDBY:
414 /* Clear PWROFF, gate CLKOUT, everything else as-is */ 366 /* Clear PWROFF, gate CLKOUT, everything else as-is */
415 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f; 367 reg = snd_soc_read(codec, WM8731_PWR) & 0xff7f;
416 wm8731_write(codec, WM8731_PWR, reg | 0x0040); 368 snd_soc_write(codec, WM8731_PWR, reg | 0x0040);
417 break; 369 break;
418 case SND_SOC_BIAS_OFF: 370 case SND_SOC_BIAS_OFF:
419 wm8731_write(codec, WM8731_ACTIVE, 0x0); 371 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
420 wm8731_write(codec, WM8731_PWR, 0xffff); 372 snd_soc_write(codec, WM8731_PWR, 0xffff);
421 break; 373 break;
422 } 374 }
423 codec->bias_level = level; 375 codec->bias_level = level;
@@ -466,7 +418,7 @@ static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
466 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 418 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
467 struct snd_soc_codec *codec = socdev->card->codec; 419 struct snd_soc_codec *codec = socdev->card->codec;
468 420
469 wm8731_write(codec, WM8731_ACTIVE, 0x0); 421 snd_soc_write(codec, WM8731_ACTIVE, 0x0);
470 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF); 422 wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
471 return 0; 423 return 0;
472} 424}
@@ -556,7 +508,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
556{ 508{
557 int ret; 509 int ret;
558 struct snd_soc_codec *codec = &wm8731->codec; 510 struct snd_soc_codec *codec = &wm8731->codec;
559 u16 reg;
560 511
561 if (wm8731_codec) { 512 if (wm8731_codec) {
562 dev_err(codec->dev, "Another WM8731 is registered\n"); 513 dev_err(codec->dev, "Another WM8731 is registered\n");
@@ -571,8 +522,6 @@ static int wm8731_register(struct wm8731_priv *wm8731)
571 codec->private_data = wm8731; 522 codec->private_data = wm8731;
572 codec->name = "WM8731"; 523 codec->name = "WM8731";
573 codec->owner = THIS_MODULE; 524 codec->owner = THIS_MODULE;
574 codec->read = wm8731_read_reg_cache;
575 codec->write = wm8731_write;
576 codec->bias_level = SND_SOC_BIAS_OFF; 525 codec->bias_level = SND_SOC_BIAS_OFF;
577 codec->set_bias_level = wm8731_set_bias_level; 526 codec->set_bias_level = wm8731_set_bias_level;
578 codec->dai = &wm8731_dai; 527 codec->dai = &wm8731_dai;
@@ -582,6 +531,12 @@ static int wm8731_register(struct wm8731_priv *wm8731)
582 531
583 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg)); 532 memcpy(codec->reg_cache, wm8731_reg, sizeof(wm8731_reg));
584 533
534 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
535 if (ret < 0) {
536 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
537 goto err;
538 }
539
585 ret = wm8731_reset(codec); 540 ret = wm8731_reset(codec);
586 if (ret < 0) { 541 if (ret < 0) {
587 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); 542 dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
@@ -593,18 +548,13 @@ static int wm8731_register(struct wm8731_priv *wm8731)
593 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 548 wm8731_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
594 549
595 /* Latch the update bits */ 550 /* Latch the update bits */
596 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V); 551 snd_soc_update_bits(codec, WM8731_LOUT1V, 0x100, 0);
597 wm8731_write(codec, WM8731_LOUT1V, reg & ~0x0100); 552 snd_soc_update_bits(codec, WM8731_ROUT1V, 0x100, 0);
598 reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V); 553 snd_soc_update_bits(codec, WM8731_LINVOL, 0x100, 0);
599 wm8731_write(codec, WM8731_ROUT1V, reg & ~0x0100); 554 snd_soc_update_bits(codec, WM8731_RINVOL, 0x100, 0);
600 reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
601 wm8731_write(codec, WM8731_LINVOL, reg & ~0x0100);
602 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
603 wm8731_write(codec, WM8731_RINVOL, reg & ~0x0100);
604 555
605 /* Disable bypass path by default */ 556 /* Disable bypass path by default */
606 reg = wm8731_read_reg_cache(codec, WM8731_APANA); 557 snd_soc_update_bits(codec, WM8731_APANA, 0x4, 0);
607 wm8731_write(codec, WM8731_APANA, reg & ~0x4);
608 558
609 wm8731_codec = codec; 559 wm8731_codec = codec;
610 560