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.c386
1 files changed, 188 insertions, 198 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 8c2a21a978ac..5d76da43b14c 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -18,6 +18,8 @@
18#include <linux/bitmap.h> 18#include <linux/bitmap.h>
19#include <linux/rbtree.h> 19#include <linux/rbtree.h>
20 20
21#include <trace/events/asoc.h>
22
21static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec, 23static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
22 unsigned int reg) 24 unsigned int reg)
23{ 25{
@@ -25,7 +27,8 @@ static unsigned int snd_soc_4_12_read(struct snd_soc_codec *codec,
25 unsigned int val; 27 unsigned int val;
26 28
27 if (reg >= codec->driver->reg_cache_size || 29 if (reg >= codec->driver->reg_cache_size ||
28 snd_soc_codec_volatile_register(codec, reg)) { 30 snd_soc_codec_volatile_register(codec, reg) ||
31 codec->cache_bypass) {
29 if (codec->cache_only) 32 if (codec->cache_only)
30 return -1; 33 return -1;
31 34
@@ -49,7 +52,8 @@ static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
49 data[1] = value & 0x00ff; 52 data[1] = value & 0x00ff;
50 53
51 if (!snd_soc_codec_volatile_register(codec, reg) && 54 if (!snd_soc_codec_volatile_register(codec, reg) &&
52 reg < codec->driver->reg_cache_size) { 55 reg < codec->driver->reg_cache_size &&
56 !codec->cache_bypass) {
53 ret = snd_soc_cache_write(codec, reg, value); 57 ret = snd_soc_cache_write(codec, reg, value);
54 if (ret < 0) 58 if (ret < 0)
55 return -1; 59 return -1;
@@ -106,7 +110,8 @@ static unsigned int snd_soc_7_9_read(struct snd_soc_codec *codec,
106 unsigned int val; 110 unsigned int val;
107 111
108 if (reg >= codec->driver->reg_cache_size || 112 if (reg >= codec->driver->reg_cache_size ||
109 snd_soc_codec_volatile_register(codec, reg)) { 113 snd_soc_codec_volatile_register(codec, reg) ||
114 codec->cache_bypass) {
110 if (codec->cache_only) 115 if (codec->cache_only)
111 return -1; 116 return -1;
112 117
@@ -130,7 +135,8 @@ static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
130 data[1] = value & 0x00ff; 135 data[1] = value & 0x00ff;
131 136
132 if (!snd_soc_codec_volatile_register(codec, reg) && 137 if (!snd_soc_codec_volatile_register(codec, reg) &&
133 reg < codec->driver->reg_cache_size) { 138 reg < codec->driver->reg_cache_size &&
139 !codec->cache_bypass) {
134 ret = snd_soc_cache_write(codec, reg, value); 140 ret = snd_soc_cache_write(codec, reg, value);
135 if (ret < 0) 141 if (ret < 0)
136 return -1; 142 return -1;
@@ -191,7 +197,8 @@ static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
191 data[1] = value & 0xff; 197 data[1] = value & 0xff;
192 198
193 if (!snd_soc_codec_volatile_register(codec, reg) && 199 if (!snd_soc_codec_volatile_register(codec, reg) &&
194 reg < codec->driver->reg_cache_size) { 200 reg < codec->driver->reg_cache_size &&
201 !codec->cache_bypass) {
195 ret = snd_soc_cache_write(codec, reg, value); 202 ret = snd_soc_cache_write(codec, reg, value);
196 if (ret < 0) 203 if (ret < 0)
197 return -1; 204 return -1;
@@ -216,7 +223,8 @@ static unsigned int snd_soc_8_8_read(struct snd_soc_codec *codec,
216 223
217 reg &= 0xff; 224 reg &= 0xff;
218 if (reg >= codec->driver->reg_cache_size || 225 if (reg >= codec->driver->reg_cache_size ||
219 snd_soc_codec_volatile_register(codec, reg)) { 226 snd_soc_codec_volatile_register(codec, reg) ||
227 codec->cache_bypass) {
220 if (codec->cache_only) 228 if (codec->cache_only)
221 return -1; 229 return -1;
222 230
@@ -271,7 +279,8 @@ static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
271 data[2] = value & 0xff; 279 data[2] = value & 0xff;
272 280
273 if (!snd_soc_codec_volatile_register(codec, reg) && 281 if (!snd_soc_codec_volatile_register(codec, reg) &&
274 reg < codec->driver->reg_cache_size) { 282 reg < codec->driver->reg_cache_size &&
283 !codec->cache_bypass) {
275 ret = snd_soc_cache_write(codec, reg, value); 284 ret = snd_soc_cache_write(codec, reg, value);
276 if (ret < 0) 285 if (ret < 0)
277 return -1; 286 return -1;
@@ -295,7 +304,8 @@ static unsigned int snd_soc_8_16_read(struct snd_soc_codec *codec,
295 unsigned int val; 304 unsigned int val;
296 305
297 if (reg >= codec->driver->reg_cache_size || 306 if (reg >= codec->driver->reg_cache_size ||
298 snd_soc_codec_volatile_register(codec, reg)) { 307 snd_soc_codec_volatile_register(codec, reg) ||
308 codec->cache_bypass) {
299 if (codec->cache_only) 309 if (codec->cache_only)
300 return -1; 310 return -1;
301 311
@@ -450,7 +460,8 @@ static unsigned int snd_soc_16_8_read(struct snd_soc_codec *codec,
450 460
451 reg &= 0xff; 461 reg &= 0xff;
452 if (reg >= codec->driver->reg_cache_size || 462 if (reg >= codec->driver->reg_cache_size ||
453 snd_soc_codec_volatile_register(codec, reg)) { 463 snd_soc_codec_volatile_register(codec, reg) ||
464 codec->cache_bypass) {
454 if (codec->cache_only) 465 if (codec->cache_only)
455 return -1; 466 return -1;
456 467
@@ -476,7 +487,8 @@ static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
476 487
477 reg &= 0xff; 488 reg &= 0xff;
478 if (!snd_soc_codec_volatile_register(codec, reg) && 489 if (!snd_soc_codec_volatile_register(codec, reg) &&
479 reg < codec->driver->reg_cache_size) { 490 reg < codec->driver->reg_cache_size &&
491 !codec->cache_bypass) {
480 ret = snd_soc_cache_write(codec, reg, value); 492 ret = snd_soc_cache_write(codec, reg, value);
481 if (ret < 0) 493 if (ret < 0)
482 return -1; 494 return -1;
@@ -568,7 +580,8 @@ static unsigned int snd_soc_16_16_read(struct snd_soc_codec *codec,
568 unsigned int val; 580 unsigned int val;
569 581
570 if (reg >= codec->driver->reg_cache_size || 582 if (reg >= codec->driver->reg_cache_size ||
571 snd_soc_codec_volatile_register(codec, reg)) { 583 snd_soc_codec_volatile_register(codec, reg) ||
584 codec->cache_bypass) {
572 if (codec->cache_only) 585 if (codec->cache_only)
573 return -1; 586 return -1;
574 587
@@ -595,7 +608,8 @@ static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
595 data[3] = value & 0xff; 608 data[3] = value & 0xff;
596 609
597 if (!snd_soc_codec_volatile_register(codec, reg) && 610 if (!snd_soc_codec_volatile_register(codec, reg) &&
598 reg < codec->driver->reg_cache_size) { 611 reg < codec->driver->reg_cache_size &&
612 !codec->cache_bypass) {
599 ret = snd_soc_cache_write(codec, reg, value); 613 ret = snd_soc_cache_write(codec, reg, value);
600 if (ret < 0) 614 if (ret < 0)
601 return -1; 615 return -1;
@@ -761,6 +775,49 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
761} 775}
762EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 776EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
763 777
778static bool snd_soc_set_cache_val(void *base, unsigned int idx,
779 unsigned int val, unsigned int word_size)
780{
781 switch (word_size) {
782 case 1: {
783 u8 *cache = base;
784 if (cache[idx] == val)
785 return true;
786 cache[idx] = val;
787 break;
788 }
789 case 2: {
790 u16 *cache = base;
791 if (cache[idx] == val)
792 return true;
793 cache[idx] = val;
794 break;
795 }
796 default:
797 BUG();
798 }
799 return false;
800}
801
802static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
803 unsigned int word_size)
804{
805 switch (word_size) {
806 case 1: {
807 const u8 *cache = base;
808 return cache[idx];
809 }
810 case 2: {
811 const u16 *cache = base;
812 return cache[idx];
813 }
814 default:
815 BUG();
816 }
817 /* unreachable */
818 return -1;
819}
820
764struct snd_soc_rbtree_node { 821struct snd_soc_rbtree_node {
765 struct rb_node node; 822 struct rb_node node;
766 unsigned int reg; 823 unsigned int reg;
@@ -835,7 +892,9 @@ static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
835 ret = snd_soc_cache_read(codec, rbnode->reg, &val); 892 ret = snd_soc_cache_read(codec, rbnode->reg, &val);
836 if (ret) 893 if (ret)
837 return ret; 894 return ret;
895 codec->cache_bypass = 1;
838 ret = snd_soc_write(codec, rbnode->reg, val); 896 ret = snd_soc_write(codec, rbnode->reg, val);
897 codec->cache_bypass = 0;
839 if (ret) 898 if (ret)
840 return ret; 899 return ret;
841 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", 900 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -924,7 +983,12 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
924 983
925static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) 984static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
926{ 985{
986 struct snd_soc_rbtree_node *rbtree_node;
927 struct snd_soc_rbtree_ctx *rbtree_ctx; 987 struct snd_soc_rbtree_ctx *rbtree_ctx;
988 unsigned int val;
989 unsigned int word_size;
990 int i;
991 int ret;
928 992
929 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL); 993 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
930 if (!codec->reg_cache) 994 if (!codec->reg_cache)
@@ -936,53 +1000,25 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
936 if (!codec->reg_def_copy) 1000 if (!codec->reg_def_copy)
937 return 0; 1001 return 0;
938 1002
939/* 1003 /*
940 * populate the rbtree with the initialized registers. All other 1004 * populate the rbtree with the initialized registers. All other
941 * registers will be inserted into the tree when they are first written. 1005 * registers will be inserted when they are first modified.
942 * 1006 */
943 * The reasoning behind this, is that we need to step through and 1007 word_size = codec->driver->reg_word_size;
944 * dereference the cache in u8/u16 increments without sacrificing 1008 for (i = 0; i < codec->driver->reg_cache_size; ++i) {
945 * portability. This could also be done using memcpy() but that would 1009 val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
946 * be slightly more cryptic. 1010 if (!val)
947 */ 1011 continue;
948#define snd_soc_rbtree_populate(cache) \ 1012 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
949({ \ 1013 if (!rbtree_node) {
950 int ret, i; \ 1014 ret = -ENOMEM;
951 struct snd_soc_rbtree_node *rbtree_node; \ 1015 snd_soc_cache_exit(codec);
952 \ 1016 break;
953 ret = 0; \ 1017 }
954 cache = codec->reg_def_copy; \ 1018 rbtree_node->reg = i;
955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \ 1019 rbtree_node->value = val;
956 if (!cache[i]) \ 1020 rbtree_node->defval = val;
957 continue; \ 1021 snd_soc_rbtree_insert(&rbtree_ctx->root, rbtree_node);
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 } 1022 }
987 1023
988 return 0; 1024 return 0;
@@ -1080,34 +1116,28 @@ static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
1080 unsigned int reg) 1116 unsigned int reg)
1081{ 1117{
1082 const struct snd_soc_codec_driver *codec_drv; 1118 const struct snd_soc_codec_driver *codec_drv;
1083 size_t reg_size;
1084 1119
1085 codec_drv = codec->driver; 1120 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) / 1121 return (reg * codec_drv->reg_word_size) /
1088 DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()); 1122 DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
1089} 1123}
1090 1124
1091static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec, 1125static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
1092 unsigned int reg) 1126 unsigned int reg)
1093{ 1127{
1094 const struct snd_soc_codec_driver *codec_drv; 1128 const struct snd_soc_codec_driver *codec_drv;
1095 size_t reg_size;
1096 1129
1097 codec_drv = codec->driver; 1130 codec_drv = codec->driver;
1098 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 1131 return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
1099 return reg % (DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count()) /
1100 codec_drv->reg_word_size); 1132 codec_drv->reg_word_size);
1101} 1133}
1102 1134
1103static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec) 1135static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
1104{ 1136{
1105 const struct snd_soc_codec_driver *codec_drv; 1137 const struct snd_soc_codec_driver *codec_drv;
1106 size_t reg_size;
1107 1138
1108 codec_drv = codec->driver; 1139 codec_drv = codec->driver;
1109 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; 1140 return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
1110 return DIV_ROUND_UP(reg_size, snd_soc_lzo_block_count());
1111} 1141}
1112 1142
1113static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec) 1143static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
@@ -1122,7 +1152,9 @@ static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
1122 ret = snd_soc_cache_read(codec, i, &val); 1152 ret = snd_soc_cache_read(codec, i, &val);
1123 if (ret) 1153 if (ret)
1124 return ret; 1154 return ret;
1155 codec->cache_bypass = 1;
1125 ret = snd_soc_write(codec, i, val); 1156 ret = snd_soc_write(codec, i, val);
1157 codec->cache_bypass = 0;
1126 if (ret) 1158 if (ret)
1127 return ret; 1159 return ret;
1128 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n", 1160 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
@@ -1165,29 +1197,10 @@ static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
1165 } 1197 }
1166 1198
1167 /* write the new value to the cache */ 1199 /* write the new value to the cache */
1168 switch (codec->driver->reg_word_size) { 1200 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
1169 case 1: { 1201 codec->driver->reg_word_size)) {
1170 u8 *cache; 1202 kfree(lzo_block->dst);
1171 cache = lzo_block->dst; 1203 goto out;
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 } 1204 }
1192 1205
1193 /* prepare the source to be the decompressed block */ 1206 /* prepare the source to be the decompressed block */
@@ -1241,25 +1254,10 @@ static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1241 1254
1242 /* decompress the block */ 1255 /* decompress the block */
1243 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block); 1256 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1244 if (ret >= 0) { 1257 if (ret >= 0)
1245 /* fetch the value from the cache */ 1258 /* fetch the value from the cache */
1246 switch (codec->driver->reg_word_size) { 1259 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
1247 case 1: { 1260 codec->driver->reg_word_size);
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 1261
1264 kfree(lzo_block->dst); 1262 kfree(lzo_block->dst);
1265 /* restore the pointer and length of the compressed block */ 1263 /* restore the pointer and length of the compressed block */
@@ -1301,7 +1299,7 @@ static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
1301static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec) 1299static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1302{ 1300{
1303 struct snd_soc_lzo_ctx **lzo_blocks; 1301 struct snd_soc_lzo_ctx **lzo_blocks;
1304 size_t reg_size, bmp_size; 1302 size_t bmp_size;
1305 const struct snd_soc_codec_driver *codec_drv; 1303 const struct snd_soc_codec_driver *codec_drv;
1306 int ret, tofree, i, blksize, blkcount; 1304 int ret, tofree, i, blksize, blkcount;
1307 const char *p, *end; 1305 const char *p, *end;
@@ -1309,7 +1307,6 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1309 1307
1310 ret = 0; 1308 ret = 0;
1311 codec_drv = codec->driver; 1309 codec_drv = codec->driver;
1312 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1313 1310
1314 /* 1311 /*
1315 * If we have not been given a default register cache 1312 * If we have not been given a default register cache
@@ -1321,8 +1318,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1321 tofree = 1; 1318 tofree = 1;
1322 1319
1323 if (!codec->reg_def_copy) { 1320 if (!codec->reg_def_copy) {
1324 codec->reg_def_copy = kzalloc(reg_size, 1321 codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
1325 GFP_KERNEL);
1326 if (!codec->reg_def_copy) 1322 if (!codec->reg_def_copy)
1327 return -ENOMEM; 1323 return -ENOMEM;
1328 } 1324 }
@@ -1370,7 +1366,7 @@ static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
1370 1366
1371 blksize = snd_soc_lzo_get_blksize(codec); 1367 blksize = snd_soc_lzo_get_blksize(codec);
1372 p = codec->reg_def_copy; 1368 p = codec->reg_def_copy;
1373 end = codec->reg_def_copy + reg_size; 1369 end = codec->reg_def_copy + codec->reg_size;
1374 /* compress the register map and fill the lzo blocks */ 1370 /* compress the register map and fill the lzo blocks */
1375 for (i = 0; i < blkcount; ++i, p += blksize) { 1371 for (i = 0; i < blkcount; ++i, p += blksize) {
1376 lzo_blocks[i]->src = p; 1372 lzo_blocks[i]->src = p;
@@ -1414,28 +1410,10 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1414 ret = snd_soc_cache_read(codec, i, &val); 1410 ret = snd_soc_cache_read(codec, i, &val);
1415 if (ret) 1411 if (ret)
1416 return ret; 1412 return ret;
1417 if (codec_drv->reg_cache_default) { 1413 if (codec->reg_def_copy)
1418 switch (codec_drv->reg_word_size) { 1414 if (snd_soc_get_cache_val(codec->reg_def_copy,
1419 case 1: { 1415 i, codec_drv->reg_word_size) == val)
1420 const u8 *cache; 1416 continue;
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); 1417 ret = snd_soc_write(codec, i, val);
1440 if (ret) 1418 if (ret)
1441 return ret; 1419 return ret;
@@ -1448,50 +1426,16 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1448static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, 1426static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1449 unsigned int reg, unsigned int value) 1427 unsigned int reg, unsigned int value)
1450{ 1428{
1451 switch (codec->driver->reg_word_size) { 1429 snd_soc_set_cache_val(codec->reg_cache, reg, value,
1452 case 1: { 1430 codec->driver->reg_word_size);
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; 1431 return 0;
1471} 1432}
1472 1433
1473static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, 1434static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1474 unsigned int reg, unsigned int *value) 1435 unsigned int reg, unsigned int *value)
1475{ 1436{
1476 switch (codec->driver->reg_word_size) { 1437 *value = snd_soc_get_cache_val(codec->reg_cache, reg,
1477 case 1: { 1438 codec->driver->reg_word_size);
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; 1439 return 0;
1496} 1440}
1497 1441
@@ -1507,24 +1451,14 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
1507static int snd_soc_flat_cache_init(struct snd_soc_codec *codec) 1451static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
1508{ 1452{
1509 const struct snd_soc_codec_driver *codec_drv; 1453 const struct snd_soc_codec_driver *codec_drv;
1510 size_t reg_size;
1511 1454
1512 codec_drv = codec->driver; 1455 codec_drv = codec->driver;
1513 reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size;
1514 1456
1515 /* 1457 if (codec->reg_def_copy)
1516 * for flat compression, we don't need to keep a copy of the 1458 codec->reg_cache = kmemdup(codec->reg_def_copy,
1517 * original defaults register cache as it will definitely not 1459 codec->reg_size, GFP_KERNEL);
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 1460 else
1527 codec->reg_cache = kzalloc(reg_size, GFP_KERNEL); 1461 codec->reg_cache = kzalloc(codec->reg_size, GFP_KERNEL);
1528 if (!codec->reg_cache) 1462 if (!codec->reg_cache)
1529 return -ENOMEM; 1463 return -ENOMEM;
1530 1464
@@ -1669,21 +1603,77 @@ EXPORT_SYMBOL_GPL(snd_soc_cache_write);
1669int snd_soc_cache_sync(struct snd_soc_codec *codec) 1603int snd_soc_cache_sync(struct snd_soc_codec *codec)
1670{ 1604{
1671 int ret; 1605 int ret;
1606 const char *name;
1672 1607
1673 if (!codec->cache_sync) { 1608 if (!codec->cache_sync) {
1674 return 0; 1609 return 0;
1675 } 1610 }
1676 1611
1677 if (codec->cache_ops && codec->cache_ops->sync) { 1612 if (!codec->cache_ops || !codec->cache_ops->sync)
1678 if (codec->cache_ops->name) 1613 return -EINVAL;
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 1614
1687 return -EINVAL; 1615 if (codec->cache_ops->name)
1616 name = codec->cache_ops->name;
1617 else
1618 name = "unknown";
1619
1620 if (codec->cache_ops->name)
1621 dev_dbg(codec->dev, "Syncing %s cache for %s codec\n",
1622 codec->cache_ops->name, codec->name);
1623 trace_snd_soc_cache_sync(codec, name, "start");
1624 ret = codec->cache_ops->sync(codec);
1625 if (!ret)
1626 codec->cache_sync = 0;
1627 trace_snd_soc_cache_sync(codec, name, "end");
1628 return ret;
1688} 1629}
1689EXPORT_SYMBOL_GPL(snd_soc_cache_sync); 1630EXPORT_SYMBOL_GPL(snd_soc_cache_sync);
1631
1632static int snd_soc_get_reg_access_index(struct snd_soc_codec *codec,
1633 unsigned int reg)
1634{
1635 const struct snd_soc_codec_driver *codec_drv;
1636 unsigned int min, max, index;
1637
1638 codec_drv = codec->driver;
1639 min = 0;
1640 max = codec_drv->reg_access_size - 1;
1641 do {
1642 index = (min + max) / 2;
1643 if (codec_drv->reg_access_default[index].reg == reg)
1644 return index;
1645 if (codec_drv->reg_access_default[index].reg < reg)
1646 min = index + 1;
1647 else
1648 max = index;
1649 } while (min <= max);
1650 return -1;
1651}
1652
1653int snd_soc_default_volatile_register(struct snd_soc_codec *codec,
1654 unsigned int reg)
1655{
1656 int index;
1657
1658 if (reg >= codec->driver->reg_cache_size)
1659 return 1;
1660 index = snd_soc_get_reg_access_index(codec, reg);
1661 if (index < 0)
1662 return 0;
1663 return codec->driver->reg_access_default[index].vol;
1664}
1665EXPORT_SYMBOL_GPL(snd_soc_default_volatile_register);
1666
1667int snd_soc_default_readable_register(struct snd_soc_codec *codec,
1668 unsigned int reg)
1669{
1670 int index;
1671
1672 if (reg >= codec->driver->reg_cache_size)
1673 return 1;
1674 index = snd_soc_get_reg_access_index(codec, reg);
1675 if (index < 0)
1676 return 0;
1677 return codec->driver->reg_access_default[index].read;
1678}
1679EXPORT_SYMBOL_GPL(snd_soc_default_readable_register);