aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/soc-cache.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/soc-cache.c')
-rw-r--r--sound/soc/soc-cache.c1065
1 files changed, 1014 insertions, 51 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index d214f02cbb65..8c2a21a978ac 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -14,27 +14,34 @@
14#include <linux/i2c.h> 14#include <linux/i2c.h>
15#include <linux/spi/spi.h> 15#include <linux/spi/spi.h>
16#include <sound/soc.h> 16#include <sound/soc.h>
17#include <linux/lzo.h>
18#include <linux/bitmap.h>
19#include <linux/rbtree.h>
17 20
18static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, 21static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
19 unsigned int reg) 22 unsigned int reg)
20{ 23{
21 u16 *cache = codec->reg_cache; 24 int ret;
25 unsigned int val;
22 26
23 if (reg >= codec->driver->reg_cache_size || 27 if (reg >= codec->driver->reg_cache_size ||
24 snd_soc_codec_volatile_register(codec, reg)) { 28 snd_soc_codec_volatile_register(codec, reg)) {
25 if (codec->cache_only) 29 if (codec->cache_only)
26 return -1; 30 return -1;
27 31
32 BUG_ON(!codec->hw_read);
28 return codec->hw_read(codec, reg); 33 return codec->hw_read(codec, reg);
29 } 34 }
30 35
31 return cache[reg]; 36 ret = snd_soc_cache_read(codec, reg, &val);
37 if (ret < 0)
38 return -1;
39 return val;
32} 40}
33 41
34static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg, 42static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
35 unsigned int value) 43 unsigned int value)
36{ 44{
37 u16 *cache = codec->reg_cache;
38 u8 data[2]; 45 u8 data[2];
39 int ret; 46 int ret;
40 47
@@ -42,16 +49,17 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
42 data[1] = value & 0x00ff; 49 data[1] = value & 0x00ff;
43 50
44 if (!snd_soc_codec_volatile_register(codec, reg) && 51 if (!snd_soc_codec_volatile_register(codec, reg) &&
45 reg < codec->driver->reg_cache_size) 52 reg < codec->driver->reg_cache_size) {
46 cache[reg] = value; 53 ret = snd_soc_cache_write(codec, reg, value);
54 if (ret < 0)
55 return -1;
56 }
47 57
48 if (codec->cache_only) { 58 if (codec->cache_only) {
49 codec->cache_sync = 1; 59 codec->cache_sync = 1;
50 return 0; 60 return 0;
51 } 61 }
52 62
53 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
54
55 ret = codec->hw_write(codec->control_data, data, 2); 63 ret = codec->hw_write(codec->control_data, data, 2);
56 if (ret == 2) 64 if (ret == 2)
57 return 0; 65 return 0;
@@ -77,7 +85,7 @@ static int snd_soc_4_12_spi_write(void *control_data, const char *data,
77 msg[1] = data[0]; 85 msg[1] = data[0];
78 86
79 spi_message_init(&m); 87 spi_message_init(&m);
80 memset(&t, 0, (sizeof t)); 88 memset(&t, 0, sizeof t);
81 89
82 t.tx_buf = &msg[0]; 90 t.tx_buf = &msg[0];
83 t.len = len; 91 t.len = len;
@@ -94,23 +102,27 @@ static int snd_soc_4_12_spi_write(void *control_data, const char *data,
94static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec, 102static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
95 unsigned int reg) 103 unsigned int reg)
96{ 104{
97 u16 *cache = codec->reg_cache; 105 int ret;
106 unsigned int val;
98 107
99 if (reg >= codec->driver->reg_cache_size || 108 if (reg >= codec->driver->reg_cache_size ||
100 snd_soc_codec_volatile_register(codec, reg)) { 109 snd_soc_codec_volatile_register(codec, reg)) {
101 if (codec->cache_only) 110 if (codec->cache_only)
102 return -1; 111 return -1;
103 112
113 BUG_ON(!codec->hw_read);
104 return codec->hw_read(codec, reg); 114 return codec->hw_read(codec, reg);
105 } 115 }
106 116
107 return cache[reg]; 117 ret = snd_soc_cache_read(codec, reg, &val);
118 if (ret < 0)
119 return -1;
120 return val;
108} 121}
109 122
110static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg, 123static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
111 unsigned int value) 124 unsigned int value)
112{ 125{
113 u16 *cache = codec->reg_cache;
114 u8 data[2]; 126 u8 data[2];
115 int ret; 127 int ret;
116 128
@@ -118,16 +130,17 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
118 data[1] = value & 0x00ff; 130 data[1] = value & 0x00ff;
119 131
120 if (!snd_soc_codec_volatile_register(codec, reg) && 132 if (!snd_soc_codec_volatile_register(codec, reg) &&
121 reg < codec->driver->reg_cache_size) 133 reg < codec->driver->reg_cache_size) {
122 cache[reg] = value; 134 ret = snd_soc_cache_write(codec, reg, value);
135 if (ret < 0)
136 return -1;
137 }
123 138
124 if (codec->cache_only) { 139 if (codec->cache_only) {
125 codec->cache_sync = 1; 140 codec->cache_sync = 1;
126 return 0; 141 return 0;
127 } 142 }
128 143
129 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
130
131 ret = codec->hw_write(codec->control_data, data, 2); 144 ret = codec->hw_write(codec->control_data, data, 2);
132 if (ret == 2) 145 if (ret == 2)
133 return 0; 146 return 0;
@@ -153,7 +166,7 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data,
153 msg[1] = data[1]; 166 msg[1] = data[1];
154 167
155 spi_message_init(&m); 168 spi_message_init(&m);
156 memset(&t, 0, (sizeof t)); 169 memset(&t, 0, sizeof t);
157 170
158 t.tx_buf = &msg[0]; 171 t.tx_buf = &msg[0];
159 t.len = len; 172 t.len = len;
@@ -170,24 +183,25 @@ static int snd_soc_7_9_spi_write(void *control_data, const char *data,
170static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg, 183static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
171 unsigned int value) 184 unsigned int value)
172{ 185{
173 u8 *cache = codec->reg_cache;
174 u8 data[2]; 186 u8 data[2];
187 int ret;
175 188
176 reg &= 0xff; 189 reg &= 0xff;
177 data[0] = reg; 190 data[0] = reg;
178 data[1] = value & 0xff; 191 data[1] = value & 0xff;
179 192
180 if (!snd_soc_codec_volatile_register(codec, reg) && 193 if (!snd_soc_codec_volatile_register(codec, reg) &&
181 reg < codec->driver->reg_cache_size) 194 reg < codec->driver->reg_cache_size) {
182 cache[reg] = value; 195 ret = snd_soc_cache_write(codec, reg, value);
196 if (ret < 0)
197 return -1;
198 }
183 199
184 if (codec->cache_only) { 200 if (codec->cache_only) {
185 codec->cache_sync = 1; 201 codec->cache_sync = 1;
186 return 0; 202 return 0;
187 } 203 }
188 204
189 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
190
191 if (codec->hw_write(codec->control_data, data, 2) == 2) 205 if (codec->hw_write(codec->control_data, data, 2) == 2)
192 return 0; 206 return 0;
193 else 207 else
@@ -197,7 +211,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
197static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec, 211static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
198 unsigned int reg) 212 unsigned int reg)
199{ 213{
200 u8 *cache = codec->reg_cache; 214 int ret;
215 unsigned int val;
201 216
202 reg &= 0xff; 217 reg &= 0xff;
203 if (reg >= codec->driver->reg_cache_size || 218 if (reg >= codec->driver->reg_cache_size ||
@@ -205,10 +220,14 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
205 if (codec->cache_only) 220 if (codec->cache_only)
206 return -1; 221 return -1;
207 222
223 BUG_ON(!codec->hw_read);
208 return codec->hw_read(codec, reg); 224 return codec->hw_read(codec, reg);
209 } 225 }
210 226
211 return cache[reg]; 227 ret = snd_soc_cache_read(codec, reg, &val);
228 if (ret < 0)
229 return -1;
230 return val;
212} 231}
213 232
214#if defined(CONFIG_SPI_MASTER) 233#if defined(CONFIG_SPI_MASTER)
@@ -227,7 +246,7 @@ static int snd_soc_8_8_spi_write(void *control_data, const char *data,
227 msg[1] = data[1]; 246 msg[1] = data[1];
228 247
229 spi_message_init(&m); 248 spi_message_init(&m);
230 memset(&t, 0, (sizeof t)); 249 memset(&t, 0, sizeof t);
231 250
232 t.tx_buf = &msg[0]; 251 t.tx_buf = &msg[0];
233 t.len = len; 252 t.len = len;
@@ -244,24 +263,25 @@ static int snd_soc_8_8_spi_write(void *control_data, const char *data,
244static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg, 263static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
245 unsigned int value) 264 unsigned int value)
246{ 265{
247 u16 *reg_cache = codec->reg_cache;
248 u8 data[3]; 266 u8 data[3];
267 int ret;
249 268
250 data[0] = reg; 269 data[0] = reg;
251 data[1] = (value >> 8) & 0xff; 270 data[1] = (value >> 8) & 0xff;
252 data[2] = value & 0xff; 271 data[2] = value & 0xff;
253 272
254 if (!snd_soc_codec_volatile_register(codec, reg) && 273 if (!snd_soc_codec_volatile_register(codec, reg) &&
255 reg < codec->driver->reg_cache_size) 274 reg < codec->driver->reg_cache_size) {
256 reg_cache[reg] = value; 275 ret = snd_soc_cache_write(codec, reg, value);
276 if (ret < 0)
277 return -1;
278 }
257 279
258 if (codec->cache_only) { 280 if (codec->cache_only) {
259 codec->cache_sync = 1; 281 codec->cache_sync = 1;
260 return 0; 282 return 0;
261 } 283 }
262 284
263 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
264
265 if (codec->hw_write(codec->control_data, data, 3) == 3) 285 if (codec->hw_write(codec->control_data, data, 3) == 3)
266 return 0; 286 return 0;
267 else 287 else
@@ -271,17 +291,22 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
271static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec, 291static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
272 unsigned int reg) 292 unsigned int reg)
273{ 293{
274 u16 *cache = codec->reg_cache; 294 int ret;
295 unsigned int val;
275 296
276 if (reg >= codec->driver->reg_cache_size || 297 if (reg >= codec->driver->reg_cache_size ||
277 snd_soc_codec_volatile_register(codec, reg)) { 298 snd_soc_codec_volatile_register(codec, reg)) {
278 if (codec->cache_only) 299 if (codec->cache_only)
279 return -1; 300 return -1;
280 301
302 BUG_ON(!codec->hw_read);
281 return codec->hw_read(codec, reg); 303 return codec->hw_read(codec, reg);
282 } else {
283 return cache[reg];
284 } 304 }
305
306 ret = snd_soc_cache_read(codec, reg, &val);
307 if (ret < 0)
308 return -1;
309 return val;
285} 310}
286 311
287#if defined(CONFIG_SPI_MASTER) 312#if defined(CONFIG_SPI_MASTER)
@@ -301,7 +326,7 @@ static int snd_soc_8_16_spi_write(void *control_data, const char *data,
301 msg[2] = data[2]; 326 msg[2] = data[2];
302 327
303 spi_message_init(&m); 328 spi_message_init(&m);
304 memset(&t, 0, (sizeof t)); 329 memset(&t, 0, sizeof t);
305 330
306 t.tx_buf = &msg[0]; 331 t.tx_buf = &msg[0];
307 t.len = len; 332 t.len = len;
@@ -420,7 +445,8 @@ static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
420static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec, 445static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
421 unsigned int reg) 446 unsigned int reg)
422{ 447{
423 u8 *cache = codec->reg_cache; 448 int ret;
449 unsigned int val;
424 450
425 reg &= 0xff; 451 reg &= 0xff;
426 if (reg >= codec->driver->reg_cache_size || 452 if (reg >= codec->driver->reg_cache_size ||
@@ -428,16 +454,19 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
428 if (codec->cache_only) 454 if (codec->cache_only)
429 return -1; 455 return -1;
430 456
457 BUG_ON(!codec->hw_read);
431 return codec->hw_read(codec, reg); 458 return codec->hw_read(codec, reg);
432 } 459 }
433 460
434 return cache[reg]; 461 ret = snd_soc_cache_read(codec, reg, &val);
462 if (ret < 0)
463 return -1;
464 return val;
435} 465}
436 466
437static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg, 467static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
438 unsigned int value) 468 unsigned int value)
439{ 469{
440 u8 *cache = codec->reg_cache;
441 u8 data[3]; 470 u8 data[3];
442 int ret; 471 int ret;
443 472
@@ -447,16 +476,17 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
447 476
448 reg &= 0xff; 477 reg &= 0xff;
449 if (!snd_soc_codec_volatile_register(codec, reg) && 478 if (!snd_soc_codec_volatile_register(codec, reg) &&
450 reg < codec->driver->reg_cache_size) 479 reg < codec->driver->reg_cache_size) {
451 cache[reg] = value; 480 ret = snd_soc_cache_write(codec, reg, value);
481 if (ret < 0)
482 return -1;
483 }
452 484
453 if (codec->cache_only) { 485 if (codec->cache_only) {
454 codec->cache_sync = 1; 486 codec->cache_sync = 1;
455 return 0; 487 return 0;
456 } 488 }
457 489
458 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
459
460 ret = codec->hw_write(codec->control_data, data, 3); 490 ret = codec->hw_write(codec->control_data, data, 3);
461 if (ret == 3) 491 if (ret == 3)
462 return 0; 492 return 0;
@@ -483,7 +513,7 @@ static int snd_soc_16_8_spi_write(void *control_data, const char *data,
483 msg[2] = data[2]; 513 msg[2] = data[2];
484 514
485 spi_message_init(&m); 515 spi_message_init(&m);
486 memset(&t, 0, (sizeof t)); 516 memset(&t, 0, sizeof t);
487 517
488 t.tx_buf = &msg[0]; 518 t.tx_buf = &msg[0];
489 t.len = len; 519 t.len = len;
@@ -534,23 +564,28 @@ static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
534static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec, 564static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
535 unsigned int reg) 565 unsigned int reg)
536{ 566{
537 u16 *cache = codec->reg_cache; 567 int ret;
568 unsigned int val;
538 569
539 if (reg >= codec->driver->reg_cache_size || 570 if (reg >= codec->driver->reg_cache_size ||
540 snd_soc_codec_volatile_register(codec, reg)) { 571 snd_soc_codec_volatile_register(codec, reg)) {
541 if (codec->cache_only) 572 if (codec->cache_only)
542 return -1; 573 return -1;
543 574
575 BUG_ON(!codec->hw_read);
544 return codec->hw_read(codec, reg); 576 return codec->hw_read(codec, reg);
545 } 577 }
546 578
547 return cache[reg]; 579 ret = snd_soc_cache_read(codec, reg, &val);
580 if (ret < 0)
581 return -1;
582
583 return val;
548} 584}
549 585
550static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg, 586static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
551 unsigned int value) 587 unsigned int value)
552{ 588{
553 u16 *cache = codec->reg_cache;
554 u8 data[4]; 589 u8 data[4];
555 int ret; 590 int ret;
556 591
@@ -560,16 +595,17 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
560 data[3] = value & 0xff; 595 data[3] = value & 0xff;
561 596
562 if (!snd_soc_codec_volatile_register(codec, reg) && 597 if (!snd_soc_codec_volatile_register(codec, reg) &&
563 reg < codec->driver->reg_cache_size) 598 reg < codec->driver->reg_cache_size) {
564 cache[reg] = value; 599 ret = snd_soc_cache_write(codec, reg, value);
600 if (ret < 0)
601 return -1;
602 }
565 603
566 if (codec->cache_only) { 604 if (codec->cache_only) {
567 codec->cache_sync = 1; 605 codec->cache_sync = 1;
568 return 0; 606 return 0;
569 } 607 }
570 608
571 dev_dbg(codec->dev, "0x%x = 0x%x\n", reg, value);
572
573 ret = codec->hw_write(codec->control_data, data, 4); 609 ret = codec->hw_write(codec->control_data, data, 4);
574 if (ret == 4) 610 if (ret == 4)
575 return 0; 611 return 0;
@@ -597,7 +633,7 @@ static int snd_soc_16_16_spi_write(void *control_data, const char *data,
597 msg[3] = data[3]; 633 msg[3] = data[3];
598 634
599 spi_message_init(&m); 635 spi_message_init(&m);
600 memset(&t, 0, (sizeof t)); 636 memset(&t, 0, sizeof t);
601 637
602 t.tx_buf = &msg[0]; 638 t.tx_buf = &msg[0];
603 t.len = len; 639 t.len = len;
@@ -692,8 +728,8 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
692 return -EINVAL; 728 return -EINVAL;
693 } 729 }
694 730
695 codec->driver->write = io_types[i].write; 731 codec->write = io_types[i].write;
696 codec->driver->read = io_types[i].read; 732 codec->read = io_types[i].read;
697 733
698 switch (control) { 734 switch (control) {
699 case SND_SOC_CUSTOM: 735 case SND_SOC_CUSTOM:
@@ -724,3 +760,930 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
724 return 0; 760 return 0;
725} 761}
726EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 762EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
763
764struct snd_soc_rbtree_node {
765 struct rb_node node;
766 unsigned int reg;
767 unsigned int value;
768 unsigned int defval;
769} __attribute__ ((packed));
770
771struct snd_soc_rbtree_ctx {
772 struct rb_root root;
773};
774
775static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup(
776 struct rb_root *root, unsigned int reg)
777{
778 struct rb_node *node;
779 struct snd_soc_rbtree_node *rbnode;
780
781 node = root->rb_node;
782 while (node) {
783 rbnode = container_of(node, struct snd_soc_rbtree_node, node);
784 if (rbnode->reg < reg)
785 node = node->rb_left;
786 else if (rbnode->reg > reg)
787 node = node->rb_right;
788 else
789 return rbnode;
790 }
791
792 return NULL;
793}
794
795static int snd_soc_rbtree_insert(struct rb_root *root,
796 struct snd_soc_rbtree_node *rbnode)
797{
798 struct rb_node **new, *parent;
799 struct snd_soc_rbtree_node *rbnode_tmp;
800
801 parent = NULL;
802 new = &root->rb_node;
803 while (*new) {
804 rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node,
805 node);
806 parent = *new;
807 if (rbnode_tmp->reg < rbnode->reg)
808 new = &((*new)->rb_left);
809 else if (rbnode_tmp->reg > rbnode->reg)
810 new = &((*new)->rb_right);
811 else
812 return 0;
813 }
814
815 /* insert the node into the rbtree */
816 rb_link_node(&rbnode->node, parent, new);
817 rb_insert_color(&rbnode->node, root);
818
819 return 1;
820}
821
822static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
823{
824 struct snd_soc_rbtree_ctx *rbtree_ctx;
825 struct rb_node *node;
826 struct snd_soc_rbtree_node *rbnode;
827 unsigned int val;
828 int ret;
829
830 rbtree_ctx = codec->reg_cache;
831 for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
832 rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
833 if (rbnode->value == rbnode->defval)
834 continue;
835 ret = snd_soc_cache_read(codec, rbnode->reg, &val);
836 if (ret)
837 return ret;
838 ret = snd_soc_write(codec, rbnode->reg, val);
839 if (ret)
840 return ret;
841 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
842 rbnode->reg, val);
843 }
844
845 return 0;
846}
847
848static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec,
849 unsigned int reg, unsigned int value)
850{
851 struct snd_soc_rbtree_ctx *rbtree_ctx;
852 struct snd_soc_rbtree_node *rbnode;
853
854 rbtree_ctx = codec->reg_cache;
855 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
856 if (rbnode) {
857 if (rbnode->value == value)
858 return 0;
859 rbnode->value = value;
860 } else {
861 /* bail out early, no need to create the rbnode yet */
862 if (!value)
863 return 0;
864 /*
865 * for uninitialized registers whose value is changed
866 * from the default zero, create an rbnode and insert
867 * it into the tree.
868 */
869 rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
870 if (!rbnode)
871 return -ENOMEM;
872 rbnode->reg = reg;
873 rbnode->value = value;
874 snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode);
875 }
876
877 return 0;
878}
879
880static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec,
881 unsigned int reg, unsigned int *value)
882{
883 struct snd_soc_rbtree_ctx *rbtree_ctx;
884 struct snd_soc_rbtree_node *rbnode;
885
886 rbtree_ctx = codec->reg_cache;
887 rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
888 if (rbnode) {
889 *value = rbnode->value;
890 } else {
891 /* uninitialized registers default to 0 */
892 *value = 0;
893 }
894
895 return 0;
896}
897
898static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
899{
900 struct rb_node *next;
901 struct snd_soc_rbtree_ctx *rbtree_ctx;
902 struct snd_soc_rbtree_node *rbtree_node;
903
904 /* if we've already been called then just return */
905 rbtree_ctx = codec->reg_cache;
906 if (!rbtree_ctx)
907 return 0;
908
909 /* free up the rbtree */
910 next = rb_first(&rbtree_ctx->root);
911 while (next) {
912 rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node);
913 next = rb_next(&rbtree_node->node);
914 rb_erase(&rbtree_node->node, &rbtree_ctx->root);
915 kfree(rbtree_node);
916 }
917
918 /* release the resources */
919 kfree(codec->reg_cache);
920 codec->reg_cache = NULL;
921
922 return 0;
923}
924
925static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
926{
927 struct snd_soc_rbtree_ctx *rbtree_ctx;
928
929 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
930 if (!codec->reg_cache)
931 return -ENOMEM;
932
933 rbtree_ctx = codec->reg_cache;
934 rbtree_ctx->root = RB_ROOT;
935
936 if (!codec->reg_def_copy)
937 return 0;
938
939/*
940 * populate the rbtree with the initialized registers. All other
941 * registers will be inserted into the tree when they are first written.
942 *
943 * The reasoning behind this, is that we need to step through and
944 * dereference the cache in u8/u16 increments without sacrificing
945 * portability. This could also be done using memcpy() but that would
946 * be slightly more cryptic.
947 */
948#define snd_soc_rbtree_populate(cache) \
949({ \
950 int ret, i; \
951 struct snd_soc_rbtree_node *rbtree_node; \
952 \
953 ret = 0; \
954 cache = codec->reg_def_copy; \
955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \
956 if (!cache[i]) \
957 continue; \
958 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL); \
959 if (!rbtree_node) { \
960 ret = -ENOMEM; \
961 snd_soc_cache_exit(codec); \
962 break; \
963 } \
964 rbtree_node->reg = i; \
965 rbtree_node->value = cache[i]; \
966 rbtree_node->defval = cache[i]; \
967 snd_soc_rbtree_insert(&rbtree_ctx->root, \
968 rbtree_node); \
969 } \
970 ret; \
971})
972
973 switch (codec->driver->reg_word_size) {
974 case 1: {
975 const u8 *cache;
976
977 return snd_soc_rbtree_populate(cache);
978 }
979 case 2: {
980 const u16 *cache;
981
982 return snd_soc_rbtree_populate(cache);
983 }
984 default:
985 BUG();
986 }
987
988 return 0;
989}
990
991#ifdef CONFIG_SND_SOC_CACHE_LZO
992struct snd_soc_lzo_ctx {
993 void *wmem;
994 void *dst;
995 const void *src;
996 size_t src_len;
997 size_t dst_len;
998 size_t decompressed_size;
999 unsigned long *sync_bmp;
1000 int sync_bmp_nbits;
1001};
1002
1003#define LZO_BLOCK_NUM 8
1004static int snd_soc_lzo_block_count(void)
1005{
1006 return LZO_BLOCK_NUM;
1007}
1008
1009static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
1010{
1011 lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
1012 if (!lzo_ctx->wmem)
1013 return -ENOMEM;
1014 return 0;
1015}
1016
1017static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
1018{
1019 size_t compress_size;
1020 int ret;
1021
1022 ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
1023 lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
1024 if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
1025 return -EINVAL;
1026 lzo_ctx->dst_len = compress_size;
1027 return 0;
1028}
1029
1030static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
1031{
1032 size_t dst_len;
1033 int ret;
1034
1035 dst_len = lzo_ctx->dst_len;
1036 ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
1037 lzo_ctx->dst, &dst_len);
1038 if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
1039 return -EINVAL;
1040 return 0;
1041}
1042
1043static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
1044 struct snd_soc_lzo_ctx *lzo_ctx)
1045{
1046 int ret;
1047
1048 lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
1049 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
1050 if (!lzo_ctx->dst) {
1051 lzo_ctx->dst_len = 0;
1052 return -ENOMEM;
1053 }
1054
1055 ret = snd_soc_lzo_compress(lzo_ctx);
1056 if (ret < 0)
1057 return ret;
1058 return 0;
1059}
1060
1061static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
1062 struct snd_soc_lzo_ctx *lzo_ctx)
1063{
1064 int ret;
1065
1066 lzo_ctx->dst_len = lzo_ctx->decompressed_size;
1067 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
1068 if (!lzo_ctx->dst) {
1069 lzo_ctx->dst_len = 0;
1070 return -ENOMEM;
1071 }
1072
1073 ret = snd_soc_lzo_decompress(lzo_ctx);
1074 if (ret < 0)
1075 return ret;
1076 return 0;
1077}
1078
1079static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
1080 unsigned int reg)
1081{
1082 const struct snd_soc_codec_driver *codec_drv;
1083 size_t reg_size;
1084
1085 codec_drv = codec->driver;
1086 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1087 return (reg * codec_drv->reg_word_size) /
1088 DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
1089}
1090
1091static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
1092 unsigned int reg)
1093{
1094 const struct snd_soc_codec_driver *codec_drv;
1095 size_t reg_size;
1096
1097 codec_drv = codec->driver;
1098 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1099 return reg % (DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()) /
1100 codec_drv->reg_word_size);
1101}
1102
1103static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
1104{
1105 const struct snd_soc_codec_driver *codec_drv;
1106 size_t reg_size;
1107
1108 codec_drv = codec->driver;
1109 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1110 return DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
1111}
1112
1113static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
1114{
1115 struct snd_soc_lzo_ctx **lzo_blocks;
1116 unsigned int val;
1117 int i;
1118 int ret;
1119
1120 lzo_blocks = codec->reg_cache;
1121 for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
1122 ret = snd_soc_cache_read(codec, i, &val);
1123 if (ret)
1124 return ret;
1125 ret = snd_soc_write(codec, i, val);
1126 if (ret)
1127 return ret;
1128 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
1129 i, val);
1130 }
1131
1132 return 0;
1133}
1134
1135static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
1136 unsigned int reg, unsigned int value)
1137{
1138 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
1139 int ret, blkindex, blkpos;
1140 size_t blksize, tmp_dst_len;
1141 void *tmp_dst;
1142
1143 /* index of the compressed lzo block */
1144 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
1145 /* register index within the decompressed block */
1146 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
1147 /* size of the compressed block */
1148 blksize = snd_soc_lzo_get_blksize(codec);
1149 lzo_blocks = codec->reg_cache;
1150 lzo_block = lzo_blocks[blkindex];
1151
1152 /* save the pointer and length of the compressed block */
1153 tmp_dst = lzo_block->dst;
1154 tmp_dst_len = lzo_block->dst_len;
1155
1156 /* prepare the source to be the compressed block */
1157 lzo_block->src = lzo_block->dst;
1158 lzo_block->src_len = lzo_block->dst_len;
1159
1160 /* decompress the block */
1161 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1162 if (ret < 0) {
1163 kfree(lzo_block->dst);
1164 goto out;
1165 }
1166
1167 /* write the new value to the cache */
1168 switch (codec->driver->reg_word_size) {
1169 case 1: {
1170 u8 *cache;
1171 cache = lzo_block->dst;
1172 if (cache[blkpos] == value) {
1173 kfree(lzo_block->dst);
1174 goto out;
1175 }
1176 cache[blkpos] = value;
1177 }
1178 break;
1179 case 2: {
1180 u16 *cache;
1181 cache = lzo_block->dst;
1182 if (cache[blkpos] == value) {
1183 kfree(lzo_block->dst);
1184 goto out;
1185 }
1186 cache[blkpos] = value;
1187 }
1188 break;
1189 default:
1190 BUG();
1191 }
1192
1193 /* prepare the source to be the decompressed block */
1194 lzo_block->src = lzo_block->dst;
1195 lzo_block->src_len = lzo_block->dst_len;
1196
1197 /* compress the block */
1198 ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
1199 if (ret < 0) {
1200 kfree(lzo_block->dst);
1201 kfree(lzo_block->src);
1202 goto out;
1203 }
1204
1205 /* set the bit so we know we have to sync this register */
1206 set_bit(reg, lzo_block->sync_bmp);
1207 kfree(tmp_dst);
1208 kfree(lzo_block->src);
1209 return 0;
1210out:
1211 lzo_block->dst = tmp_dst;
1212 lzo_block->dst_len = tmp_dst_len;
1213 return ret;
1214}
1215
1216static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1217 unsigned int reg, unsigned int *value)
1218{
1219 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
1220 int ret, blkindex, blkpos;
1221 size_t blksize, tmp_dst_len;
1222 void *tmp_dst;
1223
1224 *value = 0;
1225 /* index of the compressed lzo block */
1226 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
1227 /* register index within the decompressed block */
1228 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
1229 /* size of the compressed block */
1230 blksize = snd_soc_lzo_get_blksize(codec);
1231 lzo_blocks = codec->reg_cache;
1232 lzo_block = lzo_blocks[blkindex];
1233
1234 /* save the pointer and length of the compressed block */
1235 tmp_dst = lzo_block->dst;
1236 tmp_dst_len = lzo_block->dst_len;
1237
1238 /* prepare the source to be the compressed block */
1239 lzo_block->src = lzo_block->dst;
1240 lzo_block->src_len = lzo_block->dst_len;
1241
1242 /* decompress the block */
1243 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1244 if (ret >= 0) {
1245 /* fetch the value from the cache */
1246 switch (codec->driver->reg_word_size) {
1247 case 1: {
1248 u8 *cache;
1249 cache = lzo_block->dst;
1250 *value = cache[blkpos];
1251 }
1252 break;
1253 case 2: {
1254 u16 *cache;
1255 cache = lzo_block->dst;
1256 *value = cache[blkpos];
1257 }
1258 break;
1259 default:
1260 BUG();
1261 }
1262 }
1263
1264 kfree(lzo_block->dst);
1265 /* restore the pointer and length of the compressed block */
1266 lzo_block->dst = tmp_dst;
1267 lzo_block->dst_len = tmp_dst_len;
1268 return 0;
1269}
1270
1271static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
1272{
1273 struct snd_soc_lzo_ctx **lzo_blocks;
1274 int i, blkcount;
1275
1276 lzo_blocks = codec->reg_cache;
1277 if (!lzo_blocks)
1278 return 0;
1279
1280 blkcount = snd_soc_lzo_block_count();
1281 /*
1282 * the pointer to the bitmap used for syncing the cache
1283 * is shared amongst all lzo_blocks. Ensure it is freed
1284 * only once.
1285 */
1286 if (lzo_blocks[0])
1287 kfree(lzo_blocks[0]->sync_bmp);
1288 for (i = 0; i < blkcount; ++i) {
1289 if (lzo_blocks[i]) {
1290 kfree(lzo_blocks[i]->wmem);
1291 kfree(lzo_blocks[i]->dst);
1292 }
1293 /* each lzo_block is a pointer returned by kmalloc or NULL */
1294 kfree(lzo_blocks[i]);
1295 }
1296 kfree(lzo_blocks);
1297 codec->reg_cache = NULL;
1298 return 0;
1299}
1300
1301static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1302{
1303 struct snd_soc_lzo_ctx **lzo_blocks;
1304 size_t reg_size, bmp_size;
1305 const struct snd_soc_codec_driver *codec_drv;
1306 int ret, tofree, i, blksize, blkcount;
1307 const char *p, *end;
1308 unsigned long *sync_bmp;
1309
1310 ret = 0;
1311 codec_drv = codec->driver;
1312 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1313
1314 /*
1315 * If we have not been given a default register cache
1316 * then allocate a dummy zero-ed out region, compress it
1317 * and remember to free it afterwards.
1318 */
1319 tofree = 0;
1320 if (!codec->reg_def_copy)
1321 tofree = 1;
1322
1323 if (!codec->reg_def_copy) {
1324 codec->reg_def_copy = kzalloc(reg_size,
1325 GFP_KERNEL);
1326 if (!codec->reg_def_copy)
1327 return -ENOMEM;
1328 }
1329
1330 blkcount = snd_soc_lzo_block_count();
1331 codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
1332 GFP_KERNEL);
1333 if (!codec->reg_cache) {
1334 ret = -ENOMEM;
1335 goto err_tofree;
1336 }
1337 lzo_blocks = codec->reg_cache;
1338
1339 /*
1340 * allocate a bitmap to be used when syncing the cache with
1341 * the hardware. Each time a register is modified, the corresponding
1342 * bit is set in the bitmap, so we know that we have to sync
1343 * that register.
1344 */
1345 bmp_size = codec_drv->reg_cache_size;
1346 sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
1347 GFP_KERNEL);
1348 if (!sync_bmp) {
1349 ret = -ENOMEM;
1350 goto err;
1351 }
1352 bitmap_zero(sync_bmp, bmp_size);
1353
1354 /* allocate the lzo blocks and initialize them */
1355 for (i = 0; i < blkcount; ++i) {
1356 lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
1357 GFP_KERNEL);
1358 if (!lzo_blocks[i]) {
1359 kfree(sync_bmp);
1360 ret = -ENOMEM;
1361 goto err;
1362 }
1363 lzo_blocks[i]->sync_bmp = sync_bmp;
1364 lzo_blocks[i]->sync_bmp_nbits = bmp_size;
1365 /* alloc the working space for the compressed block */
1366 ret = snd_soc_lzo_prepare(lzo_blocks[i]);
1367 if (ret < 0)
1368 goto err;
1369 }
1370
1371 blksize = snd_soc_lzo_get_blksize(codec);
1372 p = codec->reg_def_copy;
1373 end = codec->reg_def_copy + reg_size;
1374 /* compress the register map and fill the lzo blocks */
1375 for (i = 0; i < blkcount; ++i, p += blksize) {
1376 lzo_blocks[i]->src = p;
1377 if (p + blksize > end)
1378 lzo_blocks[i]->src_len = end - p;
1379 else
1380 lzo_blocks[i]->src_len = blksize;
1381 ret = snd_soc_lzo_compress_cache_block(codec,
1382 lzo_blocks[i]);
1383 if (ret < 0)
1384 goto err;
1385 lzo_blocks[i]->decompressed_size =
1386 lzo_blocks[i]->src_len;
1387 }
1388
1389 if (tofree) {
1390 kfree(codec->reg_def_copy);
1391 codec->reg_def_copy = NULL;
1392 }
1393 return 0;
1394err:
1395 snd_soc_cache_exit(codec);
1396err_tofree:
1397 if (tofree) {
1398 kfree(codec->reg_def_copy);
1399 codec->reg_def_copy = NULL;
1400 }
1401 return ret;
1402}
1403#endif
1404
1405static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1406{
1407 int i;
1408 int ret;
1409 const struct snd_soc_codec_driver *codec_drv;
1410 unsigned int val;
1411
1412 codec_drv = codec->driver;
1413 for (i = 0; i < codec_drv->reg_cache_size; ++i) {
1414 ret = snd_soc_cache_read(codec, i, &val);
1415 if (ret)
1416 return ret;
1417 if (codec_drv->reg_cache_default) {
1418 switch (codec_drv->reg_word_size) {
1419 case 1: {
1420 const u8 *cache;
1421
1422 cache = codec_drv->reg_cache_default;
1423 if (cache[i] == val)
1424 continue;
1425 }
1426 break;
1427 case 2: {
1428 const u16 *cache;
1429
1430 cache = codec_drv->reg_cache_default;
1431 if (cache[i] == val)
1432 continue;
1433 }
1434 break;
1435 default:
1436 BUG();
1437 }
1438 }
1439 ret = snd_soc_write(codec, i, val);
1440 if (ret)
1441 return ret;
1442 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
1443 i, val);
1444 }
1445 return 0;
1446}
1447
1448static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1449 unsigned int reg, unsigned int value)
1450{
1451 switch (codec->driver->reg_word_size) {
1452 case 1: {
1453 u8 *cache;
1454
1455 cache = codec->reg_cache;
1456 cache[reg] = value;
1457 }
1458 break;
1459 case 2: {
1460 u16 *cache;
1461
1462 cache = codec->reg_cache;
1463 cache[reg] = value;
1464 }
1465 break;
1466 default:
1467 BUG();
1468 }
1469
1470 return 0;
1471}
1472
1473static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1474 unsigned int reg, unsigned int *value)
1475{
1476 switch (codec->driver->reg_word_size) {
1477 case 1: {
1478 u8 *cache;
1479
1480 cache = codec->reg_cache;
1481 *value = cache[reg];
1482 }
1483 break;
1484 case 2: {
1485 u16 *cache;
1486
1487 cache = codec->reg_cache;
1488 *value = cache[reg];
1489 }
1490 break;
1491 default:
1492 BUG();
1493 }
1494
1495 return 0;
1496}
1497
1498static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
1499{
1500 if (!codec->reg_cache)
1501 return 0;
1502 kfree(codec->reg_cache);
1503 codec->reg_cache = NULL;
1504 return 0;
1505}
1506
1507static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1508{
1509 const struct snd_soc_codec_driver *codec_drv;
1510 size_t reg_size;
1511
1512 codec_drv = codec->driver;
1513 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1514
1515 /*
1516 * for flat compression, we don't need to keep a copy of the
1517 * original defaults register cache as it will definitely not
1518 * be marked as __devinitconst
1519 */
1520 kfree(codec->reg_def_copy);
1521 codec->reg_def_copy = NULL;
1522
1523 if (codec_drv->reg_cache_default)
1524 codec->reg_cache = kmemdup(codec_drv->reg_cache_default,
1525 reg_size, GFP_KERNEL);
1526 else
1527 codec->reg_cache = kzalloc(reg_size, GFP_KERNEL);
1528 if (!codec->reg_cache)
1529 return -ENOMEM;
1530
1531 return 0;
1532}
1533
1534/* an array of all supported compression types */
1535static const struct snd_soc_cache_ops cache_types[] = {
1536 /* Flat *must* be the first entry for fallback */
1537 {
1538 .id = SND_SOC_FLAT_COMPRESSION,
1539 .name = "flat",
1540 .init = snd_soc_flat_cache_init,
1541 .exit = snd_soc_flat_cache_exit,
1542 .read = snd_soc_flat_cache_read,
1543 .write = snd_soc_flat_cache_write,
1544 .sync = snd_soc_flat_cache_sync
1545 },
1546#ifdef CONFIG_SND_SOC_CACHE_LZO
1547 {
1548 .id = SND_SOC_LZO_COMPRESSION,
1549 .name = "LZO",
1550 .init = snd_soc_lzo_cache_init,
1551 .exit = snd_soc_lzo_cache_exit,
1552 .read = snd_soc_lzo_cache_read,
1553 .write = snd_soc_lzo_cache_write,
1554 .sync = snd_soc_lzo_cache_sync
1555 },
1556#endif
1557 {
1558 .id = SND_SOC_RBTREE_COMPRESSION,
1559 .name = "rbtree",
1560 .init = snd_soc_rbtree_cache_init,
1561 .exit = snd_soc_rbtree_cache_exit,
1562 .read = snd_soc_rbtree_cache_read,
1563 .write = snd_soc_rbtree_cache_write,
1564 .sync = snd_soc_rbtree_cache_sync
1565 }
1566};
1567
1568int snd_soc_cache_init(struct snd_soc_codec *codec)
1569{
1570 int i;
1571
1572 for (i = 0; i < ARRAY_SIZE(cache_types); ++i)
1573 if (cache_types[i].id == codec->compress_type)
1574 break;
1575
1576 /* Fall back to flat compression */
1577 if (i == ARRAY_SIZE(cache_types)) {
1578 dev_warn(codec->dev, "Could not match compress type: %d\n",
1579 codec->compress_type);
1580 i = 0;
1581 }
1582
1583 mutex_init(&codec->cache_rw_mutex);
1584 codec->cache_ops = &cache_types[i];
1585
1586 if (codec->cache_ops->init) {
1587 if (codec->cache_ops->name)
1588 dev_dbg(codec->dev, "Initializing %s cache for %s codec\n",
1589 codec->cache_ops->name, codec->name);
1590 return codec->cache_ops->init(codec);
1591 }
1592 return -EINVAL;
1593}
1594
1595/*
1596 * NOTE: keep in mind that this function might be called
1597 * multiple times.
1598 */
1599int snd_soc_cache_exit(struct snd_soc_codec *codec)
1600{
1601 if (codec->cache_ops && codec->cache_ops->exit) {
1602 if (codec->cache_ops->name)
1603 dev_dbg(codec->dev, "Destroying %s cache for %s codec\n",
1604 codec->cache_ops->name, codec->name);
1605 return codec->cache_ops->exit(codec);
1606 }
1607 return -EINVAL;
1608}
1609
1610/**
1611 * snd_soc_cache_read: Fetch the value of a given register from the cache.
1612 *
1613 * @codec: CODEC to configure.
1614 * @reg: The register index.
1615 * @value: The value to be returned.
1616 */
1617int snd_soc_cache_read(struct snd_soc_codec *codec,
1618 unsigned int reg, unsigned int *value)
1619{
1620 int ret;
1621
1622 mutex_lock(&codec->cache_rw_mutex);
1623
1624 if (value && codec->cache_ops && codec->cache_ops->read) {
1625 ret = codec->cache_ops->read(codec, reg, value);
1626 mutex_unlock(&codec->cache_rw_mutex);
1627 return ret;
1628 }
1629
1630 mutex_unlock(&codec->cache_rw_mutex);
1631 return -EINVAL;
1632}
1633EXPORT_SYMBOL_GPL(snd_soc_cache_read);
1634
1635/**
1636 * snd_soc_cache_write: Set the value of a given register in the cache.
1637 *
1638 * @codec: CODEC to configure.
1639 * @reg: The register index.
1640 * @value: The new register value.
1641 */
1642int snd_soc_cache_write(struct snd_soc_codec *codec,
1643 unsigned int reg, unsigned int value)
1644{
1645 int ret;
1646
1647 mutex_lock(&codec->cache_rw_mutex);
1648
1649 if (codec->cache_ops && codec->cache_ops->write) {
1650 ret = codec->cache_ops->write(codec, reg, value);
1651 mutex_unlock(&codec->cache_rw_mutex);
1652 return ret;
1653 }
1654
1655 mutex_unlock(&codec->cache_rw_mutex);
1656 return -EINVAL;
1657}
1658EXPORT_SYMBOL_GPL(snd_soc_cache_write);
1659
1660/**
1661 * snd_soc_cache_sync: Sync the register cache with the hardware.
1662 *
1663 * @codec: CODEC to configure.
1664 *
1665 * Any registers that should not be synced should be marked as
1666 * volatile. In general drivers can choose not to use the provided
1667 * syncing functionality if they so require.
1668 */
1669int snd_soc_cache_sync(struct snd_soc_codec *codec)
1670{
1671 int ret;
1672
1673 if (!codec->cache_sync) {
1674 return 0;
1675 }
1676
1677 if (codec->cache_ops && codec->cache_ops->sync) {
1678 if (codec->cache_ops->name)
1679 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
1680 codec->cache_ops->name, codec->name);
1681 ret = codec->cache_ops->sync(codec);
1682 if (!ret)
1683 codec->cache_sync = 0;
1684 return ret;
1685 }
1686
1687 return -EINVAL;
1688}
1689EXPORT_SYMBOL_GPL(snd_soc_cache_sync);