aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/soc-cache.c230
1 files changed, 82 insertions, 148 deletions
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index a9ebc078bea8..9e534429ea63 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -761,6 +761,49 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
761} 761}
762EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); 762EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
763 763
764static bool snd_soc_set_cache_val(void *base, unsigned int idx,
765 unsigned int val, unsigned int word_size)
766{
767 switch (word_size) {
768 case 1: {
769 u8 *cache = base;
770 if (cache[idx] == val)
771 return true;
772 cache[idx] = val;
773 break;
774 }
775 case 2: {
776 u16 *cache = base;
777 if (cache[idx] == val)
778 return true;
779 cache[idx] = val;
780 break;
781 }
782 default:
783 BUG();
784 }
785 return false;
786}
787
788static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
789 unsigned int word_size)
790{
791 switch (word_size) {
792 case 1: {
793 const u8 *cache = base;
794 return cache[idx];
795 }
796 case 2: {
797 const u16 *cache = base;
798 return cache[idx];
799 }
800 default:
801 BUG();
802 }
803 /* unreachable */
804 return -1;
805}
806
764struct snd_soc_rbtree_node { 807struct snd_soc_rbtree_node {
765 struct rb_node node; 808 struct rb_node node;
766 unsigned int reg; 809 unsigned int reg;
@@ -924,7 +967,12 @@ static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
924 967
925static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) 968static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
926{ 969{
970 struct snd_soc_rbtree_node *rbtree_node;
927 struct snd_soc_rbtree_ctx *rbtree_ctx; 971 struct snd_soc_rbtree_ctx *rbtree_ctx;
972 unsigned int val;
973 unsigned int word_size;
974 int i;
975 int ret;
928 976
929 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL); 977 codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
930 if (!codec->reg_cache) 978 if (!codec->reg_cache)
@@ -936,53 +984,25 @@ static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
936 if (!codec->reg_def_copy) 984 if (!codec->reg_def_copy)
937 return 0; 985 return 0;
938 986
939/* 987 /*
940 * populate the rbtree with the initialized registers. All other 988 * populate the rbtree with the initialized registers. All other
941 * registers will be inserted into the tree when they are first written. 989 * registers will be inserted when they are first modified.
942 * 990 */
943 * The reasoning behind this, is that we need to step through and 991 word_size = codec->driver->reg_word_size;
944 * dereference the cache in u8/u16 increments without sacrificing 992 for (i = 0; i < codec->driver->reg_cache_size; ++i) {
945 * portability. This could also be done using memcpy() but that would 993 val = snd_soc_get_cache_val(codec->reg_def_copy, i, word_size);
946 * be slightly more cryptic. 994 if (!val)
947 */ 995 continue;
948#define snd_soc_rbtree_populate(cache) \ 996 rbtree_node = kzalloc(sizeof *rbtree_node, GFP_KERNEL);
949({ \ 997 if (!rbtree_node) {
950 int ret, i; \ 998 ret = -ENOMEM;
951 struct snd_soc_rbtree_node *rbtree_node; \ 999 snd_soc_cache_exit(codec);
952 \ 1000 break;
953 ret = 0; \ 1001 }
954 cache = codec->reg_def_copy; \ 1002 rbtree_node->reg = i;
955 for (i = 0; i < codec->driver->reg_cache_size; ++i) { \ 1003 rbtree_node->value = val;
956 if (!cache[i]) \ 1004 rbtree_node->defval = val;
957 continue; \ 1005 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 } 1006 }
987 1007
988 return 0; 1008 return 0;
@@ -1165,29 +1185,10 @@ static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
1165 } 1185 }
1166 1186
1167 /* write the new value to the cache */ 1187 /* write the new value to the cache */
1168 switch (codec->driver->reg_word_size) { 1188 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
1169 case 1: { 1189 codec->driver->reg_word_size)) {
1170 u8 *cache; 1190 kfree(lzo_block->dst);
1171 cache = lzo_block->dst; 1191 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 } 1192 }
1192 1193
1193 /* prepare the source to be the decompressed block */ 1194 /* prepare the source to be the decompressed block */
@@ -1241,25 +1242,10 @@ static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
1241 1242
1242 /* decompress the block */ 1243 /* decompress the block */
1243 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block); 1244 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
1244 if (ret >= 0) { 1245 if (ret >= 0)
1245 /* fetch the value from the cache */ 1246 /* fetch the value from the cache */
1246 switch (codec->driver->reg_word_size) { 1247 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
1247 case 1: { 1248 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 1249
1264 kfree(lzo_block->dst); 1250 kfree(lzo_block->dst);
1265 /* restore the pointer and length of the compressed block */ 1251 /* restore the pointer and length of the compressed block */
@@ -1414,28 +1400,10 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
1414 ret = snd_soc_cache_read(codec, i, &val); 1400 ret = snd_soc_cache_read(codec, i, &val);
1415 if (ret) 1401 if (ret)
1416 return ret; 1402 return ret;
1417 if (codec_drv->reg_cache_default) { 1403 if (codec_drv->reg_cache_default)
1418 switch (codec_drv->reg_word_size) { 1404 if (snd_soc_get_cache_val(codec_drv->reg_cache_default,
1419 case 1: { 1405 i, codec_drv->reg_word_size) == val)
1420 const u8 *cache; 1406 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); 1407 ret = snd_soc_write(codec, i, val);
1440 if (ret) 1408 if (ret)
1441 return ret; 1409 return ret;
@@ -1448,50 +1416,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, 1416static int snd_soc_flat_cache_write(struct snd_soc_codec *codec,
1449 unsigned int reg, unsigned int value) 1417 unsigned int reg, unsigned int value)
1450{ 1418{
1451 switch (codec->driver->reg_word_size) { 1419 snd_soc_set_cache_val(codec->reg_cache, reg, value,
1452 case 1: { 1420 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; 1421 return 0;
1471} 1422}
1472 1423
1473static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, 1424static int snd_soc_flat_cache_read(struct snd_soc_codec *codec,
1474 unsigned int reg, unsigned int *value) 1425 unsigned int reg, unsigned int *value)
1475{ 1426{
1476 switch (codec->driver->reg_word_size) { 1427 *value = snd_soc_get_cache_val(codec->reg_cache, reg,
1477 case 1: { 1428 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; 1429 return 0;
1496} 1430}
1497 1431