aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/Makefile2
-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
-rw-r--r--sound/soc/soc-cache.c105
9 files changed, 398 insertions, 577 deletions
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 6f1e28de23cf..4eaf48aab0fa 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,4 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o 1snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o
2 2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o 3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ 4obj-$(CONFIG_SND_SOC) += codecs/
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
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
new file mode 100644
index 000000000000..4eb4333a0efb
--- /dev/null
+++ b/sound/soc/soc-cache.c
@@ -0,0 +1,105 @@
1/*
2 * soc-cache.c -- ASoC register cache helpers
3 *
4 * Copyright 2009 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#include <sound/soc.h>
15
16static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
17 unsigned int reg)
18{
19 u16 *cache = codec->reg_cache;
20 if (reg >= codec->reg_cache_size)
21 return -1;
22 return cache[reg];
23}
24
25static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
26 unsigned int value)
27{
28 u16 *cache = codec->reg_cache;
29 u8 data[2];
30 int ret;
31
32 BUG_ON(codec->volatile_register);
33
34 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
35 data[1] = value & 0x00ff;
36
37 if (reg < codec->reg_cache_size)
38 cache[reg] = value;
39 ret = codec->hw_write(codec->control_data, data, 2);
40 if (ret == 2)
41 return 0;
42 if (ret < 0)
43 return ret;
44 else
45 return -EIO;
46}
47
48
49static struct {
50 int addr_bits;
51 int data_bits;
52 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
53 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
54} io_types[] = {
55 { 7, 9, snd_soc_7_9_write, snd_soc_7_9_read },
56};
57
58/**
59 * snd_soc_codec_set_cache_io: Set up standard I/O functions.
60 *
61 * @codec: CODEC to configure.
62 * @type: Type of cache.
63 * @addr_bits: Number of bits of register address data.
64 * @data_bits: Number of bits of data per register.
65 *
66 * Register formats are frequently shared between many I2C and SPI
67 * devices. In order to promote code reuse the ASoC core provides
68 * some standard implementations of CODEC read and write operations
69 * which can be set up using this function.
70 *
71 * The caller is responsible for allocating and initialising the
72 * actual cache.
73 *
74 * Note that at present this code cannot be used by CODECs with
75 * volatile registers.
76 */
77int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
78 int addr_bits, int data_bits)
79{
80 int i;
81
82 /* We don't support volatile registers yet - refactoring of
83 * the hw_read operation will be required to do so. */
84 if (codec->volatile_register) {
85 printk(KERN_ERR "Volatile registers not yet supported\n");
86 return -EINVAL;
87 }
88
89 for (i = 0; i < ARRAY_SIZE(io_types); i++)
90 if (io_types[i].addr_bits == addr_bits &&
91 io_types[i].data_bits == data_bits)
92 break;
93 if (i == ARRAY_SIZE(io_types)) {
94 printk(KERN_ERR
95 "No I/O functions for %d bit address %d bit data\n",
96 addr_bits, data_bits);
97 return -EINVAL;
98 }
99
100 codec->write = io_types[i].write;
101 codec->read = io_types[i].read;
102
103 return 0;
104}
105EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);