summaryrefslogtreecommitdiff
path: root/lib/lzo
diff options
context:
space:
mode:
Diffstat (limited to 'lib/lzo')
-rw-r--r--lib/lzo/Makefile11
-rw-r--r--lib/lzo/lzo1x_compress.c279
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c268
-rwxr-xr-xlib/lzo/lzo1x_hw_compress.c238
-rwxr-xr-xlib/lzo/lzo1x_hw_decompress.c106
-rw-r--r--lib/lzo/lzodefs.h59
-rwxr-xr-xlib/lzo/sprd_zipdec_drv.c238
-rwxr-xr-xlib/lzo/sprd_zipdec_drv.h147
-rwxr-xr-xlib/lzo/sprd_zipenc_drv.c246
-rwxr-xr-xlib/lzo/sprd_zipenc_drv.h136
10 files changed, 1728 insertions, 0 deletions
diff --git a/lib/lzo/Makefile b/lib/lzo/Makefile
new file mode 100644
index 00000000..309baa21
--- /dev/null
+++ b/lib/lzo/Makefile
@@ -0,0 +1,11 @@
+
+ifeq ($(CONFIG_LZO_HW_ALGO),y)
+obj-y += lzo1x_hw_compress.o sprd_zipenc_drv.o
+obj-y += lzo1x_hw_decompress.o sprd_zipdec_drv.o
+endif
+
+lzo_compress-objs := lzo1x_compress.o
+lzo_decompress-objs := lzo1x_decompress_safe.o
+
+obj-$(CONFIG_LZO_COMPRESS) += lzo_compress.o
+obj-$(CONFIG_LZO_DECOMPRESS) += lzo_decompress.o
diff --git a/lib/lzo/lzo1x_compress.c b/lib/lzo/lzo1x_compress.c
new file mode 100644
index 00000000..236eb211
--- /dev/null
+++ b/lib/lzo/lzo1x_compress.c
@@ -0,0 +1,279 @@
+/*
+ * LZO1X Compressor from LZO
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <asm/unaligned.h>
+#include <linux/lzo.h>
+#include "lzodefs.h"
+
+static noinline size_t
+lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ size_t ti, void *wrkmem)
+{
+ const unsigned char *ip;
+ unsigned char *op;
+ const unsigned char * const in_end = in + in_len;
+ const unsigned char * const ip_end = in + in_len - 20;
+ const unsigned char *ii;
+ lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
+
+ op = out;
+ ip = in;
+ ii = ip;
+ ip += ti < 4 ? 4 - ti : 0;
+
+ for (;;) {
+ const unsigned char *m_pos;
+ size_t t, m_len, m_off;
+ u32 dv;
+literal:
+ ip += 1 + ((ip - ii) >> 5);
+next:
+ if (unlikely(ip >= ip_end))
+ break;
+ dv = get_unaligned_le32(ip);
+ t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
+ m_pos = in + dict[t];
+ dict[t] = (lzo_dict_t) (ip - in);
+ if (unlikely(dv != get_unaligned_le32(m_pos)))
+ goto literal;
+
+ ii -= ti;
+ ti = 0;
+ t = ip - ii;
+ if (t != 0) {
+ if (t <= 3) {
+ op[-2] |= t;
+ COPY4(op, ii);
+ op += t;
+ } else if (t <= 16) {
+ *op++ = (t - 3);
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += t;
+ } else {
+ if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
+ *op++ = 0;
+ while (unlikely(tt > 255)) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
+ }
+ do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
+ *op++ = *ii++;
+ } while (--t > 0);
+ }
+ }
+
+ m_len = 4;
+ {
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
+ u64 v;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 8;
+ v = get_unaligned((const u64 *) (ip + m_len)) ^
+ get_unaligned((const u64 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctzll(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clzll(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
+ u32 v;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(v == 0)) {
+ do {
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (v != 0)
+ break;
+ m_len += 4;
+ v = get_unaligned((const u32 *) (ip + m_len)) ^
+ get_unaligned((const u32 *) (m_pos + m_len));
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (v == 0);
+ }
+# if defined(__LITTLE_ENDIAN)
+ m_len += (unsigned) __builtin_ctz(v) / 8;
+# elif defined(__BIG_ENDIAN)
+ m_len += (unsigned) __builtin_clz(v) / 8;
+# else
+# error "missing endian definition"
+# endif
+#else
+ if (unlikely(ip[m_len] == m_pos[m_len])) {
+ do {
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (ip[m_len] != m_pos[m_len])
+ break;
+ m_len += 1;
+ if (unlikely(ip + m_len >= ip_end))
+ goto m_len_done;
+ } while (ip[m_len] == m_pos[m_len]);
+ }
+#endif
+ }
+m_len_done:
+
+ m_off = ip - m_pos;
+ ip += m_len;
+ ii = ip;
+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
+ m_off -= 1;
+ *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
+ *op++ = (m_off >> 3);
+ } else if (m_off <= M3_MAX_OFFSET) {
+ m_off -= 1;
+ if (m_len <= M3_MAX_LEN)
+ *op++ = (M3_MARKER | (m_len - 2));
+ else {
+ m_len -= M3_MAX_LEN;
+ *op++ = M3_MARKER | 0;
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ *op++ = (m_len);
+ }
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
+ } else {
+ m_off -= 0x4000;
+ if (m_len <= M4_MAX_LEN)
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8)
+ | (m_len - 2));
+ else {
+ m_len -= M4_MAX_LEN;
+ *op++ = (M4_MARKER | ((m_off >> 11) & 8));
+ while (unlikely(m_len > 255)) {
+ m_len -= 255;
+ *op++ = 0;
+ }
+ *op++ = (m_len);
+ }
+ *op++ = (m_off << 2);
+ *op++ = (m_off >> 6);
+ }
+ goto next;
+ }
+ *out_len = op - out;
+ return in_end - (ii - ti);
+}
+
+int lzo1x_1_compress(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len,
+ void *wrkmem)
+{
+ const unsigned char *ip = in;
+ unsigned char *op = out;
+ size_t l = in_len;
+ size_t t = 0;
+
+ while (l > 20) {
+ size_t ll = l <= (M4_MAX_OFFSET + 1) ? l : (M4_MAX_OFFSET + 1);
+ uintptr_t ll_end = (uintptr_t) ip + ll;
+ if ((ll_end + ((t + ll) >> 5)) <= ll_end)
+ break;
+ BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
+ memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
+ t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem);
+ ip += ll;
+ op += *out_len;
+ l -= ll;
+ }
+ t += l;
+
+ if (t > 0) {
+ const unsigned char *ii = in + in_len - t;
+
+ if (op == out && t <= 238) {
+ *op++ = (17 + t);
+ } else if (t <= 3) {
+ op[-2] |= t;
+ } else if (t <= 18) {
+ *op++ = (t - 3);
+ } else {
+ size_t tt = t - 18;
+ *op++ = 0;
+ while (tt > 255) {
+ tt -= 255;
+ *op++ = 0;
+ }
+ *op++ = tt;
+ }
+ if (t >= 16) do {
+ COPY8(op, ii);
+ COPY8(op + 8, ii + 8);
+ op += 16;
+ ii += 16;
+ t -= 16;
+ } while (t >= 16);
+ if (t > 0) do {
+ *op++ = *ii++;
+ } while (--t > 0);
+ }
+
+ *op++ = M4_MARKER | 1;
+ *op++ = 0;
+ *op++ = 0;
+
+ *out_len = op - out;
+ return LZO_E_OK;
+}
+EXPORT_SYMBOL_GPL(lzo1x_1_compress);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X-1 Compressor");
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
new file mode 100644
index 00000000..a1c387f6
--- /dev/null
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -0,0 +1,268 @@
+/*
+ * LZO1X Decompressor from LZO
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+#include <asm/unaligned.h>
+#include <linux/lzo.h>
+#include "lzodefs.h"
+
+#define HAVE_IP(x) ((size_t)(ip_end - ip) >= (size_t)(x))
+#define HAVE_OP(x) ((size_t)(op_end - op) >= (size_t)(x))
+#define NEED_IP(x) if (!HAVE_IP(x)) goto input_overrun
+#define NEED_OP(x) if (!HAVE_OP(x)) goto output_overrun
+#define TEST_LB(m_pos) if ((m_pos) < out) goto lookbehind_overrun
+
+/* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
+ * count without overflowing an integer. The multiply will overflow when
+ * multiplying 255 by more than MAXINT/255. The sum will overflow earlier
+ * depending on the base count. Since the base count is taken from a u8
+ * and a few bits, it is safe to assume that it will always be lower than
+ * or equal to 2*255, thus we can always prevent any overflow by accepting
+ * two less 255 steps. See Documentation/lzo.txt for more information.
+ */
+#define MAX_255_COUNT ((((size_t)~0) / 255) - 2)
+
+int lzo1x_decompress_safe(const unsigned char *in, size_t in_len,
+ unsigned char *out, size_t *out_len)
+{
+ unsigned char *op;
+ const unsigned char *ip;
+ size_t t, next;
+ size_t state = 0;
+ const unsigned char *m_pos;
+ const unsigned char * const ip_end = in + in_len;
+ unsigned char * const op_end = out + *out_len;
+
+ op = out;
+ ip = in;
+
+ if (unlikely(in_len < 3))
+ goto input_overrun;
+ if (*ip > 17) {
+ t = *ip++ - 17;
+ if (t < 4) {
+ next = t;
+ goto match_next;
+ }
+ goto copy_literal_run;
+ }
+
+ for (;;) {
+ t = *ip++;
+ if (t < 16) {
+ if (likely(state == 0)) {
+ if (unlikely(t == 0)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
+
+ while (unlikely(*ip == 0)) {
+ ip++;
+ NEED_IP(1);
+ }
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
+
+ offset = (offset << 8) - offset;
+ t += offset + 15 + *ip++;
+ }
+ t += 3;
+copy_literal_run:
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) {
+ const unsigned char *ie = ip + t;
+ unsigned char *oe = op + t;
+ do {
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ COPY8(op, ip);
+ op += 8;
+ ip += 8;
+ } while (ip < ie);
+ ip = ie;
+ op = oe;
+ } else
+#endif
+ {
+ NEED_OP(t);
+ NEED_IP(t + 3);
+ do {
+ *op++ = *ip++;
+ } while (--t > 0);
+ }
+ state = 4;
+ continue;
+ } else if (state != 4) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ TEST_LB(m_pos);
+ NEED_OP(2);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ goto match_next;
+ } else {
+ next = t & 3;
+ m_pos = op - (1 + M2_MAX_OFFSET);
+ m_pos -= t >> 2;
+ m_pos -= *ip++ << 2;
+ t = 3;
+ }
+ } else if (t >= 64) {
+ next = t & 3;
+ m_pos = op - 1;
+ m_pos -= (t >> 2) & 7;
+ m_pos -= *ip++ << 3;
+ t = (t >> 5) - 1 + (3 - 1);
+ } else if (t >= 32) {
+ t = (t & 31) + (3 - 1);
+ if (unlikely(t == 2)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
+
+ while (unlikely(*ip == 0)) {
+ ip++;
+ NEED_IP(1);
+ }
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
+
+ offset = (offset << 8) - offset;
+ t += offset + 31 + *ip++;
+ NEED_IP(2);
+ }
+ m_pos = op - 1;
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ } else {
+ m_pos = op;
+ m_pos -= (t & 8) << 11;
+ t = (t & 7) + (3 - 1);
+ if (unlikely(t == 2)) {
+ size_t offset;
+ const unsigned char *ip_last = ip;
+
+ while (unlikely(*ip == 0)) {
+ ip++;
+ NEED_IP(1);
+ }
+ offset = ip - ip_last;
+ if (unlikely(offset > MAX_255_COUNT))
+ return LZO_E_ERROR;
+
+ offset = (offset << 8) - offset;
+ t += offset + 7 + *ip++;
+ NEED_IP(2);
+ }
+ next = get_unaligned_le16(ip);
+ ip += 2;
+ m_pos -= next >> 2;
+ next &= 3;
+ if (m_pos == op)
+ goto eof_found;
+ m_pos -= 0x4000;
+ }
+ TEST_LB(m_pos);
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (op - m_pos >= 8) {
+ unsigned char *oe = op + t;
+ if (likely(HAVE_OP(t + 15))) {
+ do {
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ COPY8(op, m_pos);
+ op += 8;
+ m_pos += 8;
+ } while (op < oe);
+ op = oe;
+ if (HAVE_IP(6)) {
+ state = next;
+ COPY4(op, ip);
+ op += next;
+ ip += next;
+ continue;
+ }
+ } else {
+ NEED_OP(t);
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+ } else
+#endif
+ {
+ unsigned char *oe = op + t;
+ NEED_OP(t);
+ op[0] = m_pos[0];
+ op[1] = m_pos[1];
+ op += 2;
+ m_pos += 2;
+ do {
+ *op++ = *m_pos++;
+ } while (op < oe);
+ }
+match_next:
+ state = next;
+ t = next;
+#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
+ if (likely(HAVE_IP(6) && HAVE_OP(4))) {
+ COPY4(op, ip);
+ op += t;
+ ip += t;
+ } else
+#endif
+ {
+ NEED_IP(t + 3);
+ NEED_OP(t);
+ while (t > 0) {
+ *op++ = *ip++;
+ t--;
+ }
+ }
+ }
+
+eof_found:
+ *out_len = op - out;
+ return (t != 3 ? LZO_E_ERROR :
+ ip == ip_end ? LZO_E_OK :
+ ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN);
+
+input_overrun:
+ *out_len = op - out;
+ return LZO_E_INPUT_OVERRUN;
+
+output_overrun:
+ *out_len = op - out;
+ return LZO_E_OUTPUT_OVERRUN;
+
+lookbehind_overrun:
+ *out_len = op - out;
+ return LZO_E_LOOKBEHIND_OVERRUN;
+}
+#ifndef STATIC
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X Decompressor");
+
+#endif
diff --git a/lib/lzo/lzo1x_hw_compress.c b/lib/lzo/lzo1x_hw_compress.c
new file mode 100755
index 00000000..346ba437
--- /dev/null
+++ b/lib/lzo/lzo1x_hw_compress.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ ** File Name: *
+ ** Author: *
+ ** DATE: *
+ ** Copyright: Spreatrum, Incoporated. All Rights Reserved. *
+ ** Description: *
+ ******************************************************************************
+
+ ******************************************************************************
+ ** Edit History *
+ ** ------------------------------------------------------------------------- *
+ ** DATE NAME DESCRIPTION *
+ ** *
+ ******************************************************************************/
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **--------------------------------------------------------------------------- */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/lzo.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#ifndef CONFIG_64BIT
+#include <mach/arch_misc.h>
+#endif
+
+#include <linux/highmem.h>
+#include <linux/vmalloc.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+
+#include "sprd_zipenc_drv.h"
+//#include "lzodefs_hw.h"
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+//macro
+
+DEFINE_SPINLOCK(zipenc_lock);
+
+u32 lzo1x_virt_to_phys(u32 virt_addr)
+{
+ u32 phy_addr;
+ struct page *page;
+ if((unsigned long)virt_addr<PAGE_OFFSET){
+ printk("%s: virtual addr is error\n",__func__);
+ return (-1UL);
+ }
+ if(virt_addr_valid(virt_addr)){
+ phy_addr=virt_to_phys(virt_addr);
+ }
+ else if(is_vmalloc_or_module_addr(virt_addr)){
+ page =vmalloc_to_page(virt_addr);
+ phy_addr =(page)? page_to_phys(page): (-1UL);
+ }
+ else{
+ page = kmap_atomic_to_page(virt_addr);
+ phy_addr =(page)? page_to_phys(page): (-1UL);
+ }
+ return phy_addr;
+}
+
+static int _lzo1x_1_hw_compress(u32 src_addr , u32 src_num , u32 dst_addr , u32 *dst_len)
+{
+
+ u32 len,ol_sts;
+ u32 phy_src_addr,phy_dst_addr;
+
+ *dst_len=0;
+
+ phy_src_addr = lzo1x_virt_to_phys(src_addr);
+ phy_dst_addr = lzo1x_virt_to_phys(dst_addr);
+
+ if((phy_src_addr==(-1UL))||(phy_dst_addr==(-1UL)))
+ {
+ printk("lzo1x phy addr errors \n");
+ return LZO_OTHER_ERROR;
+ }
+
+ spin_lock(&zipenc_lock);
+ ZipEnc_SetSrcCfg(phy_src_addr , ZIP_WORK_LENGTH);
+ ZipEnc_SetDestCfg(phy_dst_addr , ZIP_WORK_LENGTH);
+
+ //dmac_flush_range(src_addr,src_addr+ZIP_WORK_LENGTH);
+ //dmac_flush_range(dst_addr,dst_addr+ZIP_WORK_LENGTH);
+
+ ZipEnc_Run();
+ spin_unlock(&zipenc_lock);
+
+ if(Zip_Enc_Wait_Pool(ZIPENC_DONE_INT))
+ {
+ printk("zip enc error\n");
+ return LZO_HW_ERROR;
+ }
+
+ ol_sts=ZipEnc_Get_Ol_Sts();
+ if(ol_sts)
+ {
+ return LZO_HW_OUT_LEN_ERROR;
+ }
+ else
+ {
+ len=ZipEnc_Get_Comp_Len();
+ if(len >= ZIP_WORK_LENGTH )
+ {
+ return LZO_HW_OUT_LEN_ERROR;
+ }
+ }
+ *dst_len = len;
+ return 0;
+}
+
+int lzo1x_1_compress_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len , void *wrkmen)
+{
+ volatile u32 enc_len;
+ volatile int ret;
+
+ u32 src_addr =(u32)src;
+ u32 dst_addr =(u32)dst;
+
+ if (!dst || !dst_len || !src || (src_len!=PAGE_SIZE))
+ {
+ printk("zip compress input parameter error \n");
+ return LZO_HW_IN_PARA_ERROR;
+ }
+ //printk("lzo hw compress \r\n");
+ if(ret=_lzo1x_1_hw_compress((u32)src_addr ,src_len , dst_addr ,&enc_len))
+ {
+ //printk("lzo compress error ret:%d\n",ret);
+ if(ret== LZO_HW_OUT_LEN_ERROR)
+ return ret;
+
+ ZipEnc_Restart();
+
+ *dst_len=enc_len;
+ if(ret==LZO_HW_ERROR)
+ return LZO_HW_ERROR;
+ else
+ return LZO_OTHER_ERROR;
+ }
+
+ *dst_len=enc_len;
+ return LZO_HW_OK;
+}
+
+#ifndef CONFIG_64BIT
+int lzo1x_1_compress_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len , void *wrkmen)
+{
+ return ZipEnc_compress(src,src_len,dst,dst_len,wrkmen);
+}
+
+unsigned int get_zip_type(void)
+{
+ static unsigned int lzo_algo_type = 0;
+ static int read_chip_cnt = 0;
+ int chip_id;
+ if(!read_chip_cnt)
+ {
+ read_chip_cnt = 1;
+ chip_id = sci_get_chip_id();
+ if((chip_id==0x7715a000)||(chip_id==0x7715a001)||(chip_id==0x8815a000))
+ {
+ lzo_algo_type = 1;
+ }
+ printk("lzo zip type %d is %s zip\r\n",lzo_algo_type, lzo_algo_type ? "sw" : "hw");
+ }
+ return lzo_algo_type;
+}
+
+static int __init ZipEnc_Init(void)
+{
+ int ret;
+
+ printk("%s\r\n", __func__);
+
+ ZipEnc_Enable();
+ //ZipEnc_Reset();
+
+ CHIP_REG_OR(ZIPENC_CTRL , ZIPENC_EN);
+
+ ZipEnc_In_Swt(zipenc_param.in_switch_mode);
+ ZipEnc_Out_Swt(zipenc_param.out_switch_mode);
+
+ ZipEnc_LengthLimitMode();
+
+ ZipEnc_InQueue_Clr();
+ ZipEnc_OutQueue_Clr();
+
+ if(zipenc_param.wait_mode == ZIPENC_WAIT_INT)
+ {
+ ZipEnc_RegCallback(ZIPENC_DONE_INT,ZipEnc_Callback_Done);
+ ZipEnc_RegCallback(ZIPENC_TIMEOUT_INT,ZipEnc_Callback_Timeout);
+ ZipEnc_IntEn(ZIPENC_DONE_INT);
+ ZipEnc_IntEn(ZIPENC_TIMEOUT_INT);
+ ret = request_irq( zipenc_param.int_num, ZipEnc_IsrHandler,0,"zip enc",NULL);
+ if(ret)
+ {
+ printk("zip enc request irq error\n");
+ return -1;
+ }
+ }
+
+ Zip_Enc_Wait = ((zipenc_param.wait_mode==ZIPENC_WAIT_INT)? (Zip_Enc_Wait_Int) : (Zip_Enc_Wait_Pool));
+ ZipEnc_compress = get_zip_type() ? lzo1x_1_compress : _lzo1x_1_compress_hw;
+ return 0;
+}
+
+static void ZipEnc_DeInit(void)
+{
+ ZipEnc_Disable();
+ if(zipenc_param.work_mode==ZIPENC_QUEUE)
+ {
+ ZipEnc_InQueue_Clr();
+ ZipEnc_OutQueue_Clr();
+ }
+
+ if(zipenc_param.wait_mode==ZIPENC_WAIT_INT)
+ {
+ ZipEnc_IntDisable(ZIPENC_DONE_INT);
+ ZipEnc_UNRegCallback(ZIPENC_DONE_INT);
+
+ ZipEnc_UNRegCallback(ZIPENC_TIMEOUT_INT);
+ free_irq(zipenc_param.int_num,NULL);
+ }
+}
+
+module_init(ZipEnc_Init);
+module_exit(ZipEnc_DeInit);
+
+EXPORT_SYMBOL_GPL(lzo1x_1_compress_hw);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("LZO1X-1 HW Compressor");
+#endif
diff --git a/lib/lzo/lzo1x_hw_decompress.c b/lib/lzo/lzo1x_hw_decompress.c
new file mode 100755
index 00000000..b0060991
--- /dev/null
+++ b/lib/lzo/lzo1x_hw_decompress.c
@@ -0,0 +1,106 @@
+/******************************************************************************
+ ** File Name: *
+ ** Author: *
+ ** DATE: *
+ ** Copyright: Spreatrum, Incoporated. All Rights Reserved. *
+ ** Description: *
+ ******************************************************************************
+
+ ******************************************************************************
+ ** Edit History *
+ ** ------------------------------------------------------------------------- -*
+ ** DATE NAME DESCRIPTION *
+ ** *
+ ******************************************************************************/
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **--------------------------------------------------------------------------- */
+
+#ifndef STATIC
+#include <linux/module.h>
+#include <linux/kernel.h>
+#endif
+
+#include <linux/interrupt.h>
+#include <linux/lzo.h>
+#include <linux/poll.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <asm/page.h>
+#include <asm/cacheflush.h>
+#include <asm/io.h>
+
+#include "sprd_zipdec_drv.h"
+//#include "lzodefs_hw.h"
+
+//#include <linux/spinlock_types.h>
+#include <linux/sched.h>
+#include <linux/atomic.h>
+//#include <mach/sci.h>
+
+
+u32 lzo1x_virt_to_phys(u32 virt_addr);
+
+
+DEFINE_SPINLOCK(zipdec_lock);
+static int _lzo1x_decompress_single(u32 src_addr , u32 src_num , u32 dst_addr , u32 *dst_len )
+{
+
+ u32 phy_src_addr,phy_dst_addr;
+
+ *dst_len=0;
+
+ phy_src_addr = lzo1x_virt_to_phys(src_addr);
+ phy_dst_addr = lzo1x_virt_to_phys(dst_addr);
+
+ if((phy_src_addr==(-1UL))||(phy_dst_addr==(-1UL))){
+ printk("lzo1x phy addr errors \n");
+ return -1;
+ }
+
+ spin_lock(&zipdec_lock);
+ ZipDec_SetSrcCfg(0 , phy_src_addr, src_num);
+ ZipDec_SetDestCfg(0, phy_dst_addr, ZIP_WORK_LENGTH);
+
+// dmac_flush_range((void *)(src_addr),(void *)(src_addr+src_num));
+// dmac_flush_range((void *)dst_addr,(void *)(dst_addr+ZIP_WORK_LENGTH));
+
+ ZipDec_Run();
+ spin_unlock(&zipdec_lock);
+
+ if(Zip_Dec_Wait_Pool(ZIPDEC_DONE_INT))
+ {
+ return -1;
+ }
+
+ *dst_len=ZIP_WORK_LENGTH;
+ return 0;
+}
+
+
+
+int lzo1x_decompress_safe_hw(const unsigned char *src , size_t src_len , unsigned char *dst , size_t *dst_len)
+{
+ u32 dec_len;
+
+ //uint32_t src_addr =(uint32_t)src;
+ //uint32_t dst_addr =(uint32_t)dst;
+
+ if (!dst || !dst_len || !src || !src_len ||(src_len > PAGE_SIZE)) return LZO_HW_IN_PARA_ERROR;
+ //printk("lzo hw decompress\r\n");
+
+ //if(_lzo1x_decompress_single((u32)src_addr ,src_len , dst_addr ,&dec_len))
+ if(_lzo1x_decompress_single((u32)src ,(u32)src_len ,(u32)dst ,&dec_len))
+ {
+ *dst_len = dec_len;
+ ZipDec_Restart();
+ return LZO_HW_ERROR;
+ }
+ *dst_len = ZIP_WORK_LENGTH;
+ return LZO_HW_OK;
+}
+
+
+EXPORT_SYMBOL_GPL(lzo1x_decompress_safe_hw);
+
diff --git a/lib/lzo/lzodefs.h b/lib/lzo/lzodefs.h
new file mode 100644
index 00000000..6710b83c
--- /dev/null
+++ b/lib/lzo/lzodefs.h
@@ -0,0 +1,59 @@
+/*
+ * lzodefs.h -- architecture, OS and compiler specific defines
+ *
+ * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
+ *
+ * The full LZO package can be found at:
+ * http://www.oberhumer.com/opensource/lzo/
+ *
+ * Changed for Linux kernel use by:
+ * Nitin Gupta <nitingupta910@gmail.com>
+ * Richard Purdie <rpurdie@openedhand.com>
+ */
+
+
+#define COPY4(dst, src) \
+ put_unaligned(get_unaligned((const u32 *)(src)), (u32 *)(dst))
+#if defined(__x86_64__)
+#define COPY8(dst, src) \
+ put_unaligned(get_unaligned((const u64 *)(src)), (u64 *)(dst))
+#else
+#define COPY8(dst, src) \
+ COPY4(dst, src); COPY4((dst) + 4, (src) + 4)
+#endif
+
+#if defined(__BIG_ENDIAN) && defined(__LITTLE_ENDIAN)
+#error "conflicting endian definitions"
+#elif defined(__x86_64__)
+#define LZO_USE_CTZ64 1
+#define LZO_USE_CTZ32 1
+#elif defined(__i386__) || defined(__powerpc__)
+#define LZO_USE_CTZ32 1
+#elif defined(__arm__) && (__LINUX_ARM_ARCH__ >= 5)
+#define LZO_USE_CTZ32 1
+#endif
+
+#define M1_MAX_OFFSET 0x0400
+#define M2_MAX_OFFSET 0x0800
+#define M3_MAX_OFFSET 0x4000
+#define M4_MAX_OFFSET 0xbfff
+
+#define M1_MIN_LEN 2
+#define M1_MAX_LEN 2
+#define M2_MIN_LEN 3
+#define M2_MAX_LEN 8
+#define M3_MIN_LEN 3
+#define M3_MAX_LEN 33
+#define M4_MIN_LEN 3
+#define M4_MAX_LEN 9
+
+#define M1_MARKER 0
+#define M2_MARKER 64
+#define M3_MARKER 32
+#define M4_MARKER 16
+
+#define lzo_dict_t unsigned short
+#define D_BITS 13
+#define D_SIZE (1u << D_BITS)
+#define D_MASK (D_SIZE - 1)
+#define D_HIGH ((D_MASK >> 1) + 1)
diff --git a/lib/lzo/sprd_zipdec_drv.c b/lib/lzo/sprd_zipdec_drv.c
new file mode 100755
index 00000000..73768610
--- /dev/null
+++ b/lib/lzo/sprd_zipdec_drv.c
@@ -0,0 +1,238 @@
+/******************************************************************************
+ ** File Name: xxx_test.c
+ ** Author: xxx
+ ** Date: 22/08/2001
+ ** Copyright: 2001 Spreadtrum, Incorporated. All Rights Reserved.
+ ** Description: Module test entry template file.
+ **
+ **
+ *****************************************************************************
+ *****************************************************************************
+ ** Edit History
+ **--------------------------------------------------------------------------*
+ ** DATE NAME DESCRIPTION
+ ** 22/08/2001 xxx Create.
+ *****************************************************************************/
+
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **---------------------------------------------------------------------------*/
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/lzo.h>
+
+#include <soc/sprd/sci_glb_regs.h>
+#include <soc/sprd/sci.h>
+#include "sprd_zipdec_drv.h"
+
+unsigned long REGS_ZIPDEC_BASE = 0;
+
+void sprd_zipmatrix_reset(void)
+{
+ u32 i;
+ sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIP_MTX_SOFT_RST|BIT_ZIPDEC_SOFT_RST);
+ for(i=0;i<0x200;i++);
+ sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIP_MTX_SOFT_RST|BIT_ZIPDEC_SOFT_RST);
+}
+
+void sprd_zipdec_reset(void)
+{
+ u32 i;
+ sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIPDEC_SOFT_RST);
+ for(i=0;i<0x200;i++);
+ sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIPDEC_SOFT_RST);
+}
+
+void sprd_zipdec_enable(u32 enable)
+{
+ if(enable)
+ {
+ sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_EB),BIT_ZIPDEC_EB);
+ sci_glb_set(REG_GLB_SET(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB);
+ }
+ else
+ {
+ sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_EB),BIT_ZIPDEC_EB);
+ //sci_glb_set(REG_GLB_CLR(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB);
+ }
+}
+
+void ZipDec_Run(void)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+ reg_val |= ZIPDEC_RUN;
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+}
+
+void ZipDec_In_Out_SwtMode(u32 Inmode,u32 Outmode)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+ reg_val &= ~(ZIPDEC_IN_SWT_MASK|ZIPDEC_OUT_SWT_MASK);
+ reg_val |= (Inmode<<ZIPDEC_IN_SWT_SHIFT | Outmode<<ZIPDEC_OUT_SWT_SHIFT);
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+}
+
+void ZipDec_QueueEnable(u32 enable)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+ reg_val = enable ? (reg_val|ZIPDEC_QUEUE_EN): (reg_val&~ZIPDEC_QUEUE_EN);
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+}
+
+void ZipDec_QueueLength(u32 length)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+ reg_val &= ~ZIPDEC_QUEUE_LEN_MASK;
+ reg_val |= length <<ZIPDEC_QUEUE_LEN_SHIFT;
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+}
+
+void ZipDec_Set_Timeout(u32 timeout)
+{
+ __raw_writel(timeout,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_TIME_OUT));
+}
+
+void ZipDec_SetSrcCfg(u32 num,unsigned long src_start_addr, u32 src_len)
+{
+ __raw_writel(src_start_addr,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_IN_ADDR+4*num));
+ __raw_writel(src_len,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_IN_LEN+4*num));
+}
+
+void ZipDec_SetDestCfg(u32 num,unsigned long dest_start_addr,u32 dst_len)
+{
+ __raw_writel(dest_start_addr,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_OUT_ADDR+4*num));
+ __raw_writel(dst_len,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_OUT_LEN+4*num));
+}
+
+void ZipDec_Restart(void)
+{
+ sprd_zipdec_enable(0);
+ udelay(100);
+ sprd_zipdec_enable(1);
+ sprd_zipdec_reset();
+ __raw_writel(ZIPDEC_EN,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+}
+
+int Zip_Dec_Wait_Pool(ZIPDEC_INT_TYPE num)
+{
+
+ u32 int_sts;
+ while (1)
+ {
+ int_sts = __raw_readl((void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_RAW));
+
+ if(int_sts&(0x1<<ZIPDEC_TIMEOUT_INT))
+ {
+ __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR));
+ //printk("zip dec timeout: 0x%x \n", int_sts);
+ //printk("ZIPDEC_STS0:0x%x\n",CHIP_REG_GET(ZIPDEC_STS0));
+ //printk("ZIPDEC_STS1:0x%x\n",CHIP_REG_GET(ZIPDEC_STS1));
+ //printk("ZIPDEC_STS2:0x%x\n",CHIP_REG_GET(ZIPDEC_STS2));
+ //printk("ZIPDEC_STS3:0x%x\n",CHIP_REG_GET(ZIPDEC_STS3));
+ //printk("ZIPDEC_STS4:0x%x\n",CHIP_REG_GET(ZIPDEC_STS4));
+ return -1;
+ }
+ if(int_sts&0x1e)
+ {
+ __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR));
+ //printk("zip dec err: 0x%x \n", int_sts);
+ //printk("ZIPDEC_STS0:0x%x\n",CHIP_REG_GET(ZIPDEC_STS0));
+ //printk("ZIPDEC_STS1:0x%x\n",CHIP_REG_GET(ZIPDEC_STS1));
+ //printk("ZIPDEC_STS2:0x%x\n",CHIP_REG_GET(ZIPDEC_STS2));
+ //printk("ZIPDEC_STS3:0x%x\n",CHIP_REG_GET(ZIPDEC_STS3));
+ //printk("ZIPDEC_STS4:0x%x\n",CHIP_REG_GET(ZIPDEC_STS4));
+ return -1;
+ }
+ if(int_sts&(0x1<<num))
+ {
+ __raw_writel(0xFF,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_INT_CLR));
+ break;
+ }
+ }
+ return 0;
+}
+
+static int __init sprd_zipdec_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(&pdev->dev, "zipdec get io resource failed!\n");
+ return -ENODEV;
+ }
+
+ REGS_ZIPDEC_BASE = (unsigned long)ioremap_nocache(regs->start,resource_size(regs));
+ if (!REGS_ZIPDEC_BASE){
+ dev_err(&pdev->dev, "zipdec get base address failed!\n");
+ return -ENODEV;
+ }
+
+ //dev_info(&pdev->dev, "probe zipdec get regbase 0x%lx\n",REGS_ZIPDEC_BASE);
+#if 0
+ irq_num = platform_get_irq(pdev, 0);
+ if (irq_num < 0) {
+ dev_err(&pdev->dev, "zipdec get irq resource failed!\n");
+ return irq_num;
+ }
+ dev_info(&pdev->dev, "probe zipdec get irq num %d\n",irq_num);
+#endif
+ sprd_zipdec_enable(1); // global enable dec
+
+ sprd_zipdec_reset();
+
+ __raw_writel(ZIPDEC_EN,(void __iomem*)(REGS_ZIPDEC_BASE+ZIPDEC_CTRL));
+
+ return 0;
+}
+
+static void sprd_zipdec_remove(void)
+{
+ sprd_zipdec_enable(0);
+}
+
+static const struct of_device_id sprd_zipdec_of_match[] = {
+ { .compatible = "sprd,sprd-zipdec", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sprd_zipdec_driver = {
+ .driver = {
+ .name = "sprd zipdec",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(sprd_zipdec_of_match),
+ },
+ .probe = sprd_zipdec_probe,
+ .remove = __exit_p(sprd_zipdec_remove),
+};
+
+static int __init sprd_zipdec_init(void)
+{
+ return platform_driver_register(&sprd_zipdec_driver);
+}
+subsys_initcall(sprd_zipdec_init);
+
+static void __exit sprd_zipdec_exit(void)
+{
+ platform_driver_unregister(&sprd_zipdec_driver);
+}
+module_exit(sprd_zipdec_exit);
+
+MODULE_DESCRIPTION("SpreadTrum ZIPDEC Controller driver");
+MODULE_AUTHOR("SPRD");
+MODULE_LICENSE("GPL");
diff --git a/lib/lzo/sprd_zipdec_drv.h b/lib/lzo/sprd_zipdec_drv.h
new file mode 100755
index 00000000..d6e0dff7
--- /dev/null
+++ b/lib/lzo/sprd_zipdec_drv.h
@@ -0,0 +1,147 @@
+/******************************************************************************
+ ** File Name:
+ ** Author:
+ ** Date:
+ ** Copyright:
+ ** Description:
+ **
+ **
+ *****************************************************************************
+ *****************************************************************************
+ ** Edit History
+ **--------------------------------------------------------------------------*
+ ** DATE NAME DESCRIPTION
+ ** 22/08/2001 xxx Create.
+ *****************************************************************************/
+
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **---------------------------------------------------------------------------*/
+#ifndef __SPRD_ZIP_DEC_H__
+#define __SPRD_ZIP_DEC_H__
+
+#include <linux/bitops.h>
+
+#define ZIPDEC_CTRL (0x0000)
+#define ZIPDEC_INT_EN (0x0004)
+#define ZIPDEC_INT_CLR (0x0008)
+#define ZIPDEC_INT_STS (0x000C)
+
+#define ZIPDEC_INT_RAW (0x0010)
+#define ZIPDEC_STS0 (0x0014)
+#define ZIPDEC_STS1 (0x0018)
+#define ZIPDEC_STS2 (0x001C)
+
+#define ZIPDEC_STS3 (0x0020)
+#define ZIPDEC_STS4 (0x0024)
+
+#define ZIPDEC_IN_ADDR (0x0040)
+#define ZIPDEC_IN_ADDR1 (0x0044)
+#define ZIPDEC_IN_ADDR2 (0x0048)
+#define ZIPDEC_IN_ADDR3 (0x004C)
+
+#define ZIPDEC_IN_ADDR4 (0x0050)
+#define ZIPDEC_IN_ADDR5 (0x0054)
+#define ZIPDEC_IN_ADDR6 (0x0058)
+#define ZIPDEC_IN_ADDR7 (0x005C)
+
+#define ZIPDEC_IN_LEN (0x0060)
+#define ZIPDEC_IN_LEN1 (0x0064)
+#define ZIPDEC_IN_LEN2 (0x0068)
+#define ZIPDEC_IN_LEN3 (0x006C)
+
+#define ZIPDEC_IN_LEN4 (0x0070)
+#define ZIPDEC_IN_LEN5 (0x0074)
+#define ZIPDEC_IN_LEN6 (0x0078)
+#define ZIPDEC_IN_LEN7 (0x007C)
+
+#define ZIPDEC_OUT_ADDR (0x0080)
+#define ZIPDEC_OUT_ADDR1 (0x0084)
+#define ZIPDEC_OUT_ADDR2 (0x0088)
+#define ZIPDEC_OUT_ADDR3 (0x008C)
+
+#define ZIPDEC_OUT_ADDR4 (0x0090)
+#define ZIPDEC_OUT_ADDR5 (0x0094)
+#define ZIPDEC_OUT_ADDR6 (0x0098)
+#define ZIPDEC_OUT_ADDR7 (0x009C)
+
+#define ZIPDEC_OUT_LEN (0x00A0)
+#define ZIPDEC_OUT_LEN1 (0x00A4)
+#define ZIPDEC_OUT_LEN2 (0x00A8)
+#define ZIPDEC_OUT_LEN3 (0x00AC)
+
+#define ZIPDEC_OUT_LEN4 (0x00B0)
+#define ZIPDEC_OUT_LEN5 (0x00B4)
+#define ZIPDEC_OUT_LEN6 (0x00B8)
+#define ZIPDEC_OUT_LEN7 (0x00BC)
+#define ZIPDEC_TIME_OUT (0x00C0)
+
+#define ZIPDEC_EN BIT(0)
+#define ZIPDEC_QUEUE_EN BIT(3)
+#define ZIPDEC_RUN BIT(4)
+
+#define ZIPDEC_IN_SWT_SHIFT (8)
+#define ZIPDEC_IN_SWT_MASK (0x03<<ZIPDEC_IN_SWT_SHIFT)
+
+#define ZIPDEC_OUT_SWT_SHIFT (10)
+#define ZIPDEC_OUT_SWT_MASK (0x03<<ZIPDEC_OUT_SWT_SHIFT)
+
+#define ZIPDEC_QUEUE_LEN_SHIFT (16)
+#define ZIPDEC_QUEUE_LEN_MASK (0x07<<ZIPDEC_QUEUE_LEN_SHIFT)
+
+#define ZIPDEC_DONE_EN BIT(0)
+#define ZIPDEC_QUEUE_DONE_EN BIT(1)
+#define ZIPDEC_ERR_EN BIT(2)
+#define ZIPDEC_LEN_ERR_EN BIT(5)
+#define ZIPDEC_SAVE_LEN_ERR_EN BIT(4)
+#define ZIPDEC_FETCH_LEN_ERR_EN BIT(3)
+#define ZIPDEC_TIMEOUT_EN BIT(6)
+
+#define ZIPDEC_DONE_CLR BIT(0)
+#define ZIPDEC_QUEUE_DONE_CLR BIT(1)
+#define ZIPDEC_ERR_CLR BIT(2)
+#define ZIPDEC_LEN_ERR_CLR BIT(5)
+#define ZIPDEC_SAVE_LEN_ERR_CLR BIT(4)
+#define ZIPDEC_FETCH_LEN_ERR_CLR BIT(3)
+#define ZIPDEC_TIMEOUT_CLR BIT(6)
+
+#define ZIPDEC_SWITCH_MODE0 0
+#define ZIPDEC_SWITCH_MODE1 1
+#define ZIPDEC_SWITCH_MODE2 2
+#define ZIPDEC_SWITCH_MODE3 3
+
+#define ZIPDEC_WAIT_POOL 0
+#define ZIPDEC_WAIT_INT 1
+
+#define ZIPDEC_NORMAL 0
+#define ZIPDEC_QUEUE 1
+
+#define ZIP_WORK_LENGTH (0x1000)
+
+typedef enum ZIPDEC_INT_TYPE
+{
+ ZIPDEC_DONE_INT = 0,
+ ZIPDEC_QUEUE_DONE_INT,
+ ZIPDEC_ERR_INT,
+ ZIPDEC_LEN_ERR_INT,
+ ZIPDEC_SAVE_LEN_ERR_INT,
+ ZIPDEC_FETCH_LEN_ERR_INT,
+ ZIPDEC_TIMEOUT_INT,
+ ZIPDEC_ALL_INT
+}ZIPDEC_INT_TYPE;
+
+void sprd_zipmatrix_reset(void);
+void sprd_zipdec_enable(u32 enable);
+void sprd_zipdec_reset(void);
+void ZipDec_Run(void);
+void ZipDec_Queue_Enable(u32 enable);
+void ZipDec_SetSrcCfg(u32 num,unsigned long src_start_addr, u32 src_len);
+void ZipDec_SetDestCfg(u32 num,unsigned long dest_start_addr,u32 dst_len);
+void ZipDec_In_Out_SwtMode(u32 inmode,u32 outmode);
+void ZipDec_QueueEn(u32 enable);
+void ZipDec_QueueLength(u32 length);
+void ZipDec_Set_Timeout(u32 time);
+int Zip_Dec_Wait_Pool(ZIPDEC_INT_TYPE num);
+void ZipDec_Restart(void);
+#endif
diff --git a/lib/lzo/sprd_zipenc_drv.c b/lib/lzo/sprd_zipenc_drv.c
new file mode 100755
index 00000000..d52e43e0
--- /dev/null
+++ b/lib/lzo/sprd_zipenc_drv.c
@@ -0,0 +1,246 @@
+/******************************************************************************
+ ** File Name: xxx_test.c
+ ** Author: xxx
+ ** Date: 22/08/2001
+ ** Copyright: 2001 Spreadtrum, Incorporated. All Rights Reserved.
+ ** Description: Module test entry template file.
+ **
+ **
+ *****************************************************************************
+ *****************************************************************************
+ ** Edit History
+ **--------------------------------------------------------------------------*
+ ** DATE NAME DESCRIPTION
+ ** 22/08/2001 xxx Create.
+ *****************************************************************************/
+
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **---------------------------------------------------------------------------*/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <linux/lzo.h>
+#include <soc/sprd/sci_glb_regs.h>
+#include <soc/sprd/sci.h>
+
+#include "sprd_zipenc_drv.h"
+
+unsigned long REGS_ZIPENC_BASE=0;
+
+void sprd_zipenc_reset(void)
+{
+ u32 i;
+ sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_RST),BIT_ZIPENC_SOFT_RST);
+ for(i=0;i<0x200;i++);
+ sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_RST),BIT_ZIPENC_SOFT_RST);
+}
+
+void sprd_zipenc_enable(int enable)
+{
+ if(enable)
+ {
+ sci_glb_set(REG_GLB_SET(REG_AP_AHB_AHB_EB),BIT_ZIPENC_EB);
+ sci_glb_set(REG_GLB_SET(REG_AON_APB_APB_EB1),BIT_ZIP_EMC_EB);
+ }
+ else
+ {
+ sci_glb_set(REG_GLB_CLR(REG_AP_AHB_AHB_EB),BIT_ZIPENC_EB);
+ }
+}
+
+void ZipEnc_LengthLimitMode(u32 enable)
+{
+ u32 reg_val;
+ reg_val=__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+ reg_val= enable ? (reg_val|ZIPENC_MODE) : (reg_val&~ZIPENC_MODE);
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+}
+
+void ZipEnc_Run(void)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+ reg_val |= ZIPENC_RUN;
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+}
+
+void ZipEnc_SetSrcCfg(unsigned long src_start_addr, u32 src_len)
+{
+ __raw_writel(src_start_addr,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_ADDR));
+ __raw_writel(src_len,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_LEN));
+}
+
+void ZipEnc_SetDestCfg(unsigned long dest_start_addr,u32 dst_len)
+{
+ __raw_writel(dest_start_addr,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_ADDR));
+ __raw_writel(dst_len,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_LEN));
+}
+
+
+void ZipEnc_In_Out_SwtMode(u32 inmode ,u32 outmode)
+{
+ u32 reg_val;
+ reg_val = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+ reg_val &= ~(ZIPENC_IN_SWT_MASK | ZIPENC_OUT_SWT_MASK);
+ reg_val |= (inmode<<ZIPENC_IN_SWT_SHIFT | outmode<<ZIPENC_OUT_SWT_SHIFT);
+ __raw_writel(reg_val,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+}
+
+void ZipEnc_InQueue_Clr(void)
+{
+ __raw_writel(ZIPENC_IN_QUEUE,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_IN_QUEUE_CLR));
+}
+
+void ZipEnc_OutQueue_Clr(void)
+{
+ __raw_writel(ZIPENC_OUT_QUEUE,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_OUT_QUEUE_CLR));
+}
+
+u32 ZipEnc_Get_Comp_Len(void)
+{
+ return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_LEN))&ZIPENC_COMP_LEN_MASK);
+}
+
+u32 ZipEnc_Get_Ol_Sts(void)
+{
+ return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_STS))>>ZIPENC_OL_STS_SHIFT);
+}
+
+u32 ZipEnc_Get_Err_Sts(void)
+{
+ return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_COMP_STS))&ZIPENC_ERR_STS_MASK);
+}
+
+void ZipEnc_Set_Timeout(u32 timeout)
+{
+ __raw_writel(timeout<<ZIPENC_TIME_OUT_NUM_SHIFT,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_TIME_OUT));
+}
+
+u32 ZipEnc_Get_Timeout_Flag(void)
+{
+ return (__raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_TIME_OUT))>>ZIPENC_TIME_OUT_FLAG_SHIFT);
+}
+
+void ZipEnc_Restart(void)
+{
+ sprd_zipenc_enable(0);
+ udelay(100);
+
+ sprd_zipenc_enable(1); // global enable dec
+ sprd_zipenc_reset();
+
+ __raw_writel(ZIPENC_EN,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+ ZipEnc_In_Out_SwtMode(ZIPENC_SWITCH_MODE1,ZIPENC_SWITCH_MODE1);
+
+ ZipEnc_InQueue_Clr();
+ ZipEnc_OutQueue_Clr();
+}
+
+int Zip_Enc_Wait_Pool(ZIPENC_INT_TYPE num)
+{
+ u32 int_sts;
+ while (1)
+ {
+ int_sts = __raw_readl((void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_RAW));
+
+ if(int_sts&(0x1<<num))
+ {
+ __raw_writel(ZIPENC_DONE_CLR|ZIPENC_SEG_DONE_CLR|ZIPENC_TIMEOUT_CLR,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_CLR));
+ break;
+ }
+ if(int_sts&(0x1<<ZIPENC_TIMEOUT_INT))
+ {
+ __raw_writel(ZIPENC_DONE_CLR|ZIPENC_SEG_DONE_CLR|ZIPENC_TIMEOUT_CLR,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_INT_CLR));
+ printk("zip enc timeout:0x%x\n",int_sts);
+ return -1;
+ }
+ }
+ return 0;
+}
+static int __init sprd_zipenc_probe(struct platform_device *pdev)
+{
+ struct resource *regs;
+
+ regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!regs) {
+ dev_err(&pdev->dev, "zipenc get io resource failed!\n");
+ return -ENODEV;
+ }
+
+ REGS_ZIPENC_BASE = (unsigned long)ioremap_nocache(regs->start,resource_size(regs));
+ if (!REGS_ZIPENC_BASE){
+ dev_err(&pdev->dev, "zipenc get base address failed!\n");
+ return -ENODEV;
+ }
+
+ //dev_info(&pdev->dev, "probe zipenc get regbase 0x%lx\n",REGS_ZIPENC_BASE);
+
+#if 0
+ irq_num = platform_get_irq(pdev, 0);
+ if (irq_num < 0) {
+ dev_err(&pdev->dev, "zipenc get irq resource failed!\n");
+ return irq_num;
+ }
+ dev_info(&pdev->dev, "probe zipenc get irq num %d\n",irq_num);
+#endif
+ sprd_zipenc_enable(1); // global enable dec
+
+ sprd_zipenc_reset();
+
+ __raw_writel(ZIPENC_EN,(void __iomem*)(REGS_ZIPENC_BASE+ZIPENC_CTRL));
+
+ ZipEnc_In_Out_SwtMode(ZIPENC_SWITCH_MODE1,ZIPENC_SWITCH_MODE1);
+
+ ZipEnc_InQueue_Clr();
+
+ ZipEnc_OutQueue_Clr();
+
+ return 0;
+}
+
+static void sprd_zipenc_remove(void)
+{
+ sprd_zipenc_enable(0);
+}
+static const struct of_device_id sprd_zipenc_of_match[] = {
+ { .compatible = "sprd,sprd-zipenc", },
+ { /* sentinel */ }
+};
+
+static struct platform_driver sprd_zipenc_driver = {
+ .driver = {
+ .name = "sprd zipenc",
+ .owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(sprd_zipenc_of_match),
+ },
+ .probe = sprd_zipenc_probe,
+ .remove = __exit_p(sprd_zipenc_remove),
+};
+
+static int __init sprd_zipenc_init(void)
+{
+ return platform_driver_register(&sprd_zipenc_driver);
+}
+subsys_initcall(sprd_zipenc_init);
+
+static void __exit sprd_zipenc_exit(void)
+{
+ platform_driver_unregister(&sprd_zipenc_driver);
+}
+module_exit(sprd_zipenc_exit);
+
+MODULE_DESCRIPTION("SpreadTrum ZIPENC Controller driver");
+MODULE_AUTHOR("SPRD");
+MODULE_LICENSE("GPL");
diff --git a/lib/lzo/sprd_zipenc_drv.h b/lib/lzo/sprd_zipenc_drv.h
new file mode 100755
index 00000000..ae5bf168
--- /dev/null
+++ b/lib/lzo/sprd_zipenc_drv.h
@@ -0,0 +1,136 @@
+/******************************************************************************
+ ** File Name:
+ ** Author:
+ ** Date:
+ ** Copyright:
+ ** Description:
+ **
+ **
+ *****************************************************************************
+ *****************************************************************************
+ ** Edit History
+ **--------------------------------------------------------------------------*
+ ** DATE NAME DESCRIPTION
+ ** 22/08/2001 xxx Create.
+ *****************************************************************************/
+
+
+/**---------------------------------------------------------------------------*
+ ** Dependencies *
+ **---------------------------------------------------------------------------*/
+#ifndef __SPRD_ZIP_ENC_H__
+#define __SPRD_ZIP_ENC_H__
+
+#include <linux/bitops.h>
+
+#define ZIPENC_CTRL (0x0000)
+#define ZIPENC_IN_ADDR (0x0004)
+#define ZIPENC_IN_LEN (0x0008)
+#define ZIPENC_OUT_ADDR (0x000c)
+
+#define ZIPENC_OUT_LEN (0x0010)
+#define ZIPENC_CUR_IN_ADDR (0x0014)
+#define ZIPENC_CUR_IN_LEN (0x0018)
+#define ZIPENC_CUR_OUT_ADDR (0x001c)
+
+#define ZIPENC_CUR_OUT_LEN (0x0020)
+#define ZIPENC_IN_QUEUE (0x0024)
+#define ZIPENC_OUT_QUEUE (0x0028)
+#define ZIPENC_COMP_LEN (0x002c)
+
+#define ZIPENC_COMP_STS (0x0030)
+#define ZIPENC_STS0 (0x0034)
+#define ZIPENC_STS1 (0x0038)
+#define ZIPENC_STS2 (0x003C)
+
+#define ZIPENC_INT_EN (0x0040)
+#define ZIPENC_INT_CLR (0x0044)
+#define ZIPENC_INT_STS (0x0048)
+#define ZIPENC_INT_RAW (0x004c)
+
+#define ZIPENC_IN_ADDRX (0x0050)
+#define ZIPENC_IN_LENX (0x0054)
+#define ZIPENC_OUT_ADDRX (0x0058)
+#define ZIPENC_OUT_LENX (0x005c)
+#define ZIPENC_TIME_OUT (0x0060)
+
+
+#define ZIPENC_EN BIT(0)
+#define ZIPENC_MODE BIT(1)
+#define ZIPENC_RUN BIT(4)
+
+#define ZIPENC_IN_SWT_SHIFT (8)
+#define ZIPENC_IN_SWT_MASK (0x03<<ZIPENC_IN_SWT_SHIFT)
+
+#define ZIPENC_OUT_SWT_SHIFT (10)
+#define ZIPENC_OUT_SWT_MASK (0x03<<ZIPENC_OUT_SWT_SHIFT)
+
+#define ZIPENC_COMP_LEN_SHIFT (0)
+#define ZIPENC_COMP_LEN_MASK (0x1ffff<<ZIPENC_COMP_LEN_SHIFT)
+
+#define ZIPENC_ERR_STS_SHIFT (0)
+#define ZIPENC_ERR_STS_MASK (0xff<<ZIPENC_ERR_STS_SHIFT)
+
+#define ZIPENC_OL_STS_SHIFT (8)
+#define ZIPENC_OL_STS_MASK (0xff<<ZIPENC_OL_STS_SHIFT)
+
+
+#define ZIPENC_TIME_OUT_NUM_SHIFT (0)
+#define ZIPENC_TIME_OUT_NUM_MASK (0x00ffffff<<ZIPENC_TIME_OUT_NUM_SHIFT)
+
+#define ZIPENC_TIME_OUT_FLAG_SHIFT (24)
+#define ZIPENC_TIME_OUT_FLAG_MASK (0x00ffffff<<ZIPENC_TIME_OUT_FLAG_SHIFT)
+
+
+#define ZIPENC_IN_QUEUE_CLR BIT(15)
+#define ZIPENC_OUT_QUEUE_CLR BIT(15)
+
+#define ZIPENC_TIMEOUT_EN BIT(2)
+#define ZIPENC_SEG_DONE_EN BIT(1)
+#define ZIPENC_DONE_EN BIT(0)
+
+#define ZIPENC_TIMEOUT_CLR BIT(2)
+#define ZIPENC_SEG_DONE_CLR BIT(1)
+#define ZIPENC_DONE_CLR BIT(0)
+
+#define ZIPENC_NORMAL_LEN 0
+#define ZIPENC_LIMIT_LEN 1
+
+#define ZIPENC_SWITCH_MODE0 0
+#define ZIPENC_SWITCH_MODE1 1
+#define ZIPENC_SWITCH_MODE2 2
+#define ZIPENC_SWITCH_MODE3 3
+
+#define ZIPENC_WAIT_POOL 0
+#define ZIPENC_WAIT_INT 1
+
+#define ZIPENC_NORMAL 0
+#define ZIPENC_QUEUE 1
+
+#define ZIP_WORK_LENGTH (0x1000)
+
+typedef enum ZIPENC_INT_TYPE
+{
+ ZIPENC_DONE_INT = 0,
+ ZIPENC_SEG_DONE_INT,
+ ZIPENC_TIMEOUT_INT,
+ ZIPENC_ALL_INT
+}ZIPENC_INT_TYPE;
+
+//void sprd_zipenc_enable(u32 enable);
+void sped_zipenc_reset(void);
+void ZipEnc_Restart(void);
+int Zip_Enc_Wait_Pool(ZIPENC_INT_TYPE num);
+void ZipEnc_Run(void);
+void ZipEnc_LengthLimitMode(u32 enable);
+void ZipEnc_SetSrcCfg(unsigned long src_start_addr, u32 src_len);
+void ZipEnc_SetDestCfg(unsigned long dest_start_addr,u32 dst_len);
+void ZipEnc_In_Out_SwtMode(u32 inmode,u32 outmode);
+void ZipEnc_InQueue_Clr(void);
+void ZipEnc_OutQueue_Clr(void);
+void ZipEnc_Set_Timeout(u32 time);
+u32 ZipEnc_Get_Comp_Len(void);
+u32 ZipEnc_Get_Ol_Sts(void);
+u32 ZipEnc_Get_Err_Sts(void);
+u32 ZipEnc_Get_Timeout_Flag(void);
+#endif