aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs
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
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')
-rw-r--r--sound/soc/codecs/wm8510.c141
-rw-r--r--sound/soc/codecs/wm8728.c78
-rw-r--r--sound/soc/codecs/wm8731.c108
-rw-r--r--sound/soc/codecs/wm8750.c121
-rw-r--r--sound/soc/codecs/wm8960.c194
-rw-r--r--sound/soc/codecs/wm8971.c121
-rw-r--r--sound/soc/codecs/wm8988.c105
7 files changed, 292 insertions, 576 deletions
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index c8b8dba85890..7a169bff86f9 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -58,55 +58,7 @@ static const u16 wm8510_reg[WM8510_CACHEREGNUM] = {
58#define WM8510_POWER1_BIASEN 0x08 58#define WM8510_POWER1_BIASEN 0x08
59#define WM8510_POWER1_BUFIOEN 0x10 59#define WM8510_POWER1_BUFIOEN 0x10
60 60
61/* 61#define wm8510_reset(c) snd_soc_write(c, WM8510_RESET, 0)
62 * read wm8510 register cache
63 */
64static inline unsigned int wm8510_read_reg_cache(struct snd_soc_codec *codec,
65 unsigned int reg)
66{
67 u16 *cache = codec->reg_cache;
68 if (reg == WM8510_RESET)
69 return 0;
70 if (reg >= WM8510_CACHEREGNUM)
71 return -1;
72 return cache[reg];
73}
74
75/*
76 * write wm8510 register cache
77 */
78static inline void wm8510_write_reg_cache(struct snd_soc_codec *codec,
79 u16 reg, unsigned int value)
80{
81 u16 *cache = codec->reg_cache;
82 if (reg >= WM8510_CACHEREGNUM)
83 return;
84 cache[reg] = value;
85}
86
87/*
88 * write to the WM8510 register space
89 */
90static int wm8510_write(struct snd_soc_codec *codec, unsigned int reg,
91 unsigned int value)
92{
93 u8 data[2];
94
95 /* data is
96 * D15..D9 WM8510 register offset
97 * D8...D0 register data
98 */
99 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
100 data[1] = value & 0x00ff;
101
102 wm8510_write_reg_cache(codec, reg, value);
103 if (codec->hw_write(codec->control_data, data, 2) == 2)
104 return 0;
105 else
106 return -EIO;
107}
108
109#define wm8510_reset(c) wm8510_write(c, WM8510_RESET, 0)
110 62
111static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" }; 63static const char *wm8510_companding[] = { "Off", "NC", "u-law", "A-law" };
112static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" }; 64static const char *wm8510_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
@@ -327,27 +279,27 @@ static int wm8510_set_dai_pll(struct snd_soc_dai *codec_dai,
327 279
328 if (freq_in == 0 || freq_out == 0) { 280 if (freq_in == 0 || freq_out == 0) {
329 /* Clock CODEC directly from MCLK */ 281 /* Clock CODEC directly from MCLK */
330 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 282 reg = snd_soc_read(codec, WM8510_CLOCK);
331 wm8510_write(codec, WM8510_CLOCK, reg & 0x0ff); 283 snd_soc_write(codec, WM8510_CLOCK, reg & 0x0ff);
332 284
333 /* Turn off PLL */ 285 /* Turn off PLL */
334 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 286 reg = snd_soc_read(codec, WM8510_POWER1);
335 wm8510_write(codec, WM8510_POWER1, reg & 0x1df); 287 snd_soc_write(codec, WM8510_POWER1, reg & 0x1df);
336 return 0; 288 return 0;
337 } 289 }
338 290
339 pll_factors(freq_out*4, freq_in); 291 pll_factors(freq_out*4, freq_in);
340 292
341 wm8510_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n); 293 snd_soc_write(codec, WM8510_PLLN, (pll_div.pre_div << 4) | pll_div.n);
342 wm8510_write(codec, WM8510_PLLK1, pll_div.k >> 18); 294 snd_soc_write(codec, WM8510_PLLK1, pll_div.k >> 18);
343 wm8510_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff); 295 snd_soc_write(codec, WM8510_PLLK2, (pll_div.k >> 9) & 0x1ff);
344 wm8510_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff); 296 snd_soc_write(codec, WM8510_PLLK3, pll_div.k & 0x1ff);
345 reg = wm8510_read_reg_cache(codec, WM8510_POWER1); 297 reg = snd_soc_read(codec, WM8510_POWER1);
346 wm8510_write(codec, WM8510_POWER1, reg | 0x020); 298 snd_soc_write(codec, WM8510_POWER1, reg | 0x020);
347 299
348 /* Run CODEC from PLL instead of MCLK */ 300 /* Run CODEC from PLL instead of MCLK */
349 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK); 301 reg = snd_soc_read(codec, WM8510_CLOCK);
350 wm8510_write(codec, WM8510_CLOCK, reg | 0x100); 302 snd_soc_write(codec, WM8510_CLOCK, reg | 0x100);
351 303
352 return 0; 304 return 0;
353} 305}
@@ -363,24 +315,24 @@ static int wm8510_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
363 315
364 switch (div_id) { 316 switch (div_id) {
365 case WM8510_OPCLKDIV: 317 case WM8510_OPCLKDIV:
366 reg = wm8510_read_reg_cache(codec, WM8510_GPIO) & 0x1cf; 318 reg = snd_soc_read(codec, WM8510_GPIO) & 0x1cf;
367 wm8510_write(codec, WM8510_GPIO, reg | div); 319 snd_soc_write(codec, WM8510_GPIO, reg | div);
368 break; 320 break;
369 case WM8510_MCLKDIV: 321 case WM8510_MCLKDIV:
370 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x11f; 322 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x11f;
371 wm8510_write(codec, WM8510_CLOCK, reg | div); 323 snd_soc_write(codec, WM8510_CLOCK, reg | div);
372 break; 324 break;
373 case WM8510_ADCCLK: 325 case WM8510_ADCCLK:
374 reg = wm8510_read_reg_cache(codec, WM8510_ADC) & 0x1f7; 326 reg = snd_soc_read(codec, WM8510_ADC) & 0x1f7;
375 wm8510_write(codec, WM8510_ADC, reg | div); 327 snd_soc_write(codec, WM8510_ADC, reg | div);
376 break; 328 break;
377 case WM8510_DACCLK: 329 case WM8510_DACCLK:
378 reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0x1f7; 330 reg = snd_soc_read(codec, WM8510_DAC) & 0x1f7;
379 wm8510_write(codec, WM8510_DAC, reg | div); 331 snd_soc_write(codec, WM8510_DAC, reg | div);
380 break; 332 break;
381 case WM8510_BCLKDIV: 333 case WM8510_BCLKDIV:
382 reg = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1e3; 334 reg = snd_soc_read(codec, WM8510_CLOCK) & 0x1e3;
383 wm8510_write(codec, WM8510_CLOCK, reg | div); 335 snd_soc_write(codec, WM8510_CLOCK, reg | div);
384 break; 336 break;
385 default: 337 default:
386 return -EINVAL; 338 return -EINVAL;
@@ -394,7 +346,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
394{ 346{
395 struct snd_soc_codec *codec = codec_dai->codec; 347 struct snd_soc_codec *codec = codec_dai->codec;
396 u16 iface = 0; 348 u16 iface = 0;
397 u16 clk = wm8510_read_reg_cache(codec, WM8510_CLOCK) & 0x1fe; 349 u16 clk = snd_soc_read(codec, WM8510_CLOCK) & 0x1fe;
398 350
399 /* set master/slave audio interface */ 351 /* set master/slave audio interface */
400 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { 352 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -441,8 +393,8 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
441 return -EINVAL; 393 return -EINVAL;
442 } 394 }
443 395
444 wm8510_write(codec, WM8510_IFACE, iface); 396 snd_soc_write(codec, WM8510_IFACE, iface);
445 wm8510_write(codec, WM8510_CLOCK, clk); 397 snd_soc_write(codec, WM8510_CLOCK, clk);
446 return 0; 398 return 0;
447} 399}
448 400
@@ -453,8 +405,8 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
453 struct snd_soc_pcm_runtime *rtd = substream->private_data; 405 struct snd_soc_pcm_runtime *rtd = substream->private_data;
454 struct snd_soc_device *socdev = rtd->socdev; 406 struct snd_soc_device *socdev = rtd->socdev;
455 struct snd_soc_codec *codec = socdev->card->codec; 407 struct snd_soc_codec *codec = socdev->card->codec;
456 u16 iface = wm8510_read_reg_cache(codec, WM8510_IFACE) & 0x19f; 408 u16 iface = snd_soc_read(codec, WM8510_IFACE) & 0x19f;
457 u16 adn = wm8510_read_reg_cache(codec, WM8510_ADD) & 0x1f1; 409 u16 adn = snd_soc_read(codec, WM8510_ADD) & 0x1f1;
458 410
459 /* bit size */ 411 /* bit size */
460 switch (params_format(params)) { 412 switch (params_format(params)) {
@@ -493,20 +445,20 @@ static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
493 break; 445 break;
494 } 446 }
495 447
496 wm8510_write(codec, WM8510_IFACE, iface); 448 snd_soc_write(codec, WM8510_IFACE, iface);
497 wm8510_write(codec, WM8510_ADD, adn); 449 snd_soc_write(codec, WM8510_ADD, adn);
498 return 0; 450 return 0;
499} 451}
500 452
501static int wm8510_mute(struct snd_soc_dai *dai, int mute) 453static int wm8510_mute(struct snd_soc_dai *dai, int mute)
502{ 454{
503 struct snd_soc_codec *codec = dai->codec; 455 struct snd_soc_codec *codec = dai->codec;
504 u16 mute_reg = wm8510_read_reg_cache(codec, WM8510_DAC) & 0xffbf; 456 u16 mute_reg = snd_soc_read(codec, WM8510_DAC) & 0xffbf;
505 457
506 if (mute) 458 if (mute)
507 wm8510_write(codec, WM8510_DAC, mute_reg | 0x40); 459 snd_soc_write(codec, WM8510_DAC, mute_reg | 0x40);
508 else 460 else
509 wm8510_write(codec, WM8510_DAC, mute_reg); 461 snd_soc_write(codec, WM8510_DAC, mute_reg);
510 return 0; 462 return 0;
511} 463}
512 464
@@ -514,13 +466,13 @@ static int wm8510_mute(struct snd_soc_dai *dai, int mute)
514static int wm8510_set_bias_level(struct snd_soc_codec *codec, 466static int wm8510_set_bias_level(struct snd_soc_codec *codec,
515 enum snd_soc_bias_level level) 467 enum snd_soc_bias_level level)
516{ 468{
517 u16 power1 = wm8510_read_reg_cache(codec, WM8510_POWER1) & ~0x3; 469 u16 power1 = snd_soc_read(codec, WM8510_POWER1) & ~0x3;
518 470
519 switch (level) { 471 switch (level) {
520 case SND_SOC_BIAS_ON: 472 case SND_SOC_BIAS_ON:
521 case SND_SOC_BIAS_PREPARE: 473 case SND_SOC_BIAS_PREPARE:
522 power1 |= 0x1; /* VMID 50k */ 474 power1 |= 0x1; /* VMID 50k */
523 wm8510_write(codec, WM8510_POWER1, power1); 475 snd_soc_write(codec, WM8510_POWER1, power1);
524 break; 476 break;
525 477
526 case SND_SOC_BIAS_STANDBY: 478 case SND_SOC_BIAS_STANDBY:
@@ -528,18 +480,18 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
528 480
529 if (codec->bias_level == SND_SOC_BIAS_OFF) { 481 if (codec->bias_level == SND_SOC_BIAS_OFF) {
530 /* Initial cap charge at VMID 5k */ 482 /* Initial cap charge at VMID 5k */
531 wm8510_write(codec, WM8510_POWER1, power1 | 0x3); 483 snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
532 mdelay(100); 484 mdelay(100);
533 } 485 }
534 486
535 power1 |= 0x2; /* VMID 500k */ 487 power1 |= 0x2; /* VMID 500k */
536 wm8510_write(codec, WM8510_POWER1, power1); 488 snd_soc_write(codec, WM8510_POWER1, power1);
537 break; 489 break;
538 490
539 case SND_SOC_BIAS_OFF: 491 case SND_SOC_BIAS_OFF:
540 wm8510_write(codec, WM8510_POWER1, 0); 492 snd_soc_write(codec, WM8510_POWER1, 0);
541 wm8510_write(codec, WM8510_POWER2, 0); 493 snd_soc_write(codec, WM8510_POWER2, 0);
542 wm8510_write(codec, WM8510_POWER3, 0); 494 snd_soc_write(codec, WM8510_POWER3, 0);
543 break; 495 break;
544 } 496 }
545 497
@@ -619,8 +571,6 @@ static int wm8510_init(struct snd_soc_device *socdev)
619 571
620 codec->name = "WM8510"; 572 codec->name = "WM8510";
621 codec->owner = THIS_MODULE; 573 codec->owner = THIS_MODULE;
622 codec->read = wm8510_read_reg_cache;
623 codec->write = wm8510_write;
624 codec->set_bias_level = wm8510_set_bias_level; 574 codec->set_bias_level = wm8510_set_bias_level;
625 codec->dai = &wm8510_dai; 575 codec->dai = &wm8510_dai;
626 codec->num_dai = 1; 576 codec->num_dai = 1;
@@ -630,13 +580,20 @@ static int wm8510_init(struct snd_soc_device *socdev)
630 if (codec->reg_cache == NULL) 580 if (codec->reg_cache == NULL)
631 return -ENOMEM; 581 return -ENOMEM;
632 582
583 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
584 if (ret < 0) {
585 printk(KERN_ERR "wm8510: failed to set cache I/O: %d\n",
586 ret);
587 goto err;
588 }
589
633 wm8510_reset(codec); 590 wm8510_reset(codec);
634 591
635 /* register pcms */ 592 /* register pcms */
636 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 593 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
637 if (ret < 0) { 594 if (ret < 0) {
638 printk(KERN_ERR "wm8510: failed to create pcms\n"); 595 printk(KERN_ERR "wm8510: failed to create pcms\n");
639 goto pcm_err; 596 goto err;
640 } 597 }
641 598
642 /* power on device */ 599 /* power on device */
@@ -655,7 +612,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
655card_err: 612card_err:
656 snd_soc_free_pcms(socdev); 613 snd_soc_free_pcms(socdev);
657 snd_soc_dapm_free(socdev); 614 snd_soc_dapm_free(socdev);
658pcm_err: 615err:
659 kfree(codec->reg_cache); 616 kfree(codec->reg_cache);
660 return ret; 617 return ret;
661} 618}
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index e7ff2121ede9..66da44b08d35 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -43,45 +43,6 @@ static const u16 wm8728_reg_defaults[] = {
43 0x100, 43 0x100,
44}; 44};
45 45
46static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
47 unsigned int reg)
48{
49 u16 *cache = codec->reg_cache;
50 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
51 return cache[reg];
52}
53
54static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
55 u16 reg, unsigned int value)
56{
57 u16 *cache = codec->reg_cache;
58 BUG_ON(reg >= ARRAY_SIZE(wm8728_reg_defaults));
59 cache[reg] = value;
60}
61
62/*
63 * write to the WM8728 register space
64 */
65static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
66 unsigned int value)
67{
68 u8 data[2];
69
70 /* data is
71 * D15..D9 WM8728 register offset
72 * D8...D0 register data
73 */
74 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
75 data[1] = value & 0x00ff;
76
77 wm8728_write_reg_cache(codec, reg, value);
78
79 if (codec->hw_write(codec->control_data, data, 2) == 2)
80 return 0;
81 else
82 return -EIO;
83}
84
85static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1); 46static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
86 47
87static const struct snd_kcontrol_new wm8728_snd_controls[] = { 48static const struct snd_kcontrol_new wm8728_snd_controls[] = {
@@ -121,12 +82,12 @@ static int wm8728_add_widgets(struct snd_soc_codec *codec)
121static int wm8728_mute(struct snd_soc_dai *dai, int mute) 82static int wm8728_mute(struct snd_soc_dai *dai, int mute)
122{ 83{
123 struct snd_soc_codec *codec = dai->codec; 84 struct snd_soc_codec *codec = dai->codec;
124 u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 85 u16 mute_reg = snd_soc_read(codec, WM8728_DACCTL);
125 86
126 if (mute) 87 if (mute)
127 wm8728_write(codec, WM8728_DACCTL, mute_reg | 1); 88 snd_soc_write(codec, WM8728_DACCTL, mute_reg | 1);
128 else 89 else
129 wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1); 90 snd_soc_write(codec, WM8728_DACCTL, mute_reg & ~1);
130 91
131 return 0; 92 return 0;
132} 93}
@@ -138,7 +99,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
138 struct snd_soc_pcm_runtime *rtd = substream->private_data; 99 struct snd_soc_pcm_runtime *rtd = substream->private_data;
139 struct snd_soc_device *socdev = rtd->socdev; 100 struct snd_soc_device *socdev = rtd->socdev;
140 struct snd_soc_codec *codec = socdev->card->codec; 101 struct snd_soc_codec *codec = socdev->card->codec;
141 u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL); 102 u16 dac = snd_soc_read(codec, WM8728_DACCTL);
142 103
143 dac &= ~0x18; 104 dac &= ~0x18;
144 105
@@ -155,7 +116,7 @@ static int wm8728_hw_params(struct snd_pcm_substream *substream,
155 return -EINVAL; 116 return -EINVAL;
156 } 117 }
157 118
158 wm8728_write(codec, WM8728_DACCTL, dac); 119 snd_soc_write(codec, WM8728_DACCTL, dac);
159 120
160 return 0; 121 return 0;
161} 122}
@@ -164,7 +125,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
164 unsigned int fmt) 125 unsigned int fmt)
165{ 126{
166 struct snd_soc_codec *codec = codec_dai->codec; 127 struct snd_soc_codec *codec = codec_dai->codec;
167 u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL); 128 u16 iface = snd_soc_read(codec, WM8728_IFCTL);
168 129
169 /* Currently only I2S is supported by the driver, though the 130 /* Currently only I2S is supported by the driver, though the
170 * hardware is more flexible. 131 * hardware is more flexible.
@@ -204,7 +165,7 @@ static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
204 return -EINVAL; 165 return -EINVAL;
205 } 166 }
206 167
207 wm8728_write(codec, WM8728_IFCTL, iface); 168 snd_soc_write(codec, WM8728_IFCTL, iface);
208 return 0; 169 return 0;
209} 170}
210 171
@@ -220,19 +181,19 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
220 case SND_SOC_BIAS_STANDBY: 181 case SND_SOC_BIAS_STANDBY:
221 if (codec->bias_level == SND_SOC_BIAS_OFF) { 182 if (codec->bias_level == SND_SOC_BIAS_OFF) {
222 /* Power everything up... */ 183 /* Power everything up... */
223 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 184 reg = snd_soc_read(codec, WM8728_DACCTL);
224 wm8728_write(codec, WM8728_DACCTL, reg & ~0x4); 185 snd_soc_write(codec, WM8728_DACCTL, reg & ~0x4);
225 186
226 /* ..then sync in the register cache. */ 187 /* ..then sync in the register cache. */
227 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++) 188 for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
228 wm8728_write(codec, i, 189 snd_soc_write(codec, i,
229 wm8728_read_reg_cache(codec, i)); 190 snd_soc_read(codec, i));
230 } 191 }
231 break; 192 break;
232 193
233 case SND_SOC_BIAS_OFF: 194 case SND_SOC_BIAS_OFF:
234 reg = wm8728_read_reg_cache(codec, WM8728_DACCTL); 195 reg = snd_soc_read(codec, WM8728_DACCTL);
235 wm8728_write(codec, WM8728_DACCTL, reg | 0x4); 196 snd_soc_write(codec, WM8728_DACCTL, reg | 0x4);
236 break; 197 break;
237 } 198 }
238 codec->bias_level = level; 199 codec->bias_level = level;
@@ -294,8 +255,6 @@ static int wm8728_init(struct snd_soc_device *socdev)
294 255
295 codec->name = "WM8728"; 256 codec->name = "WM8728";
296 codec->owner = THIS_MODULE; 257 codec->owner = THIS_MODULE;
297 codec->read = wm8728_read_reg_cache;
298 codec->write = wm8728_write;
299 codec->set_bias_level = wm8728_set_bias_level; 258 codec->set_bias_level = wm8728_set_bias_level;
300 codec->dai = &wm8728_dai; 259 codec->dai = &wm8728_dai;
301 codec->num_dai = 1; 260 codec->num_dai = 1;
@@ -307,11 +266,18 @@ static int wm8728_init(struct snd_soc_device *socdev)
307 if (codec->reg_cache == NULL) 266 if (codec->reg_cache == NULL)
308 return -ENOMEM; 267 return -ENOMEM;
309 268
269 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
270 if (ret < 0) {
271 printk(KERN_ERR "wm8728: failed to configure cache I/O: %d\n",
272 ret);
273 goto err;
274 }
275
310 /* register pcms */ 276 /* register pcms */
311 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 277 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
312 if (ret < 0) { 278 if (ret < 0) {
313 printk(KERN_ERR "wm8728: failed to create pcms\n"); 279 printk(KERN_ERR "wm8728: failed to create pcms\n");
314 goto pcm_err; 280 goto err;
315 } 281 }
316 282
317 /* power on device */ 283 /* power on device */
@@ -331,7 +297,7 @@ static int wm8728_init(struct snd_soc_device *socdev)
331card_err: 297card_err:
332 snd_soc_free_pcms(socdev); 298 snd_soc_free_pcms(socdev);
333 snd_soc_dapm_free(socdev); 299 snd_soc_dapm_free(socdev);
334pcm_err: 300err:
335 kfree(codec->reg_cache); 301 kfree(codec->reg_cache);
336 return ret; 302 return ret;
337} 303}
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
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index b64509b01a49..ed09043181e1 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -55,50 +55,7 @@ static const u16 wm8750_reg[] = {
55 0x0079, 0x0079, 0x0079, /* 40 */ 55 0x0079, 0x0079, 0x0079, /* 40 */
56}; 56};
57 57
58/* 58#define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0)
59 * read wm8750 register cache
60 */
61static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
62 unsigned int reg)
63{
64 u16 *cache = codec->reg_cache;
65 if (reg > WM8750_CACHE_REGNUM)
66 return -1;
67 return cache[reg];
68}
69
70/*
71 * write wm8750 register cache
72 */
73static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
74 unsigned int reg, unsigned int value)
75{
76 u16 *cache = codec->reg_cache;
77 if (reg > WM8750_CACHE_REGNUM)
78 return;
79 cache[reg] = value;
80}
81
82static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
83 unsigned int value)
84{
85 u8 data[2];
86
87 /* data is
88 * D15..D9 WM8753 register offset
89 * D8...D0 register data
90 */
91 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
92 data[1] = value & 0x00ff;
93
94 wm8750_write_reg_cache(codec, reg, value);
95 if (codec->hw_write(codec->control_data, data, 2) == 2)
96 return 0;
97 else
98 return -EIO;
99}
100
101#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
102 59
103/* 60/*
104 * WM8750 Controls 61 * WM8750 Controls
@@ -594,7 +551,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
594 return -EINVAL; 551 return -EINVAL;
595 } 552 }
596 553
597 wm8750_write(codec, WM8750_IFACE, iface); 554 snd_soc_write(codec, WM8750_IFACE, iface);
598 return 0; 555 return 0;
599} 556}
600 557
@@ -606,8 +563,8 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
606 struct snd_soc_device *socdev = rtd->socdev; 563 struct snd_soc_device *socdev = rtd->socdev;
607 struct snd_soc_codec *codec = socdev->card->codec; 564 struct snd_soc_codec *codec = socdev->card->codec;
608 struct wm8750_priv *wm8750 = codec->private_data; 565 struct wm8750_priv *wm8750 = codec->private_data;
609 u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3; 566 u16 iface = snd_soc_read(codec, WM8750_IFACE) & 0x1f3;
610 u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0; 567 u16 srate = snd_soc_read(codec, WM8750_SRATE) & 0x1c0;
611 int coeff = get_coeff(wm8750->sysclk, params_rate(params)); 568 int coeff = get_coeff(wm8750->sysclk, params_rate(params));
612 569
613 /* bit size */ 570 /* bit size */
@@ -626,9 +583,9 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
626 } 583 }
627 584
628 /* set iface & srate */ 585 /* set iface & srate */
629 wm8750_write(codec, WM8750_IFACE, iface); 586 snd_soc_write(codec, WM8750_IFACE, iface);
630 if (coeff >= 0) 587 if (coeff >= 0)
631 wm8750_write(codec, WM8750_SRATE, srate | 588 snd_soc_write(codec, WM8750_SRATE, srate |
632 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 589 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
633 590
634 return 0; 591 return 0;
@@ -637,35 +594,35 @@ static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
637static int wm8750_mute(struct snd_soc_dai *dai, int mute) 594static int wm8750_mute(struct snd_soc_dai *dai, int mute)
638{ 595{
639 struct snd_soc_codec *codec = dai->codec; 596 struct snd_soc_codec *codec = dai->codec;
640 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7; 597 u16 mute_reg = snd_soc_read(codec, WM8750_ADCDAC) & 0xfff7;
641 598
642 if (mute) 599 if (mute)
643 wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8); 600 snd_soc_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
644 else 601 else
645 wm8750_write(codec, WM8750_ADCDAC, mute_reg); 602 snd_soc_write(codec, WM8750_ADCDAC, mute_reg);
646 return 0; 603 return 0;
647} 604}
648 605
649static int wm8750_set_bias_level(struct snd_soc_codec *codec, 606static int wm8750_set_bias_level(struct snd_soc_codec *codec,
650 enum snd_soc_bias_level level) 607 enum snd_soc_bias_level level)
651{ 608{
652 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e; 609 u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e;
653 610
654 switch (level) { 611 switch (level) {
655 case SND_SOC_BIAS_ON: 612 case SND_SOC_BIAS_ON:
656 /* set vmid to 50k and unmute dac */ 613 /* set vmid to 50k and unmute dac */
657 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); 614 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
658 break; 615 break;
659 case SND_SOC_BIAS_PREPARE: 616 case SND_SOC_BIAS_PREPARE:
660 /* set vmid to 5k for quick power up */ 617 /* set vmid to 5k for quick power up */
661 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); 618 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
662 break; 619 break;
663 case SND_SOC_BIAS_STANDBY: 620 case SND_SOC_BIAS_STANDBY:
664 /* mute dac and set vmid to 500k, enable VREF */ 621 /* mute dac and set vmid to 500k, enable VREF */
665 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141); 622 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
666 break; 623 break;
667 case SND_SOC_BIAS_OFF: 624 case SND_SOC_BIAS_OFF:
668 wm8750_write(codec, WM8750_PWR1, 0x0001); 625 snd_soc_write(codec, WM8750_PWR1, 0x0001);
669 break; 626 break;
670 } 627 }
671 codec->bias_level = level; 628 codec->bias_level = level;
@@ -761,8 +718,6 @@ static int wm8750_init(struct snd_soc_device *socdev)
761 718
762 codec->name = "WM8750"; 719 codec->name = "WM8750";
763 codec->owner = THIS_MODULE; 720 codec->owner = THIS_MODULE;
764 codec->read = wm8750_read_reg_cache;
765 codec->write = wm8750_write;
766 codec->set_bias_level = wm8750_set_bias_level; 721 codec->set_bias_level = wm8750_set_bias_level;
767 codec->dai = &wm8750_dai; 722 codec->dai = &wm8750_dai;
768 codec->num_dai = 1; 723 codec->num_dai = 1;
@@ -771,13 +726,23 @@ static int wm8750_init(struct snd_soc_device *socdev)
771 if (codec->reg_cache == NULL) 726 if (codec->reg_cache == NULL)
772 return -ENOMEM; 727 return -ENOMEM;
773 728
774 wm8750_reset(codec); 729 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
730 if (ret < 0) {
731 printk(KERN_ERR "wm8750: failed to set cache I/O: %d\n", ret);
732 goto err;
733 }
734
735 ret = wm8750_reset(codec);
736 if (ret < 0) {
737 printk(KERN_ERR "wm8750: failed to reset: %d\n", ret);
738 goto err;
739 }
775 740
776 /* register pcms */ 741 /* register pcms */
777 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 742 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
778 if (ret < 0) { 743 if (ret < 0) {
779 printk(KERN_ERR "wm8750: failed to create pcms\n"); 744 printk(KERN_ERR "wm8750: failed to create pcms\n");
780 goto pcm_err; 745 goto err;
781 } 746 }
782 747
783 /* charge output caps */ 748 /* charge output caps */
@@ -786,22 +751,22 @@ static int wm8750_init(struct snd_soc_device *socdev)
786 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000)); 751 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
787 752
788 /* set the update bits */ 753 /* set the update bits */
789 reg = wm8750_read_reg_cache(codec, WM8750_LDAC); 754 reg = snd_soc_read(codec, WM8750_LDAC);
790 wm8750_write(codec, WM8750_LDAC, reg | 0x0100); 755 snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
791 reg = wm8750_read_reg_cache(codec, WM8750_RDAC); 756 reg = snd_soc_read(codec, WM8750_RDAC);
792 wm8750_write(codec, WM8750_RDAC, reg | 0x0100); 757 snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
793 reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V); 758 reg = snd_soc_read(codec, WM8750_LOUT1V);
794 wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100); 759 snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
795 reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V); 760 reg = snd_soc_read(codec, WM8750_ROUT1V);
796 wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100); 761 snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
797 reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V); 762 reg = snd_soc_read(codec, WM8750_LOUT2V);
798 wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100); 763 snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
799 reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V); 764 reg = snd_soc_read(codec, WM8750_ROUT2V);
800 wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100); 765 snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
801 reg = wm8750_read_reg_cache(codec, WM8750_LINVOL); 766 reg = snd_soc_read(codec, WM8750_LINVOL);
802 wm8750_write(codec, WM8750_LINVOL, reg | 0x0100); 767 snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
803 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL); 768 reg = snd_soc_read(codec, WM8750_RINVOL);
804 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100); 769 snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
805 770
806 snd_soc_add_controls(codec, wm8750_snd_controls, 771 snd_soc_add_controls(codec, wm8750_snd_controls,
807 ARRAY_SIZE(wm8750_snd_controls)); 772 ARRAY_SIZE(wm8750_snd_controls));
@@ -816,7 +781,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
816card_err: 781card_err:
817 snd_soc_free_pcms(socdev); 782 snd_soc_free_pcms(socdev);
818 snd_soc_dapm_free(socdev); 783 snd_soc_dapm_free(socdev);
819pcm_err: 784err:
820 kfree(codec->reg_cache); 785 kfree(codec->reg_cache);
821 return ret; 786 return ret;
822} 787}
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index d1769e6c0c44..c529ffcfe5d8 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -69,61 +69,7 @@ struct wm8960_priv {
69 struct snd_soc_codec codec; 69 struct snd_soc_codec codec;
70}; 70};
71 71
72/* 72#define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0)
73 * read wm8960 register cache
74 */
75static inline unsigned int wm8960_read_reg_cache(struct snd_soc_codec *codec,
76 unsigned int reg)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg == WM8960_RESET)
80 return 0;
81 if (reg >= WM8960_CACHEREGNUM)
82 return -1;
83 return cache[reg];
84}
85
86/*
87 * write wm8960 register cache
88 */
89static inline void wm8960_write_reg_cache(struct snd_soc_codec *codec,
90 u16 reg, unsigned int value)
91{
92 u16 *cache = codec->reg_cache;
93 if (reg >= WM8960_CACHEREGNUM)
94 return;
95 cache[reg] = value;
96}
97
98static inline unsigned int wm8960_read(struct snd_soc_codec *codec,
99 unsigned int reg)
100{
101 return wm8960_read_reg_cache(codec, reg);
102}
103
104/*
105 * write to the WM8960 register space
106 */
107static int wm8960_write(struct snd_soc_codec *codec, unsigned int reg,
108 unsigned int value)
109{
110 u8 data[2];
111
112 /* data is
113 * D15..D9 WM8960 register offset
114 * D8...D0 register data
115 */
116 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
117 data[1] = value & 0x00ff;
118
119 wm8960_write_reg_cache(codec, reg, value);
120 if (codec->hw_write(codec->control_data, data, 2) == 2)
121 return 0;
122 else
123 return -EIO;
124}
125
126#define wm8960_reset(c) wm8960_write(c, WM8960_RESET, 0)
127 73
128/* enumerated controls */ 74/* enumerated controls */
129static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"}; 75static const char *wm8960_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -420,7 +366,7 @@ static int wm8960_set_dai_fmt(struct snd_soc_dai *codec_dai,
420 } 366 }
421 367
422 /* set iface */ 368 /* set iface */
423 wm8960_write(codec, WM8960_IFACE1, iface); 369 snd_soc_write(codec, WM8960_IFACE1, iface);
424 return 0; 370 return 0;
425} 371}
426 372
@@ -431,7 +377,7 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
431 struct snd_soc_pcm_runtime *rtd = substream->private_data; 377 struct snd_soc_pcm_runtime *rtd = substream->private_data;
432 struct snd_soc_device *socdev = rtd->socdev; 378 struct snd_soc_device *socdev = rtd->socdev;
433 struct snd_soc_codec *codec = socdev->card->codec; 379 struct snd_soc_codec *codec = socdev->card->codec;
434 u16 iface = wm8960_read(codec, WM8960_IFACE1) & 0xfff3; 380 u16 iface = snd_soc_read(codec, WM8960_IFACE1) & 0xfff3;
435 381
436 /* bit size */ 382 /* bit size */
437 switch (params_format(params)) { 383 switch (params_format(params)) {
@@ -446,19 +392,19 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
446 } 392 }
447 393
448 /* set iface */ 394 /* set iface */
449 wm8960_write(codec, WM8960_IFACE1, iface); 395 snd_soc_write(codec, WM8960_IFACE1, iface);
450 return 0; 396 return 0;
451} 397}
452 398
453static int wm8960_mute(struct snd_soc_dai *dai, int mute) 399static int wm8960_mute(struct snd_soc_dai *dai, int mute)
454{ 400{
455 struct snd_soc_codec *codec = dai->codec; 401 struct snd_soc_codec *codec = dai->codec;
456 u16 mute_reg = wm8960_read(codec, WM8960_DACCTL1) & 0xfff7; 402 u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
457 403
458 if (mute) 404 if (mute)
459 wm8960_write(codec, WM8960_DACCTL1, mute_reg | 0x8); 405 snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
460 else 406 else
461 wm8960_write(codec, WM8960_DACCTL1, mute_reg); 407 snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
462 return 0; 408 return 0;
463} 409}
464 410
@@ -474,16 +420,16 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
474 420
475 case SND_SOC_BIAS_PREPARE: 421 case SND_SOC_BIAS_PREPARE:
476 /* Set VMID to 2x50k */ 422 /* Set VMID to 2x50k */
477 reg = wm8960_read(codec, WM8960_POWER1); 423 reg = snd_soc_read(codec, WM8960_POWER1);
478 reg &= ~0x180; 424 reg &= ~0x180;
479 reg |= 0x80; 425 reg |= 0x80;
480 wm8960_write(codec, WM8960_POWER1, reg); 426 snd_soc_write(codec, WM8960_POWER1, reg);
481 break; 427 break;
482 428
483 case SND_SOC_BIAS_STANDBY: 429 case SND_SOC_BIAS_STANDBY:
484 if (codec->bias_level == SND_SOC_BIAS_OFF) { 430 if (codec->bias_level == SND_SOC_BIAS_OFF) {
485 /* Enable anti-pop features */ 431 /* Enable anti-pop features */
486 wm8960_write(codec, WM8960_APOP1, 432 snd_soc_write(codec, WM8960_APOP1,
487 WM8960_POBCTRL | WM8960_SOFT_ST | 433 WM8960_POBCTRL | WM8960_SOFT_ST |
488 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 434 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
489 435
@@ -491,43 +437,43 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
491 reg = WM8960_DISOP; 437 reg = WM8960_DISOP;
492 if (pdata) 438 if (pdata)
493 reg |= pdata->dres << 4; 439 reg |= pdata->dres << 4;
494 wm8960_write(codec, WM8960_APOP2, reg); 440 snd_soc_write(codec, WM8960_APOP2, reg);
495 441
496 msleep(400); 442 msleep(400);
497 443
498 wm8960_write(codec, WM8960_APOP2, 0); 444 snd_soc_write(codec, WM8960_APOP2, 0);
499 445
500 /* Enable & ramp VMID at 2x50k */ 446 /* Enable & ramp VMID at 2x50k */
501 reg = wm8960_read(codec, WM8960_POWER1); 447 reg = snd_soc_read(codec, WM8960_POWER1);
502 reg |= 0x80; 448 reg |= 0x80;
503 wm8960_write(codec, WM8960_POWER1, reg); 449 snd_soc_write(codec, WM8960_POWER1, reg);
504 msleep(100); 450 msleep(100);
505 451
506 /* Enable VREF */ 452 /* Enable VREF */
507 wm8960_write(codec, WM8960_POWER1, reg | WM8960_VREF); 453 snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
508 454
509 /* Disable anti-pop features */ 455 /* Disable anti-pop features */
510 wm8960_write(codec, WM8960_APOP1, WM8960_BUFIOEN); 456 snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
511 } 457 }
512 458
513 /* Set VMID to 2x250k */ 459 /* Set VMID to 2x250k */
514 reg = wm8960_read(codec, WM8960_POWER1); 460 reg = snd_soc_read(codec, WM8960_POWER1);
515 reg &= ~0x180; 461 reg &= ~0x180;
516 reg |= 0x100; 462 reg |= 0x100;
517 wm8960_write(codec, WM8960_POWER1, reg); 463 snd_soc_write(codec, WM8960_POWER1, reg);
518 break; 464 break;
519 465
520 case SND_SOC_BIAS_OFF: 466 case SND_SOC_BIAS_OFF:
521 /* Enable anti-pop features */ 467 /* Enable anti-pop features */
522 wm8960_write(codec, WM8960_APOP1, 468 snd_soc_write(codec, WM8960_APOP1,
523 WM8960_POBCTRL | WM8960_SOFT_ST | 469 WM8960_POBCTRL | WM8960_SOFT_ST |
524 WM8960_BUFDCOPEN | WM8960_BUFIOEN); 470 WM8960_BUFDCOPEN | WM8960_BUFIOEN);
525 471
526 /* Disable VMID and VREF, let them discharge */ 472 /* Disable VMID and VREF, let them discharge */
527 wm8960_write(codec, WM8960_POWER1, 0); 473 snd_soc_write(codec, WM8960_POWER1, 0);
528 msleep(600); 474 msleep(600);
529 475
530 wm8960_write(codec, WM8960_APOP1, 0); 476 snd_soc_write(codec, WM8960_APOP1, 0);
531 break; 477 break;
532 } 478 }
533 479
@@ -610,33 +556,33 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai,
610 556
611 /* Disable the PLL: even if we are changing the frequency the 557 /* Disable the PLL: even if we are changing the frequency the
612 * PLL needs to be disabled while we do so. */ 558 * PLL needs to be disabled while we do so. */
613 wm8960_write(codec, WM8960_CLOCK1, 559 snd_soc_write(codec, WM8960_CLOCK1,
614 wm8960_read(codec, WM8960_CLOCK1) & ~1); 560 snd_soc_read(codec, WM8960_CLOCK1) & ~1);
615 wm8960_write(codec, WM8960_POWER2, 561 snd_soc_write(codec, WM8960_POWER2,
616 wm8960_read(codec, WM8960_POWER2) & ~1); 562 snd_soc_read(codec, WM8960_POWER2) & ~1);
617 563
618 if (!freq_in || !freq_out) 564 if (!freq_in || !freq_out)
619 return 0; 565 return 0;
620 566
621 reg = wm8960_read(codec, WM8960_PLL1) & ~0x3f; 567 reg = snd_soc_read(codec, WM8960_PLL1) & ~0x3f;
622 reg |= pll_div.pre_div << 4; 568 reg |= pll_div.pre_div << 4;
623 reg |= pll_div.n; 569 reg |= pll_div.n;
624 570
625 if (pll_div.k) { 571 if (pll_div.k) {
626 reg |= 0x20; 572 reg |= 0x20;
627 573
628 wm8960_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f); 574 snd_soc_write(codec, WM8960_PLL2, (pll_div.k >> 18) & 0x3f);
629 wm8960_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff); 575 snd_soc_write(codec, WM8960_PLL3, (pll_div.k >> 9) & 0x1ff);
630 wm8960_write(codec, WM8960_PLL4, pll_div.k & 0x1ff); 576 snd_soc_write(codec, WM8960_PLL4, pll_div.k & 0x1ff);
631 } 577 }
632 wm8960_write(codec, WM8960_PLL1, reg); 578 snd_soc_write(codec, WM8960_PLL1, reg);
633 579
634 /* Turn it on */ 580 /* Turn it on */
635 wm8960_write(codec, WM8960_POWER2, 581 snd_soc_write(codec, WM8960_POWER2,
636 wm8960_read(codec, WM8960_POWER2) | 1); 582 snd_soc_read(codec, WM8960_POWER2) | 1);
637 msleep(250); 583 msleep(250);
638 wm8960_write(codec, WM8960_CLOCK1, 584 snd_soc_write(codec, WM8960_CLOCK1,
639 wm8960_read(codec, WM8960_CLOCK1) | 1); 585 snd_soc_read(codec, WM8960_CLOCK1) | 1);
640 586
641 return 0; 587 return 0;
642} 588}
@@ -649,28 +595,28 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
649 595
650 switch (div_id) { 596 switch (div_id) {
651 case WM8960_SYSCLKSEL: 597 case WM8960_SYSCLKSEL:
652 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1fe; 598 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe;
653 wm8960_write(codec, WM8960_CLOCK1, reg | div); 599 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
654 break; 600 break;
655 case WM8960_SYSCLKDIV: 601 case WM8960_SYSCLKDIV:
656 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1f9; 602 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9;
657 wm8960_write(codec, WM8960_CLOCK1, reg | div); 603 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
658 break; 604 break;
659 case WM8960_DACDIV: 605 case WM8960_DACDIV:
660 reg = wm8960_read(codec, WM8960_CLOCK1) & 0x1c7; 606 reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1c7;
661 wm8960_write(codec, WM8960_CLOCK1, reg | div); 607 snd_soc_write(codec, WM8960_CLOCK1, reg | div);
662 break; 608 break;
663 case WM8960_OPCLKDIV: 609 case WM8960_OPCLKDIV:
664 reg = wm8960_read(codec, WM8960_PLL1) & 0x03f; 610 reg = snd_soc_read(codec, WM8960_PLL1) & 0x03f;
665 wm8960_write(codec, WM8960_PLL1, reg | div); 611 snd_soc_write(codec, WM8960_PLL1, reg | div);
666 break; 612 break;
667 case WM8960_DCLKDIV: 613 case WM8960_DCLKDIV:
668 reg = wm8960_read(codec, WM8960_CLOCK2) & 0x03f; 614 reg = snd_soc_read(codec, WM8960_CLOCK2) & 0x03f;
669 wm8960_write(codec, WM8960_CLOCK2, reg | div); 615 snd_soc_write(codec, WM8960_CLOCK2, reg | div);
670 break; 616 break;
671 case WM8960_TOCLKSEL: 617 case WM8960_TOCLKSEL:
672 reg = wm8960_read(codec, WM8960_ADDCTL1) & 0x1fd; 618 reg = snd_soc_read(codec, WM8960_ADDCTL1) & 0x1fd;
673 wm8960_write(codec, WM8960_ADDCTL1, reg | div); 619 snd_soc_write(codec, WM8960_ADDCTL1, reg | div);
674 break; 620 break;
675 default: 621 default:
676 return -EINVAL; 622 return -EINVAL;
@@ -830,8 +776,6 @@ static int wm8960_register(struct wm8960_priv *wm8960)
830 codec->private_data = wm8960; 776 codec->private_data = wm8960;
831 codec->name = "WM8960"; 777 codec->name = "WM8960";
832 codec->owner = THIS_MODULE; 778 codec->owner = THIS_MODULE;
833 codec->read = wm8960_read_reg_cache;
834 codec->write = wm8960_write;
835 codec->bias_level = SND_SOC_BIAS_OFF; 779 codec->bias_level = SND_SOC_BIAS_OFF;
836 codec->set_bias_level = wm8960_set_bias_level; 780 codec->set_bias_level = wm8960_set_bias_level;
837 codec->dai = &wm8960_dai; 781 codec->dai = &wm8960_dai;
@@ -841,6 +785,12 @@ static int wm8960_register(struct wm8960_priv *wm8960)
841 785
842 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg)); 786 memcpy(codec->reg_cache, wm8960_reg, sizeof(wm8960_reg));
843 787
788 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
789 if (ret < 0) {
790 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
791 goto err;
792 }
793
844 ret = wm8960_reset(codec); 794 ret = wm8960_reset(codec);
845 if (ret < 0) { 795 if (ret < 0) {
846 dev_err(codec->dev, "Failed to issue reset\n"); 796 dev_err(codec->dev, "Failed to issue reset\n");
@@ -852,26 +802,26 @@ static int wm8960_register(struct wm8960_priv *wm8960)
852 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); 802 wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
853 803
854 /* Latch the update bits */ 804 /* Latch the update bits */
855 reg = wm8960_read(codec, WM8960_LINVOL); 805 reg = snd_soc_read(codec, WM8960_LINVOL);
856 wm8960_write(codec, WM8960_LINVOL, reg | 0x100); 806 snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
857 reg = wm8960_read(codec, WM8960_RINVOL); 807 reg = snd_soc_read(codec, WM8960_RINVOL);
858 wm8960_write(codec, WM8960_RINVOL, reg | 0x100); 808 snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
859 reg = wm8960_read(codec, WM8960_LADC); 809 reg = snd_soc_read(codec, WM8960_LADC);
860 wm8960_write(codec, WM8960_LADC, reg | 0x100); 810 snd_soc_write(codec, WM8960_LADC, reg | 0x100);
861 reg = wm8960_read(codec, WM8960_RADC); 811 reg = snd_soc_read(codec, WM8960_RADC);
862 wm8960_write(codec, WM8960_RADC, reg | 0x100); 812 snd_soc_write(codec, WM8960_RADC, reg | 0x100);
863 reg = wm8960_read(codec, WM8960_LDAC); 813 reg = snd_soc_read(codec, WM8960_LDAC);
864 wm8960_write(codec, WM8960_LDAC, reg | 0x100); 814 snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
865 reg = wm8960_read(codec, WM8960_RDAC); 815 reg = snd_soc_read(codec, WM8960_RDAC);
866 wm8960_write(codec, WM8960_RDAC, reg | 0x100); 816 snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
867 reg = wm8960_read(codec, WM8960_LOUT1); 817 reg = snd_soc_read(codec, WM8960_LOUT1);
868 wm8960_write(codec, WM8960_LOUT1, reg | 0x100); 818 snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
869 reg = wm8960_read(codec, WM8960_ROUT1); 819 reg = snd_soc_read(codec, WM8960_ROUT1);
870 wm8960_write(codec, WM8960_ROUT1, reg | 0x100); 820 snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
871 reg = wm8960_read(codec, WM8960_LOUT2); 821 reg = snd_soc_read(codec, WM8960_LOUT2);
872 wm8960_write(codec, WM8960_LOUT2, reg | 0x100); 822 snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
873 reg = wm8960_read(codec, WM8960_ROUT2); 823 reg = snd_soc_read(codec, WM8960_ROUT2);
874 wm8960_write(codec, WM8960_ROUT2, reg | 0x100); 824 snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
875 825
876 wm8960_codec = codec; 826 wm8960_codec = codec;
877 827
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 032dca22dbd3..53f3bc90ea0c 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -59,44 +59,7 @@ static const u16 wm8971_reg[] = {
59 0x0079, 0x0079, 0x0079, /* 40 */ 59 0x0079, 0x0079, 0x0079, /* 40 */
60}; 60};
61 61
62static inline unsigned int wm8971_read_reg_cache(struct snd_soc_codec *codec, 62#define wm8971_reset(c) snd_soc_write(c, WM8971_RESET, 0)
63 unsigned int reg)
64{
65 u16 *cache = codec->reg_cache;
66 if (reg < WM8971_REG_COUNT)
67 return cache[reg];
68
69 return -1;
70}
71
72static inline void wm8971_write_reg_cache(struct snd_soc_codec *codec,
73 unsigned int reg, unsigned int value)
74{
75 u16 *cache = codec->reg_cache;
76 if (reg < WM8971_REG_COUNT)
77 cache[reg] = value;
78}
79
80static int wm8971_write(struct snd_soc_codec *codec, unsigned int reg,
81 unsigned int value)
82{
83 u8 data[2];
84
85 /* data is
86 * D15..D9 WM8753 register offset
87 * D8...D0 register data
88 */
89 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
90 data[1] = value & 0x00ff;
91
92 wm8971_write_reg_cache (codec, reg, value);
93 if (codec->hw_write(codec->control_data, data, 2) == 2)
94 return 0;
95 else
96 return -EIO;
97}
98
99#define wm8971_reset(c) wm8971_write(c, WM8971_RESET, 0)
100 63
101/* WM8971 Controls */ 64/* WM8971 Controls */
102static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" }; 65static const char *wm8971_bass[] = { "Linear Control", "Adaptive Boost" };
@@ -521,7 +484,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
521 return -EINVAL; 484 return -EINVAL;
522 } 485 }
523 486
524 wm8971_write(codec, WM8971_IFACE, iface); 487 snd_soc_write(codec, WM8971_IFACE, iface);
525 return 0; 488 return 0;
526} 489}
527 490
@@ -533,8 +496,8 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
533 struct snd_soc_device *socdev = rtd->socdev; 496 struct snd_soc_device *socdev = rtd->socdev;
534 struct snd_soc_codec *codec = socdev->card->codec; 497 struct snd_soc_codec *codec = socdev->card->codec;
535 struct wm8971_priv *wm8971 = codec->private_data; 498 struct wm8971_priv *wm8971 = codec->private_data;
536 u16 iface = wm8971_read_reg_cache(codec, WM8971_IFACE) & 0x1f3; 499 u16 iface = snd_soc_read(codec, WM8971_IFACE) & 0x1f3;
537 u16 srate = wm8971_read_reg_cache(codec, WM8971_SRATE) & 0x1c0; 500 u16 srate = snd_soc_read(codec, WM8971_SRATE) & 0x1c0;
538 int coeff = get_coeff(wm8971->sysclk, params_rate(params)); 501 int coeff = get_coeff(wm8971->sysclk, params_rate(params));
539 502
540 /* bit size */ 503 /* bit size */
@@ -553,9 +516,9 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
553 } 516 }
554 517
555 /* set iface & srate */ 518 /* set iface & srate */
556 wm8971_write(codec, WM8971_IFACE, iface); 519 snd_soc_write(codec, WM8971_IFACE, iface);
557 if (coeff >= 0) 520 if (coeff >= 0)
558 wm8971_write(codec, WM8971_SRATE, srate | 521 snd_soc_write(codec, WM8971_SRATE, srate |
559 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 522 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
560 523
561 return 0; 524 return 0;
@@ -564,33 +527,33 @@ static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
564static int wm8971_mute(struct snd_soc_dai *dai, int mute) 527static int wm8971_mute(struct snd_soc_dai *dai, int mute)
565{ 528{
566 struct snd_soc_codec *codec = dai->codec; 529 struct snd_soc_codec *codec = dai->codec;
567 u16 mute_reg = wm8971_read_reg_cache(codec, WM8971_ADCDAC) & 0xfff7; 530 u16 mute_reg = snd_soc_read(codec, WM8971_ADCDAC) & 0xfff7;
568 531
569 if (mute) 532 if (mute)
570 wm8971_write(codec, WM8971_ADCDAC, mute_reg | 0x8); 533 snd_soc_write(codec, WM8971_ADCDAC, mute_reg | 0x8);
571 else 534 else
572 wm8971_write(codec, WM8971_ADCDAC, mute_reg); 535 snd_soc_write(codec, WM8971_ADCDAC, mute_reg);
573 return 0; 536 return 0;
574} 537}
575 538
576static int wm8971_set_bias_level(struct snd_soc_codec *codec, 539static int wm8971_set_bias_level(struct snd_soc_codec *codec,
577 enum snd_soc_bias_level level) 540 enum snd_soc_bias_level level)
578{ 541{
579 u16 pwr_reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 542 u16 pwr_reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
580 543
581 switch (level) { 544 switch (level) {
582 case SND_SOC_BIAS_ON: 545 case SND_SOC_BIAS_ON:
583 /* set vmid to 50k and unmute dac */ 546 /* set vmid to 50k and unmute dac */
584 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x00c1); 547 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x00c1);
585 break; 548 break;
586 case SND_SOC_BIAS_PREPARE: 549 case SND_SOC_BIAS_PREPARE:
587 break; 550 break;
588 case SND_SOC_BIAS_STANDBY: 551 case SND_SOC_BIAS_STANDBY:
589 /* mute dac and set vmid to 500k, enable VREF */ 552 /* mute dac and set vmid to 500k, enable VREF */
590 wm8971_write(codec, WM8971_PWR1, pwr_reg | 0x0140); 553 snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
591 break; 554 break;
592 case SND_SOC_BIAS_OFF: 555 case SND_SOC_BIAS_OFF:
593 wm8971_write(codec, WM8971_PWR1, 0x0001); 556 snd_soc_write(codec, WM8971_PWR1, 0x0001);
594 break; 557 break;
595 } 558 }
596 codec->bias_level = level; 559 codec->bias_level = level;
@@ -667,8 +630,8 @@ static int wm8971_resume(struct platform_device *pdev)
667 630
668 /* charge wm8971 caps */ 631 /* charge wm8971 caps */
669 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) { 632 if (codec->suspend_bias_level == SND_SOC_BIAS_ON) {
670 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 633 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
671 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 634 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
672 codec->bias_level = SND_SOC_BIAS_ON; 635 codec->bias_level = SND_SOC_BIAS_ON;
673 queue_delayed_work(wm8971_workq, &codec->delayed_work, 636 queue_delayed_work(wm8971_workq, &codec->delayed_work,
674 msecs_to_jiffies(1000)); 637 msecs_to_jiffies(1000));
@@ -684,8 +647,6 @@ static int wm8971_init(struct snd_soc_device *socdev)
684 647
685 codec->name = "WM8971"; 648 codec->name = "WM8971";
686 codec->owner = THIS_MODULE; 649 codec->owner = THIS_MODULE;
687 codec->read = wm8971_read_reg_cache;
688 codec->write = wm8971_write;
689 codec->set_bias_level = wm8971_set_bias_level; 650 codec->set_bias_level = wm8971_set_bias_level;
690 codec->dai = &wm8971_dai; 651 codec->dai = &wm8971_dai;
691 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg); 652 codec->reg_cache_size = ARRAY_SIZE(wm8971_reg);
@@ -695,42 +656,48 @@ static int wm8971_init(struct snd_soc_device *socdev)
695 if (codec->reg_cache == NULL) 656 if (codec->reg_cache == NULL)
696 return -ENOMEM; 657 return -ENOMEM;
697 658
659 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
660 if (ret < 0) {
661 printk(KERN_ERR "wm8971: failed to set cache I/O: %d\n", ret);
662 goto err;
663 }
664
698 wm8971_reset(codec); 665 wm8971_reset(codec);
699 666
700 /* register pcms */ 667 /* register pcms */
701 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 668 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
702 if (ret < 0) { 669 if (ret < 0) {
703 printk(KERN_ERR "wm8971: failed to create pcms\n"); 670 printk(KERN_ERR "wm8971: failed to create pcms\n");
704 goto pcm_err; 671 goto err;
705 } 672 }
706 673
707 /* charge output caps - set vmid to 5k for quick power up */ 674 /* charge output caps - set vmid to 5k for quick power up */
708 reg = wm8971_read_reg_cache(codec, WM8971_PWR1) & 0xfe3e; 675 reg = snd_soc_read(codec, WM8971_PWR1) & 0xfe3e;
709 wm8971_write(codec, WM8971_PWR1, reg | 0x01c0); 676 snd_soc_write(codec, WM8971_PWR1, reg | 0x01c0);
710 codec->bias_level = SND_SOC_BIAS_STANDBY; 677 codec->bias_level = SND_SOC_BIAS_STANDBY;
711 queue_delayed_work(wm8971_workq, &codec->delayed_work, 678 queue_delayed_work(wm8971_workq, &codec->delayed_work,
712 msecs_to_jiffies(1000)); 679 msecs_to_jiffies(1000));
713 680
714 /* set the update bits */ 681 /* set the update bits */
715 reg = wm8971_read_reg_cache(codec, WM8971_LDAC); 682 reg = snd_soc_read(codec, WM8971_LDAC);
716 wm8971_write(codec, WM8971_LDAC, reg | 0x0100); 683 snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
717 reg = wm8971_read_reg_cache(codec, WM8971_RDAC); 684 reg = snd_soc_read(codec, WM8971_RDAC);
718 wm8971_write(codec, WM8971_RDAC, reg | 0x0100); 685 snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
719 686
720 reg = wm8971_read_reg_cache(codec, WM8971_LOUT1V); 687 reg = snd_soc_read(codec, WM8971_LOUT1V);
721 wm8971_write(codec, WM8971_LOUT1V, reg | 0x0100); 688 snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
722 reg = wm8971_read_reg_cache(codec, WM8971_ROUT1V); 689 reg = snd_soc_read(codec, WM8971_ROUT1V);
723 wm8971_write(codec, WM8971_ROUT1V, reg | 0x0100); 690 snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
724 691
725 reg = wm8971_read_reg_cache(codec, WM8971_LOUT2V); 692 reg = snd_soc_read(codec, WM8971_LOUT2V);
726 wm8971_write(codec, WM8971_LOUT2V, reg | 0x0100); 693 snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
727 reg = wm8971_read_reg_cache(codec, WM8971_ROUT2V); 694 reg = snd_soc_read(codec, WM8971_ROUT2V);
728 wm8971_write(codec, WM8971_ROUT2V, reg | 0x0100); 695 snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
729 696
730 reg = wm8971_read_reg_cache(codec, WM8971_LINVOL); 697 reg = snd_soc_read(codec, WM8971_LINVOL);
731 wm8971_write(codec, WM8971_LINVOL, reg | 0x0100); 698 snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
732 reg = wm8971_read_reg_cache(codec, WM8971_RINVOL); 699 reg = snd_soc_read(codec, WM8971_RINVOL);
733 wm8971_write(codec, WM8971_RINVOL, reg | 0x0100); 700 snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
734 701
735 snd_soc_add_controls(codec, wm8971_snd_controls, 702 snd_soc_add_controls(codec, wm8971_snd_controls,
736 ARRAY_SIZE(wm8971_snd_controls)); 703 ARRAY_SIZE(wm8971_snd_controls));
@@ -745,7 +712,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
745card_err: 712card_err:
746 snd_soc_free_pcms(socdev); 713 snd_soc_free_pcms(socdev);
747 snd_soc_dapm_free(socdev); 714 snd_soc_dapm_free(socdev);
748pcm_err: 715err:
749 kfree(codec->reg_cache); 716 kfree(codec->reg_cache);
750 return ret; 717 return ret;
751} 718}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 6f15acd10489..7d5b807bdb48 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -57,50 +57,7 @@ struct wm8988_priv {
57}; 57};
58 58
59 59
60/* 60#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
61 * read wm8988 register cache
62 */
63static inline unsigned int wm8988_read_reg_cache(struct snd_soc_codec *codec,
64 unsigned int reg)
65{
66 u16 *cache = codec->reg_cache;
67 if (reg > WM8988_NUM_REG)
68 return -1;
69 return cache[reg];
70}
71
72/*
73 * write wm8988 register cache
74 */
75static inline void wm8988_write_reg_cache(struct snd_soc_codec *codec,
76 unsigned int reg, unsigned int value)
77{
78 u16 *cache = codec->reg_cache;
79 if (reg > WM8988_NUM_REG)
80 return;
81 cache[reg] = value;
82}
83
84static int wm8988_write(struct snd_soc_codec *codec, unsigned int reg,
85 unsigned int value)
86{
87 u8 data[2];
88
89 /* data is
90 * D15..D9 WM8753 register offset
91 * D8...D0 register data
92 */
93 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
94 data[1] = value & 0x00ff;
95
96 wm8988_write_reg_cache(codec, reg, value);
97 if (codec->hw_write(codec->control_data, data, 2) == 2)
98 return 0;
99 else
100 return -EIO;
101}
102
103#define wm8988_reset(c) wm8988_write(c, WM8988_RESET, 0)
104 61
105/* 62/*
106 * WM8988 Controls 63 * WM8988 Controls
@@ -226,15 +183,15 @@ static int wm8988_lrc_control(struct snd_soc_dapm_widget *w,
226 struct snd_kcontrol *kcontrol, int event) 183 struct snd_kcontrol *kcontrol, int event)
227{ 184{
228 struct snd_soc_codec *codec = w->codec; 185 struct snd_soc_codec *codec = w->codec;
229 u16 adctl2 = wm8988_read_reg_cache(codec, WM8988_ADCTL2); 186 u16 adctl2 = snd_soc_read(codec, WM8988_ADCTL2);
230 187
231 /* Use the DAC to gate LRC if active, otherwise use ADC */ 188 /* Use the DAC to gate LRC if active, otherwise use ADC */
232 if (wm8988_read_reg_cache(codec, WM8988_PWR2) & 0x180) 189 if (snd_soc_read(codec, WM8988_PWR2) & 0x180)
233 adctl2 &= ~0x4; 190 adctl2 &= ~0x4;
234 else 191 else
235 adctl2 |= 0x4; 192 adctl2 |= 0x4;
236 193
237 return wm8988_write(codec, WM8988_ADCTL2, adctl2); 194 return snd_soc_write(codec, WM8988_ADCTL2, adctl2);
238} 195}
239 196
240static const char *wm8988_line_texts[] = { 197static const char *wm8988_line_texts[] = {
@@ -619,7 +576,7 @@ static int wm8988_set_dai_fmt(struct snd_soc_dai *codec_dai,
619 return -EINVAL; 576 return -EINVAL;
620 } 577 }
621 578
622 wm8988_write(codec, WM8988_IFACE, iface); 579 snd_soc_write(codec, WM8988_IFACE, iface);
623 return 0; 580 return 0;
624} 581}
625 582
@@ -653,8 +610,8 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
653 struct snd_soc_device *socdev = rtd->socdev; 610 struct snd_soc_device *socdev = rtd->socdev;
654 struct snd_soc_codec *codec = socdev->card->codec; 611 struct snd_soc_codec *codec = socdev->card->codec;
655 struct wm8988_priv *wm8988 = codec->private_data; 612 struct wm8988_priv *wm8988 = codec->private_data;
656 u16 iface = wm8988_read_reg_cache(codec, WM8988_IFACE) & 0x1f3; 613 u16 iface = snd_soc_read(codec, WM8988_IFACE) & 0x1f3;
657 u16 srate = wm8988_read_reg_cache(codec, WM8988_SRATE) & 0x180; 614 u16 srate = snd_soc_read(codec, WM8988_SRATE) & 0x180;
658 int coeff; 615 int coeff;
659 616
660 coeff = get_coeff(wm8988->sysclk, params_rate(params)); 617 coeff = get_coeff(wm8988->sysclk, params_rate(params));
@@ -685,9 +642,9 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
685 } 642 }
686 643
687 /* set iface & srate */ 644 /* set iface & srate */
688 wm8988_write(codec, WM8988_IFACE, iface); 645 snd_soc_write(codec, WM8988_IFACE, iface);
689 if (coeff >= 0) 646 if (coeff >= 0)
690 wm8988_write(codec, WM8988_SRATE, srate | 647 snd_soc_write(codec, WM8988_SRATE, srate |
691 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb); 648 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
692 649
693 return 0; 650 return 0;
@@ -696,19 +653,19 @@ static int wm8988_pcm_hw_params(struct snd_pcm_substream *substream,
696static int wm8988_mute(struct snd_soc_dai *dai, int mute) 653static int wm8988_mute(struct snd_soc_dai *dai, int mute)
697{ 654{
698 struct snd_soc_codec *codec = dai->codec; 655 struct snd_soc_codec *codec = dai->codec;
699 u16 mute_reg = wm8988_read_reg_cache(codec, WM8988_ADCDAC) & 0xfff7; 656 u16 mute_reg = snd_soc_read(codec, WM8988_ADCDAC) & 0xfff7;
700 657
701 if (mute) 658 if (mute)
702 wm8988_write(codec, WM8988_ADCDAC, mute_reg | 0x8); 659 snd_soc_write(codec, WM8988_ADCDAC, mute_reg | 0x8);
703 else 660 else
704 wm8988_write(codec, WM8988_ADCDAC, mute_reg); 661 snd_soc_write(codec, WM8988_ADCDAC, mute_reg);
705 return 0; 662 return 0;
706} 663}
707 664
708static int wm8988_set_bias_level(struct snd_soc_codec *codec, 665static int wm8988_set_bias_level(struct snd_soc_codec *codec,
709 enum snd_soc_bias_level level) 666 enum snd_soc_bias_level level)
710{ 667{
711 u16 pwr_reg = wm8988_read_reg_cache(codec, WM8988_PWR1) & ~0x1c1; 668 u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
712 669
713 switch (level) { 670 switch (level) {
714 case SND_SOC_BIAS_ON: 671 case SND_SOC_BIAS_ON:
@@ -716,24 +673,24 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
716 673
717 case SND_SOC_BIAS_PREPARE: 674 case SND_SOC_BIAS_PREPARE:
718 /* VREF, VMID=2x50k, digital enabled */ 675 /* VREF, VMID=2x50k, digital enabled */
719 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x00c0); 676 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x00c0);
720 break; 677 break;
721 678
722 case SND_SOC_BIAS_STANDBY: 679 case SND_SOC_BIAS_STANDBY:
723 if (codec->bias_level == SND_SOC_BIAS_OFF) { 680 if (codec->bias_level == SND_SOC_BIAS_OFF) {
724 /* VREF, VMID=2x5k */ 681 /* VREF, VMID=2x5k */
725 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x1c1); 682 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
726 683
727 /* Charge caps */ 684 /* Charge caps */
728 msleep(100); 685 msleep(100);
729 } 686 }
730 687
731 /* VREF, VMID=2*500k, digital stopped */ 688 /* VREF, VMID=2*500k, digital stopped */
732 wm8988_write(codec, WM8988_PWR1, pwr_reg | 0x0141); 689 snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x0141);
733 break; 690 break;
734 691
735 case SND_SOC_BIAS_OFF: 692 case SND_SOC_BIAS_OFF:
736 wm8988_write(codec, WM8988_PWR1, 0x0000); 693 snd_soc_write(codec, WM8988_PWR1, 0x0000);
737 break; 694 break;
738 } 695 }
739 codec->bias_level = level; 696 codec->bias_level = level;
@@ -887,8 +844,6 @@ static int wm8988_register(struct wm8988_priv *wm8988)
887 codec->private_data = wm8988; 844 codec->private_data = wm8988;
888 codec->name = "WM8988"; 845 codec->name = "WM8988";
889 codec->owner = THIS_MODULE; 846 codec->owner = THIS_MODULE;
890 codec->read = wm8988_read_reg_cache;
891 codec->write = wm8988_write;
892 codec->dai = &wm8988_dai; 847 codec->dai = &wm8988_dai;
893 codec->num_dai = 1; 848 codec->num_dai = 1;
894 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache); 849 codec->reg_cache_size = ARRAY_SIZE(wm8988->reg_cache);
@@ -899,6 +854,12 @@ static int wm8988_register(struct wm8988_priv *wm8988)
899 memcpy(codec->reg_cache, wm8988_reg, 854 memcpy(codec->reg_cache, wm8988_reg,
900 sizeof(wm8988_reg)); 855 sizeof(wm8988_reg));
901 856
857 ret = snd_soc_codec_set_cache_io(codec, 7, 9);
858 if (ret < 0) {
859 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
860 goto err;
861 }
862
902 ret = wm8988_reset(codec); 863 ret = wm8988_reset(codec);
903 if (ret < 0) { 864 if (ret < 0) {
904 dev_err(codec->dev, "Failed to issue reset\n"); 865 dev_err(codec->dev, "Failed to issue reset\n");
@@ -906,16 +867,16 @@ static int wm8988_register(struct wm8988_priv *wm8988)
906 } 867 }
907 868
908 /* set the update bits (we always update left then right) */ 869 /* set the update bits (we always update left then right) */
909 reg = wm8988_read_reg_cache(codec, WM8988_RADC); 870 reg = snd_soc_read(codec, WM8988_RADC);
910 wm8988_write(codec, WM8988_RADC, reg | 0x100); 871 snd_soc_write(codec, WM8988_RADC, reg | 0x100);
911 reg = wm8988_read_reg_cache(codec, WM8988_RDAC); 872 reg = snd_soc_read(codec, WM8988_RDAC);
912 wm8988_write(codec, WM8988_RDAC, reg | 0x0100); 873 snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
913 reg = wm8988_read_reg_cache(codec, WM8988_ROUT1V); 874 reg = snd_soc_read(codec, WM8988_ROUT1V);
914 wm8988_write(codec, WM8988_ROUT1V, reg | 0x0100); 875 snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
915 reg = wm8988_read_reg_cache(codec, WM8988_ROUT2V); 876 reg = snd_soc_read(codec, WM8988_ROUT2V);
916 wm8988_write(codec, WM8988_ROUT2V, reg | 0x0100); 877 snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
917 reg = wm8988_read_reg_cache(codec, WM8988_RINVOL); 878 reg = snd_soc_read(codec, WM8988_RINVOL);
918 wm8988_write(codec, WM8988_RINVOL, reg | 0x0100); 879 snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
919 880
920 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY); 881 wm8988_set_bias_level(&wm8988->codec, SND_SOC_BIAS_STANDBY);
921 882