aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h1
-rw-r--r--sound/soc/Kconfig15
-rw-r--r--sound/soc/soc-cache.c384
3 files changed, 0 insertions, 400 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 02a5c5519f3..b21b3047e91 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -266,7 +266,6 @@ enum snd_soc_control_type {
266 266
267enum snd_soc_compress_type { 267enum snd_soc_compress_type {
268 SND_SOC_FLAT_COMPRESSION = 1, 268 SND_SOC_FLAT_COMPRESSION = 1,
269 SND_SOC_LZO_COMPRESSION,
270 SND_SOC_RBTREE_COMPRESSION 269 SND_SOC_RBTREE_COMPRESSION
271}; 270};
272 271
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 1381db853ef..35e662d270e 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -22,21 +22,6 @@ menuconfig SND_SOC
22 22
23if SND_SOC 23if SND_SOC
24 24
25config SND_SOC_CACHE_LZO
26 bool "Support LZO compression for register caches"
27 select LZO_COMPRESS
28 select LZO_DECOMPRESS
29 ---help---
30 Select this to enable LZO compression for register caches.
31 This will allow machine or CODEC drivers to compress register
32 caches in memory, reducing the memory consumption at the
33 expense of performance. If this is not present and is used
34 the system will fall back to uncompressed caches.
35
36 Usually it is safe to disable this option, where cache
37 compression in used the rbtree option will typically perform
38 better.
39
40config SND_SOC_AC97_BUS 25config SND_SOC_AC97_BUS
41 bool 26 bool
42 27
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index 9077aa4b3b4..18bb6b3335e 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -14,7 +14,6 @@
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> 17#include <linux/bitmap.h>
19#include <linux/rbtree.h> 18#include <linux/rbtree.h>
20#include <linux/export.h> 19#include <linux/export.h>
@@ -439,378 +438,6 @@ err:
439 return ret; 438 return ret;
440} 439}
441 440
442#ifdef CONFIG_SND_SOC_CACHE_LZO
443struct snd_soc_lzo_ctx {
444 void *wmem;
445 void *dst;
446 const void *src;
447 size_t src_len;
448 size_t dst_len;
449 size_t decompressed_size;
450 unsigned long *sync_bmp;
451 int sync_bmp_nbits;
452};
453
454#define LZO_BLOCK_NUM 8
455static int snd_soc_lzo_block_count(void)
456{
457 return LZO_BLOCK_NUM;
458}
459
460static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
461{
462 lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
463 if (!lzo_ctx->wmem)
464 return -ENOMEM;
465 return 0;
466}
467
468static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
469{
470 size_t compress_size;
471 int ret;
472
473 ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
474 lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
475 if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
476 return -EINVAL;
477 lzo_ctx->dst_len = compress_size;
478 return 0;
479}
480
481static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
482{
483 size_t dst_len;
484 int ret;
485
486 dst_len = lzo_ctx->dst_len;
487 ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
488 lzo_ctx->dst, &dst_len);
489 if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
490 return -EINVAL;
491 return 0;
492}
493
494static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
495 struct snd_soc_lzo_ctx *lzo_ctx)
496{
497 int ret;
498
499 lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
500 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
501 if (!lzo_ctx->dst) {
502 lzo_ctx->dst_len = 0;
503 return -ENOMEM;
504 }
505
506 ret = snd_soc_lzo_compress(lzo_ctx);
507 if (ret < 0)
508 return ret;
509 return 0;
510}
511
512static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
513 struct snd_soc_lzo_ctx *lzo_ctx)
514{
515 int ret;
516
517 lzo_ctx->dst_len = lzo_ctx->decompressed_size;
518 lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
519 if (!lzo_ctx->dst) {
520 lzo_ctx->dst_len = 0;
521 return -ENOMEM;
522 }
523
524 ret = snd_soc_lzo_decompress(lzo_ctx);
525 if (ret < 0)
526 return ret;
527 return 0;
528}
529
530static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
531 unsigned int reg)
532{
533 const struct snd_soc_codec_driver *codec_drv;
534
535 codec_drv = codec->driver;
536 return (reg * codec_drv->reg_word_size) /
537 DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
538}
539
540static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
541 unsigned int reg)
542{
543 const struct snd_soc_codec_driver *codec_drv;
544
545 codec_drv = codec->driver;
546 return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
547 codec_drv->reg_word_size);
548}
549
550static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
551{
552 return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
553}
554
555static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
556{
557 struct snd_soc_lzo_ctx **lzo_blocks;
558 unsigned int val;
559 int i;
560 int ret;
561
562 lzo_blocks = codec->reg_cache;
563 for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
564 WARN_ON(!snd_soc_codec_writable_register(codec, i));
565 ret = snd_soc_cache_read(codec, i, &val);
566 if (ret)
567 return ret;
568 codec->cache_bypass = 1;
569 ret = snd_soc_write(codec, i, val);
570 codec->cache_bypass = 0;
571 if (ret)
572 return ret;
573 dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
574 i, val);
575 }
576
577 return 0;
578}
579
580static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
581 unsigned int reg, unsigned int value)
582{
583 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
584 int ret, blkindex, blkpos;
585 size_t blksize, tmp_dst_len;
586 void *tmp_dst;
587
588 /* index of the compressed lzo block */
589 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
590 /* register index within the decompressed block */
591 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
592 /* size of the compressed block */
593 blksize = snd_soc_lzo_get_blksize(codec);
594 lzo_blocks = codec->reg_cache;
595 lzo_block = lzo_blocks[blkindex];
596
597 /* save the pointer and length of the compressed block */
598 tmp_dst = lzo_block->dst;
599 tmp_dst_len = lzo_block->dst_len;
600
601 /* prepare the source to be the compressed block */
602 lzo_block->src = lzo_block->dst;
603 lzo_block->src_len = lzo_block->dst_len;
604
605 /* decompress the block */
606 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
607 if (ret < 0) {
608 kfree(lzo_block->dst);
609 goto out;
610 }
611
612 /* write the new value to the cache */
613 if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
614 codec->driver->reg_word_size)) {
615 kfree(lzo_block->dst);
616 goto out;
617 }
618
619 /* prepare the source to be the decompressed block */
620 lzo_block->src = lzo_block->dst;
621 lzo_block->src_len = lzo_block->dst_len;
622
623 /* compress the block */
624 ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
625 if (ret < 0) {
626 kfree(lzo_block->dst);
627 kfree(lzo_block->src);
628 goto out;
629 }
630
631 /* set the bit so we know we have to sync this register */
632 set_bit(reg, lzo_block->sync_bmp);
633 kfree(tmp_dst);
634 kfree(lzo_block->src);
635 return 0;
636out:
637 lzo_block->dst = tmp_dst;
638 lzo_block->dst_len = tmp_dst_len;
639 return ret;
640}
641
642static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
643 unsigned int reg, unsigned int *value)
644{
645 struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
646 int ret, blkindex, blkpos;
647 size_t blksize, tmp_dst_len;
648 void *tmp_dst;
649
650 *value = 0;
651 /* index of the compressed lzo block */
652 blkindex = snd_soc_lzo_get_blkindex(codec, reg);
653 /* register index within the decompressed block */
654 blkpos = snd_soc_lzo_get_blkpos(codec, reg);
655 /* size of the compressed block */
656 blksize = snd_soc_lzo_get_blksize(codec);
657 lzo_blocks = codec->reg_cache;
658 lzo_block = lzo_blocks[blkindex];
659
660 /* save the pointer and length of the compressed block */
661 tmp_dst = lzo_block->dst;
662 tmp_dst_len = lzo_block->dst_len;
663
664 /* prepare the source to be the compressed block */
665 lzo_block->src = lzo_block->dst;
666 lzo_block->src_len = lzo_block->dst_len;
667
668 /* decompress the block */
669 ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
670 if (ret >= 0)
671 /* fetch the value from the cache */
672 *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
673 codec->driver->reg_word_size);
674
675 kfree(lzo_block->dst);
676 /* restore the pointer and length of the compressed block */
677 lzo_block->dst = tmp_dst;
678 lzo_block->dst_len = tmp_dst_len;
679 return 0;
680}
681
682static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
683{
684 struct snd_soc_lzo_ctx **lzo_blocks;
685 int i, blkcount;
686
687 lzo_blocks = codec->reg_cache;
688 if (!lzo_blocks)
689 return 0;
690
691 blkcount = snd_soc_lzo_block_count();
692 /*
693 * the pointer to the bitmap used for syncing the cache
694 * is shared amongst all lzo_blocks. Ensure it is freed
695 * only once.
696 */
697 if (lzo_blocks[0])
698 kfree(lzo_blocks[0]->sync_bmp);
699 for (i = 0; i < blkcount; ++i) {
700 if (lzo_blocks[i]) {
701 kfree(lzo_blocks[i]->wmem);
702 kfree(lzo_blocks[i]->dst);
703 }
704 /* each lzo_block is a pointer returned by kmalloc or NULL */
705 kfree(lzo_blocks[i]);
706 }
707 kfree(lzo_blocks);
708 codec->reg_cache = NULL;
709 return 0;
710}
711
712static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
713{
714 struct snd_soc_lzo_ctx **lzo_blocks;
715 size_t bmp_size;
716 const struct snd_soc_codec_driver *codec_drv;
717 int ret, tofree, i, blksize, blkcount;
718 const char *p, *end;
719 unsigned long *sync_bmp;
720
721 ret = 0;
722 codec_drv = codec->driver;
723
724 /*
725 * If we have not been given a default register cache
726 * then allocate a dummy zero-ed out region, compress it
727 * and remember to free it afterwards.
728 */
729 tofree = 0;
730 if (!codec->reg_def_copy)
731 tofree = 1;
732
733 if (!codec->reg_def_copy) {
734 codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
735 if (!codec->reg_def_copy)
736 return -ENOMEM;
737 }
738
739 blkcount = snd_soc_lzo_block_count();
740 codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
741 GFP_KERNEL);
742 if (!codec->reg_cache) {
743 ret = -ENOMEM;
744 goto err_tofree;
745 }
746 lzo_blocks = codec->reg_cache;
747
748 /*
749 * allocate a bitmap to be used when syncing the cache with
750 * the hardware. Each time a register is modified, the corresponding
751 * bit is set in the bitmap, so we know that we have to sync
752 * that register.
753 */
754 bmp_size = codec_drv->reg_cache_size;
755 sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
756 GFP_KERNEL);
757 if (!sync_bmp) {
758 ret = -ENOMEM;
759 goto err;
760 }
761 bitmap_zero(sync_bmp, bmp_size);
762
763 /* allocate the lzo blocks and initialize them */
764 for (i = 0; i < blkcount; ++i) {
765 lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
766 GFP_KERNEL);
767 if (!lzo_blocks[i]) {
768 kfree(sync_bmp);
769 ret = -ENOMEM;
770 goto err;
771 }
772 lzo_blocks[i]->sync_bmp = sync_bmp;
773 lzo_blocks[i]->sync_bmp_nbits = bmp_size;
774 /* alloc the working space for the compressed block */
775 ret = snd_soc_lzo_prepare(lzo_blocks[i]);
776 if (ret < 0)
777 goto err;
778 }
779
780 blksize = snd_soc_lzo_get_blksize(codec);
781 p = codec->reg_def_copy;
782 end = codec->reg_def_copy + codec->reg_size;
783 /* compress the register map and fill the lzo blocks */
784 for (i = 0; i < blkcount; ++i, p += blksize) {
785 lzo_blocks[i]->src = p;
786 if (p + blksize > end)
787 lzo_blocks[i]->src_len = end - p;
788 else
789 lzo_blocks[i]->src_len = blksize;
790 ret = snd_soc_lzo_compress_cache_block(codec,
791 lzo_blocks[i]);
792 if (ret < 0)
793 goto err;
794 lzo_blocks[i]->decompressed_size =
795 lzo_blocks[i]->src_len;
796 }
797
798 if (tofree) {
799 kfree(codec->reg_def_copy);
800 codec->reg_def_copy = NULL;
801 }
802 return 0;
803err:
804 snd_soc_cache_exit(codec);
805err_tofree:
806 if (tofree) {
807 kfree(codec->reg_def_copy);
808 codec->reg_def_copy = NULL;
809 }
810 return ret;
811}
812#endif
813
814static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec) 441static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
815{ 442{
816 int i; 443 int i;
@@ -889,17 +516,6 @@ static const struct snd_soc_cache_ops cache_types[] = {
889 .write = snd_soc_flat_cache_write, 516 .write = snd_soc_flat_cache_write,
890 .sync = snd_soc_flat_cache_sync 517 .sync = snd_soc_flat_cache_sync
891 }, 518 },
892#ifdef CONFIG_SND_SOC_CACHE_LZO
893 {
894 .id = SND_SOC_LZO_COMPRESSION,
895 .name = "LZO",
896 .init = snd_soc_lzo_cache_init,
897 .exit = snd_soc_lzo_cache_exit,
898 .read = snd_soc_lzo_cache_read,
899 .write = snd_soc_lzo_cache_write,
900 .sync = snd_soc_lzo_cache_sync
901 },
902#endif
903 { 519 {
904 .id = SND_SOC_RBTREE_COMPRESSION, 520 .id = SND_SOC_RBTREE_COMPRESSION,
905 .name = "rbtree", 521 .name = "rbtree",