diff options
-rw-r--r-- | sound/soc/soc-cache.c | 230 |
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 | } |
762 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); | 762 | EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io); |
763 | 763 | ||
764 | static 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 | |||
788 | static 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 | |||
764 | struct snd_soc_rbtree_node { | 807 | struct 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 | ||
925 | static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec) | 968 | static 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) | |||
1448 | static int snd_soc_flat_cache_write(struct snd_soc_codec *codec, | 1416 | static 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 | ||
1473 | static int snd_soc_flat_cache_read(struct snd_soc_codec *codec, | 1424 | static 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 | ||