From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001
From: Srikant Patnaik
Date: Sun, 11 Jan 2015 12:28:04 +0530
Subject: Moved, renamed, and deleted files

The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
---
 drivers/video/wmt/Makefile                         |   25 +
 drivers/video/wmt/bootanimation/LzmaDec.c          | 1007 +++++++
 drivers/video/wmt/bootanimation/LzmaDec.h          |  223 ++
 drivers/video/wmt/bootanimation/Makefile           |   19 +
 drivers/video/wmt/bootanimation/Types.h            |  237 ++
 drivers/video/wmt/bootanimation/anim_data.h        |  911 ++++++
 drivers/video/wmt/bootanimation/animation.c        |  448 +++
 drivers/video/wmt/bootanimation/animation.h        |   15 +
 drivers/video/wmt/bootanimation/buffer.c           |   85 +
 drivers/video/wmt/bootanimation/buffer.h           |   34 +
 drivers/video/wmt/cec.c                            |  333 +++
 drivers/video/wmt/cec.h                            |   64 +
 drivers/video/wmt/com-cec.h                        |   65 +
 drivers/video/wmt/com-mb.h                         |   92 +
 drivers/video/wmt/com-vpp.h                        |  455 +++
 drivers/video/wmt/dev-cec.c                        |  488 +++
 drivers/video/wmt/devices/Makefile                 |   26 +
 drivers/video/wmt/devices/cs8556.c                 |  627 ++++
 drivers/video/wmt/devices/lcd-AUO-A080SN01.c       |   95 +
 drivers/video/wmt/devices/lcd-CHILIN-LW700at9003.c |  104 +
 .../video/wmt/devices/lcd-EKING-EK08009-70135.c    |  103 +
 .../video/wmt/devices/lcd-HANNSTAR-HSD101PFW2.c    |  103 +
 drivers/video/wmt/devices/lcd-INNOLUX-AT070TN83.c  |  118 +
 drivers/video/wmt/devices/lcd-b079xan01.c          |  363 +++
 drivers/video/wmt/devices/lcd-gl5001w.c            | 1412 +++++++++
 drivers/video/wmt/devices/lcd-lvds-1024x600.c      |   94 +
 drivers/video/wmt/devices/lcd-oem.c                |  430 +++
 drivers/video/wmt/devices/lcd-setup.c              |  311 ++
 drivers/video/wmt/devices/lcd-spi.c                |  786 +++++
 drivers/video/wmt/devices/lcd.c                    |  440 +++
 drivers/video/wmt/devices/ts8224b.h                |  446 +++
 drivers/video/wmt/devices/vt1625.c                 |  946 ++++++
 drivers/video/wmt/devices/vt1632.c                 |  157 +
 drivers/video/wmt/edid.h                           |  168 ++
 drivers/video/wmt/ge/Makefile                      |    5 +
 drivers/video/wmt/ge/ge_accel.c                    |  372 +++
 drivers/video/wmt/ge/ge_accel.h                    |   78 +
 drivers/video/wmt/ge/ge_main.c                     |  795 +++++
 drivers/video/wmt/govrh.c                          | 1932 ++++++++++++
 drivers/video/wmt/govrh.h                          |  184 ++
 drivers/video/wmt/hdmi.c                           | 1457 +++++++++
 drivers/video/wmt/hdmi.h                           |  352 +++
 drivers/video/wmt/hw/wmt-cec-reg.h                 |  220 ++
 drivers/video/wmt/hw/wmt-govrh-reg.h               |  366 +++
 drivers/video/wmt/hw/wmt-hdmi-reg.h                |  379 +++
 drivers/video/wmt/hw/wmt-lvds-reg.h                |  129 +
 drivers/video/wmt/hw/wmt-scl-reg.h                 |  543 ++++
 drivers/video/wmt/hw/wmt-vpp-hw.h                  |  137 +
 drivers/video/wmt/hw/wmt-vpp-reg.h                 |  132 +
 drivers/video/wmt/lcd.h                            |  105 +
 drivers/video/wmt/lvds.c                           |  202 ++
 drivers/video/wmt/lvds.h                           |   73 +
 drivers/video/wmt/mali.c                           |  761 +++++
 drivers/video/wmt/mali.h                           |   49 +
 drivers/video/wmt/parse-edid.c                     | 1069 +++++++
 drivers/video/wmt/scl.c                            | 1556 ++++++++++
 drivers/video/wmt/scl.h                            |  128 +
 drivers/video/wmt/sw_i2c.c                         |  436 +++
 drivers/video/wmt/sw_i2c.h                         |   63 +
 drivers/video/wmt/vout-wmt.c                       | 1344 +++++++++
 drivers/video/wmt/vout.c                           |  941 ++++++
 drivers/video/wmt/vout.h                           |  391 +++
 drivers/video/wmt/vpp-osif.c                       |  912 ++++++
 drivers/video/wmt/vpp-osif.h                       |  263 ++
 drivers/video/wmt/vpp.c                            | 1413 +++++++++
 drivers/video/wmt/vpp.h                            |  679 +++++
 drivers/video/wmt/vppm.c                           |  284 ++
 drivers/video/wmt/vppm.h                           |   63 +
 drivers/video/wmt/wmt-mb.c                         | 3154 ++++++++++++++++++++
 drivers/video/wmt/wmt-sync.c                       |  340 +++
 drivers/video/wmt/wmt-vpp.c                        | 1538 ++++++++++
 drivers/video/wmt/wmtfb.c                          | 1110 +++++++
 72 files changed, 35185 insertions(+)
 create mode 100755 drivers/video/wmt/Makefile
 create mode 100755 drivers/video/wmt/bootanimation/LzmaDec.c
 create mode 100755 drivers/video/wmt/bootanimation/LzmaDec.h
 create mode 100755 drivers/video/wmt/bootanimation/Makefile
 create mode 100755 drivers/video/wmt/bootanimation/Types.h
 create mode 100755 drivers/video/wmt/bootanimation/anim_data.h
 create mode 100755 drivers/video/wmt/bootanimation/animation.c
 create mode 100755 drivers/video/wmt/bootanimation/animation.h
 create mode 100755 drivers/video/wmt/bootanimation/buffer.c
 create mode 100755 drivers/video/wmt/bootanimation/buffer.h
 create mode 100755 drivers/video/wmt/cec.c
 create mode 100755 drivers/video/wmt/cec.h
 create mode 100755 drivers/video/wmt/com-cec.h
 create mode 100755 drivers/video/wmt/com-mb.h
 create mode 100755 drivers/video/wmt/com-vpp.h
 create mode 100755 drivers/video/wmt/dev-cec.c
 create mode 100755 drivers/video/wmt/devices/Makefile
 create mode 100755 drivers/video/wmt/devices/cs8556.c
 create mode 100755 drivers/video/wmt/devices/lcd-AUO-A080SN01.c
 create mode 100755 drivers/video/wmt/devices/lcd-CHILIN-LW700at9003.c
 create mode 100755 drivers/video/wmt/devices/lcd-EKING-EK08009-70135.c
 create mode 100755 drivers/video/wmt/devices/lcd-HANNSTAR-HSD101PFW2.c
 create mode 100755 drivers/video/wmt/devices/lcd-INNOLUX-AT070TN83.c
 create mode 100755 drivers/video/wmt/devices/lcd-b079xan01.c
 create mode 100755 drivers/video/wmt/devices/lcd-gl5001w.c
 create mode 100755 drivers/video/wmt/devices/lcd-lvds-1024x600.c
 create mode 100755 drivers/video/wmt/devices/lcd-oem.c
 create mode 100755 drivers/video/wmt/devices/lcd-setup.c
 create mode 100755 drivers/video/wmt/devices/lcd-spi.c
 create mode 100755 drivers/video/wmt/devices/lcd.c
 create mode 100755 drivers/video/wmt/devices/ts8224b.h
 create mode 100755 drivers/video/wmt/devices/vt1625.c
 create mode 100755 drivers/video/wmt/devices/vt1632.c
 create mode 100755 drivers/video/wmt/edid.h
 create mode 100755 drivers/video/wmt/ge/Makefile
 create mode 100755 drivers/video/wmt/ge/ge_accel.c
 create mode 100755 drivers/video/wmt/ge/ge_accel.h
 create mode 100755 drivers/video/wmt/ge/ge_main.c
 create mode 100755 drivers/video/wmt/govrh.c
 create mode 100755 drivers/video/wmt/govrh.h
 create mode 100755 drivers/video/wmt/hdmi.c
 create mode 100755 drivers/video/wmt/hdmi.h
 create mode 100755 drivers/video/wmt/hw/wmt-cec-reg.h
 create mode 100755 drivers/video/wmt/hw/wmt-govrh-reg.h
 create mode 100755 drivers/video/wmt/hw/wmt-hdmi-reg.h
 create mode 100755 drivers/video/wmt/hw/wmt-lvds-reg.h
 create mode 100755 drivers/video/wmt/hw/wmt-scl-reg.h
 create mode 100755 drivers/video/wmt/hw/wmt-vpp-hw.h
 create mode 100755 drivers/video/wmt/hw/wmt-vpp-reg.h
 create mode 100755 drivers/video/wmt/lcd.h
 create mode 100755 drivers/video/wmt/lvds.c
 create mode 100755 drivers/video/wmt/lvds.h
 create mode 100755 drivers/video/wmt/mali.c
 create mode 100755 drivers/video/wmt/mali.h
 create mode 100755 drivers/video/wmt/parse-edid.c
 create mode 100755 drivers/video/wmt/scl.c
 create mode 100755 drivers/video/wmt/scl.h
 create mode 100755 drivers/video/wmt/sw_i2c.c
 create mode 100755 drivers/video/wmt/sw_i2c.h
 create mode 100755 drivers/video/wmt/vout-wmt.c
 create mode 100755 drivers/video/wmt/vout.c
 create mode 100755 drivers/video/wmt/vout.h
 create mode 100755 drivers/video/wmt/vpp-osif.c
 create mode 100755 drivers/video/wmt/vpp-osif.h
 create mode 100755 drivers/video/wmt/vpp.c
 create mode 100755 drivers/video/wmt/vpp.h
 create mode 100755 drivers/video/wmt/vppm.c
 create mode 100755 drivers/video/wmt/vppm.h
 create mode 100755 drivers/video/wmt/wmt-mb.c
 create mode 100755 drivers/video/wmt/wmt-sync.c
 create mode 100755 drivers/video/wmt/wmt-vpp.c
 create mode 100755 drivers/video/wmt/wmtfb.c

(limited to 'drivers/video/wmt')

diff --git a/drivers/video/wmt/Makefile b/drivers/video/wmt/Makefile
new file mode 100755
index 00000000..1847d587
--- /dev/null
+++ b/drivers/video/wmt/Makefile
@@ -0,0 +1,25 @@
+#
+# Makefile for the Wonder Media framebuffer driver
+#
+
+# wmt external video device
+obj-$(CONFIG_FB_WMT) += devices/
+obj-$(CONFIG_WMT_EDID) += parse-edid.o sw_i2c.o
+
+# wmt vout for platform
+obj-$(CONFIG_FB_WMT) += vout-wmt.o
+
+# wmt vpp
+obj-$(CONFIG_FB_WMT) += vout.o vpp.o govrh.o scl.o vppm.o lvds.o
+obj-$(CONFIG_WMT_HDMI) += hdmi.o
+obj-$(CONFIG_FB_WMT) += vpp-osif.o wmt-vpp.o wmt-sync.o
+obj-$(CONFIG_WMT_CEC) += cec.o dev-cec.o
+
+obj-$(CONFIG_FB_WMT) += mali.o
+obj-$(CONFIG_FB_WMT_GE) += ge/
+
+# wmt fb
+obj-$(CONFIG_FB_WMT) += wmtfb.o
+
+# wmt mb
+obj-$(CONFIG_WMT_MB) += wmt-mb.o
diff --git a/drivers/video/wmt/bootanimation/LzmaDec.c b/drivers/video/wmt/bootanimation/LzmaDec.c
new file mode 100755
index 00000000..10f6cda6
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/LzmaDec.c
@@ -0,0 +1,1007 @@
+/* LzmaDec.c -- LZMA Decoder
+2008-11-06 : Igor Pavlov : Public domain */
+
+#include "LzmaDec.h"
+
+#include <linux/string.h>
+
+#define kNumTopBits 24
+#define kTopValue ((UInt32)1 << kNumTopBits)
+
+#define kNumBitModelTotalBits 11
+#define kBitModelTotal (1 << kNumBitModelTotalBits)
+#define kNumMoveBits 5
+
+#define RC_INIT_SIZE 5
+
+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
+  { UPDATE_0(p); i = (i + i); A0; } else \
+  { UPDATE_1(p); i = (i + i) + 1; A1; }
+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
+
+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
+#define TREE_DECODE(probs, limit, i) \
+  { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
+
+/* #define _LZMA_SIZE_OPT */
+
+#ifdef _LZMA_SIZE_OPT
+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
+#else
+#define TREE_6_DECODE(probs, i) \
+  { i = 1; \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  TREE_GET_BIT(probs, i); \
+  i -= 0x40; }
+#endif
+
+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
+
+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
+#define UPDATE_0_CHECK range = bound;
+#define UPDATE_1_CHECK range -= bound; code -= bound;
+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
+  { UPDATE_0_CHECK; i = (i + i); A0; } else \
+  { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
+#define TREE_DECODE_CHECK(probs, limit, i) \
+  { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; }
+
+
+#define kNumPosBitsMax 4
+#define kNumPosStatesMax (1 << kNumPosBitsMax)
+
+#define kLenNumLowBits 3
+#define kLenNumLowSymbols (1 << kLenNumLowBits)
+#define kLenNumMidBits 3
+#define kLenNumMidSymbols (1 << kLenNumMidBits)
+#define kLenNumHighBits 8
+#define kLenNumHighSymbols (1 << kLenNumHighBits)
+
+#define LenChoice 0
+#define LenChoice2 (LenChoice + 1)
+#define LenLow (LenChoice2 + 1)
+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
+
+
+#define kNumStates 12
+#define kNumLitStates 7
+
+#define kStartPosModelIndex 4
+#define kEndPosModelIndex 14
+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
+
+#define kNumPosSlotBits 6
+#define kNumLenToPosStates 4
+
+#define kNumAlignBits 4
+#define kAlignTableSize (1 << kNumAlignBits)
+
+#define kMatchMinLen 2
+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
+
+#define IsMatch 0
+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
+#define IsRepG0 (IsRep + kNumStates)
+#define IsRepG1 (IsRepG0 + kNumStates)
+#define IsRepG2 (IsRepG1 + kNumStates)
+#define IsRep0Long (IsRepG2 + kNumStates)
+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
+#define LenCoder (Align + kAlignTableSize)
+#define RepLenCoder (LenCoder + kNumLenProbs)
+#define Literal (RepLenCoder + kNumLenProbs)
+
+#define LZMA_BASE_SIZE 1846
+#define LZMA_LIT_SIZE 768
+
+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
+
+#if Literal != LZMA_BASE_SIZE
+StopCompilingDueBUG
+#endif
+
+static const Byte kLiteralNextStates[kNumStates * 2] =
+{
+  0, 0, 0, 0, 1, 2, 3,  4,  5,  6,  4,  5,
+  7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
+};
+
+#define LZMA_DIC_MIN (1 << 12)
+
+/* First LZMA-symbol is always decoded.
+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
+Out:
+  Result:
+    SZ_OK - OK
+    SZ_ERROR_DATA - Error
+  p->remainLen:
+    < kMatchSpecLenStart : normal remain
+    = kMatchSpecLenStart : finished
+    = kMatchSpecLenStart + 1 : Flush marker
+    = kMatchSpecLenStart + 2 : State Init Marker
+*/
+
+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  CLzmaProb *probs = p->probs;
+
+  unsigned state = p->state;
+  UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
+  unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
+  unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
+  unsigned lc = p->prop.lc;
+
+  Byte *dic = p->dic;
+  SizeT dicBufSize = p->dicBufSize;
+  SizeT dicPos = p->dicPos;
+  
+  UInt32 processedPos = p->processedPos;
+  UInt32 checkDicSize = p->checkDicSize;
+  unsigned len = 0;
+
+  const Byte *buf = p->buf;
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+
+  do
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = processedPos & pbMask;
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0(prob)
+    {
+      unsigned symbol;
+      UPDATE_0(prob);
+      prob = probs + Literal;
+      if (checkDicSize != 0 || processedPos != 0)
+        prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
+        (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
+
+      if (state < kNumLitStates)
+      {
+        symbol = 1;
+        do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+        unsigned offs = 0x100;
+        symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      dic[dicPos++] = (Byte)symbol;
+      processedPos++;
+
+      state = kLiteralNextStates[state];
+      /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
+      continue;
+    }
+    else
+    {
+      UPDATE_1(prob);
+      prob = probs + IsRep + state;
+      IF_BIT_0(prob)
+      {
+        UPDATE_0(prob);
+        state += kNumStates;
+        prob = probs + LenCoder;
+      }
+      else
+      {
+        UPDATE_1(prob);
+        if (checkDicSize == 0 && processedPos == 0)
+          return SZ_ERROR_DATA;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0(prob)
+        {
+          UPDATE_0(prob);
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+            dicPos++;
+            processedPos++;
+            state = state < kNumLitStates ? 9 : 11;
+            continue;
+          }
+          UPDATE_1(prob);
+        }
+        else
+        {
+          UInt32 distance;
+          UPDATE_1(prob);
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0(prob)
+          {
+            UPDATE_0(prob);
+            distance = rep1;
+          }
+          else
+          {
+            UPDATE_1(prob);
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0(prob)
+            {
+              UPDATE_0(prob);
+              distance = rep2;
+            }
+            else
+            {
+              UPDATE_1(prob);
+              distance = rep3;
+              rep3 = rep2;
+            }
+            rep2 = rep1;
+          }
+          rep1 = rep0;
+          rep0 = distance;
+        }
+        state = state < kNumLitStates ? 8 : 11;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0(probLen)
+        {
+          UPDATE_0(probLen);
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = (1 << kLenNumLowBits);
+        }
+        else
+        {
+          UPDATE_1(probLen);
+          probLen = prob + LenChoice2;
+          IF_BIT_0(probLen)
+          {
+            UPDATE_0(probLen);
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = (1 << kLenNumMidBits);
+          }
+          else
+          {
+            UPDATE_1(probLen);
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = (1 << kLenNumHighBits);
+          }
+        }
+        TREE_DECODE(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state >= kNumStates)
+      {
+        UInt32 distance;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
+        TREE_6_DECODE(prob, distance);
+        if (distance >= kStartPosModelIndex)
+        {
+          unsigned posSlot = (unsigned)distance;
+          int numDirectBits = (int)(((distance >> 1) - 1));
+          distance = (2 | (distance & 1));
+          if (posSlot < kEndPosModelIndex)
+          {
+            distance <<= numDirectBits;
+            prob = probs + SpecPos + distance - posSlot - 1;
+            {
+              UInt32 mask = 1;
+              unsigned i = 1;
+              do
+              {
+                GET_BIT2(prob + i, i, ; , distance |= mask);
+                mask <<= 1;
+              }
+              while (--numDirectBits != 0);
+            }
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE
+              range >>= 1;
+              
+              {
+                UInt32 t;
+                code -= range;
+                t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
+                distance = (distance << 1) + (t + 1);
+                code += range & t;
+              }
+              /*
+              distance <<= 1;
+              if (code >= range)
+              {
+                code -= range;
+                distance |= 1;
+              }
+              */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            distance <<= kNumAlignBits;
+            {
+              unsigned i = 1;
+              GET_BIT2(prob + i, i, ; , distance |= 1);
+              GET_BIT2(prob + i, i, ; , distance |= 2);
+              GET_BIT2(prob + i, i, ; , distance |= 4);
+              GET_BIT2(prob + i, i, ; , distance |= 8);
+            }
+            if (distance == (UInt32)0xFFFFFFFF)
+            {
+              len += kMatchSpecLenStart;
+              state -= kNumStates;
+              break;
+            }
+          }
+        }
+        rep3 = rep2;
+        rep2 = rep1;
+        rep1 = rep0;
+        rep0 = distance + 1;
+        if (checkDicSize == 0)
+        {
+          if (distance >= processedPos)
+            return SZ_ERROR_DATA;
+        }
+        else if (distance >= checkDicSize)
+          return SZ_ERROR_DATA;
+        state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
+        /* state = kLiteralNextStates[state]; */
+      }
+
+      len += kMatchMinLen;
+
+      if (limit == dicPos)
+        return SZ_ERROR_DATA;
+      {
+        SizeT rem = limit - dicPos;
+        unsigned curLen = ((rem < len) ? (unsigned)rem : len);
+        SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
+
+        processedPos += curLen;
+
+        len -= curLen;
+        if (pos + curLen <= dicBufSize)
+        {
+          Byte *dest = dic + dicPos;
+          ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
+          const Byte *lim = dest + curLen;
+          dicPos += curLen;
+          do
+            *(dest) = (Byte)*(dest + src);
+          while (++dest != lim);
+        }
+        else
+        {
+          do
+          {
+            dic[dicPos++] = dic[pos];
+            if (++pos == dicBufSize)
+              pos = 0;
+          }
+          while (--curLen != 0);
+        }
+      }
+    }
+  }
+  while (dicPos < limit && buf < bufLimit);
+  NORMALIZE;
+  p->buf = buf;
+  p->range = range;
+  p->code = code;
+  p->remainLen = len;
+  p->dicPos = dicPos;
+  p->processedPos = processedPos;
+  p->reps[0] = rep0;
+  p->reps[1] = rep1;
+  p->reps[2] = rep2;
+  p->reps[3] = rep3;
+  p->state = state;
+
+  return SZ_OK;
+}
+
+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
+{
+  if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
+  {
+    Byte *dic = p->dic;
+    SizeT dicPos = p->dicPos;
+    SizeT dicBufSize = p->dicBufSize;
+    unsigned len = p->remainLen;
+    UInt32 rep0 = p->reps[0];
+    if (limit - dicPos < len)
+      len = (unsigned)(limit - dicPos);
+
+    if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
+      p->checkDicSize = p->prop.dicSize;
+
+    p->processedPos += len;
+    p->remainLen -= len;
+    while (len-- != 0)
+    {
+      dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
+      dicPos++;
+    }
+    p->dicPos = dicPos;
+  }
+}
+
+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
+{
+  do
+  {
+    SizeT limit2 = limit;
+    if (p->checkDicSize == 0)
+    {
+      UInt32 rem = p->prop.dicSize - p->processedPos;
+      if (limit - p->dicPos > rem)
+        limit2 = p->dicPos + rem;
+    }
+    RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
+    if (p->processedPos >= p->prop.dicSize)
+      p->checkDicSize = p->prop.dicSize;
+    LzmaDec_WriteRem(p, limit);
+  }
+  while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
+
+  if (p->remainLen > kMatchSpecLenStart)
+  {
+    p->remainLen = kMatchSpecLenStart;
+  }
+  return 0;
+}
+
+typedef enum
+{
+  DUMMY_ERROR, /* unexpected end of input stream */
+  DUMMY_LIT,
+  DUMMY_MATCH,
+  DUMMY_REP
+} ELzmaDummy;
+
+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
+{
+  UInt32 range = p->range;
+  UInt32 code = p->code;
+  const Byte *bufLimit = buf + inSize;
+  CLzmaProb *probs = p->probs;
+  unsigned state = p->state;
+  ELzmaDummy res;
+
+  {
+    CLzmaProb *prob;
+    UInt32 bound;
+    unsigned ttt;
+    unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
+
+    prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
+    IF_BIT_0_CHECK(prob)
+    {
+      UPDATE_0_CHECK
+
+      /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
+
+      prob = probs + Literal;
+      if (p->checkDicSize != 0 || p->processedPos != 0)
+        prob += (LZMA_LIT_SIZE *
+          ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
+          (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
+
+      if (state < kNumLitStates)
+      {
+        unsigned symbol = 1;
+        do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
+      }
+      else
+      {
+        unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
+            ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
+        unsigned offs = 0x100;
+        unsigned symbol = 1;
+        do
+        {
+          unsigned bit;
+          CLzmaProb *probLit;
+          matchByte <<= 1;
+          bit = (matchByte & offs);
+          probLit = prob + offs + bit + symbol;
+          GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
+        }
+        while (symbol < 0x100);
+      }
+      res = DUMMY_LIT;
+    }
+    else
+    {
+      unsigned len;
+      UPDATE_1_CHECK;
+
+      prob = probs + IsRep + state;
+      IF_BIT_0_CHECK(prob)
+      {
+        UPDATE_0_CHECK;
+        state = 0;
+        prob = probs + LenCoder;
+        res = DUMMY_MATCH;
+      }
+      else
+      {
+        UPDATE_1_CHECK;
+        res = DUMMY_REP;
+        prob = probs + IsRepG0 + state;
+        IF_BIT_0_CHECK(prob)
+        {
+          UPDATE_0_CHECK;
+          prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+            NORMALIZE_CHECK;
+            return DUMMY_REP;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+          }
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          prob = probs + IsRepG1 + state;
+          IF_BIT_0_CHECK(prob)
+          {
+            UPDATE_0_CHECK;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            prob = probs + IsRepG2 + state;
+            IF_BIT_0_CHECK(prob)
+            {
+              UPDATE_0_CHECK;
+            }
+            else
+            {
+              UPDATE_1_CHECK;
+            }
+          }
+        }
+        state = kNumStates;
+        prob = probs + RepLenCoder;
+      }
+      {
+        unsigned limit, offset;
+        CLzmaProb *probLen = prob + LenChoice;
+        IF_BIT_0_CHECK(probLen)
+        {
+          UPDATE_0_CHECK;
+          probLen = prob + LenLow + (posState << kLenNumLowBits);
+          offset = 0;
+          limit = 1 << kLenNumLowBits;
+        }
+        else
+        {
+          UPDATE_1_CHECK;
+          probLen = prob + LenChoice2;
+          IF_BIT_0_CHECK(probLen)
+          {
+            UPDATE_0_CHECK;
+            probLen = prob + LenMid + (posState << kLenNumMidBits);
+            offset = kLenNumLowSymbols;
+            limit = 1 << kLenNumMidBits;
+          }
+          else
+          {
+            UPDATE_1_CHECK;
+            probLen = prob + LenHigh;
+            offset = kLenNumLowSymbols + kLenNumMidSymbols;
+            limit = 1 << kLenNumHighBits;
+          }
+        }
+        TREE_DECODE_CHECK(probLen, limit, len);
+        len += offset;
+      }
+
+      if (state < 4)
+      {
+        unsigned posSlot;
+        prob = probs + PosSlot +
+            ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
+            kNumPosSlotBits);
+        TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
+        if (posSlot >= kStartPosModelIndex)
+        {
+          int numDirectBits = ((posSlot >> 1) - 1);
+
+          /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
+
+          if (posSlot < kEndPosModelIndex)
+          {
+            prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
+          }
+          else
+          {
+            numDirectBits -= kNumAlignBits;
+            do
+            {
+              NORMALIZE_CHECK
+              range >>= 1;
+              code -= range & (((code - range) >> 31) - 1);
+              /* if (code >= range) code -= range; */
+            }
+            while (--numDirectBits != 0);
+            prob = probs + Align;
+            numDirectBits = kNumAlignBits;
+          }
+          {
+            unsigned i = 1;
+            do
+            {
+              GET_BIT_CHECK(prob + i, i);
+            }
+            while (--numDirectBits != 0);
+          }
+        }
+      }
+    }
+  }
+  NORMALIZE_CHECK;
+  return res;
+}
+
+
+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
+{
+  p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
+  p->range = 0xFFFFFFFF;
+  p->needFlush = 0;
+}
+
+void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
+{
+  p->needFlush = 1;
+  p->remainLen = 0;
+  p->tempBufSize = 0;
+
+  if (initDic)
+  {
+    p->processedPos = 0;
+    p->checkDicSize = 0;
+    p->needInitState = 1;
+  }
+  if (initState)
+    p->needInitState = 1;
+}
+
+void LzmaDec_Init(CLzmaDec *p)
+{
+  p->dicPos = 0;
+  LzmaDec_InitDicAndState(p, True, True);
+}
+
+static void LzmaDec_InitStateReal(CLzmaDec *p)
+{
+  UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
+  UInt32 i;
+  CLzmaProb *probs = p->probs;
+  for (i = 0; i < numProbs; i++)
+    probs[i] = kBitModelTotal >> 1;
+  p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
+  p->state = 0;
+  p->needInitState = 0;
+}
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
+    ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT inSize = *srcLen;
+  (*srcLen) = 0;
+  LzmaDec_WriteRem(p, dicLimit);
+  
+  *status = LZMA_STATUS_NOT_SPECIFIED;
+
+  while (p->remainLen != kMatchSpecLenStart)
+  {
+      int checkEndMarkNow;
+
+      if (p->needFlush != 0)
+      {
+        for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
+          p->tempBuf[p->tempBufSize++] = *src++;
+        if (p->tempBufSize < RC_INIT_SIZE)
+        {
+          *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+          return SZ_OK;
+        }
+        if (p->tempBuf[0] != 0)
+          return SZ_ERROR_DATA;
+
+        LzmaDec_InitRc(p, p->tempBuf);
+        p->tempBufSize = 0;
+      }
+
+      checkEndMarkNow = 0;
+      if (p->dicPos >= dicLimit)
+      {
+        if (p->remainLen == 0 && p->code == 0)
+        {
+          *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
+          return SZ_OK;
+        }
+        if (finishMode == LZMA_FINISH_ANY)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_OK;
+        }
+        if (p->remainLen != 0)
+        {
+          *status = LZMA_STATUS_NOT_FINISHED;
+          return SZ_ERROR_DATA;
+        }
+        checkEndMarkNow = 1;
+      }
+
+      if (p->needInitState)
+        LzmaDec_InitStateReal(p);
+  
+      if (p->tempBufSize == 0)
+      {
+        SizeT processed;
+        const Byte *bufLimit;
+        if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, src, inSize);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            memcpy(p->tempBuf, src, inSize);
+            p->tempBufSize = (unsigned)inSize;
+            (*srcLen) += inSize;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+          bufLimit = src;
+        }
+        else
+          bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
+        p->buf = src;
+        if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
+          return SZ_ERROR_DATA;
+        processed = (SizeT)(p->buf - src);
+        (*srcLen) += processed;
+        src += processed;
+        inSize -= processed;
+      }
+      else
+      {
+        unsigned rem = p->tempBufSize, lookAhead = 0;
+        while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
+          p->tempBuf[rem++] = src[lookAhead++];
+        p->tempBufSize = rem;
+        if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
+        {
+          int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
+          if (dummyRes == DUMMY_ERROR)
+          {
+            (*srcLen) += lookAhead;
+            *status = LZMA_STATUS_NEEDS_MORE_INPUT;
+            return SZ_OK;
+          }
+          if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
+          {
+            *status = LZMA_STATUS_NOT_FINISHED;
+            return SZ_ERROR_DATA;
+          }
+        }
+        p->buf = p->tempBuf;
+        if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
+          return SZ_ERROR_DATA;
+        lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
+        (*srcLen) += lookAhead;
+        src += lookAhead;
+        inSize -= lookAhead;
+        p->tempBufSize = 0;
+      }
+  }
+  if (p->code == 0)
+    *status = LZMA_STATUS_FINISHED_WITH_MARK;
+  return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
+}
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
+{
+  SizeT outSize = *destLen;
+  SizeT inSize = *srcLen;
+  *srcLen = *destLen = 0;
+  for (;;)
+  {
+    SizeT inSizeCur = inSize, outSizeCur, dicPos;
+    ELzmaFinishMode curFinishMode;
+    SRes res;
+    if (p->dicPos == p->dicBufSize)
+      p->dicPos = 0;
+    dicPos = p->dicPos;
+    if (outSize > p->dicBufSize - dicPos)
+    {
+      outSizeCur = p->dicBufSize;
+      curFinishMode = LZMA_FINISH_ANY;
+    }
+    else
+    {
+      outSizeCur = dicPos + outSize;
+      curFinishMode = finishMode;
+    }
+
+    res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
+    src += inSizeCur;
+    inSize -= inSizeCur;
+    *srcLen += inSizeCur;
+    outSizeCur = p->dicPos - dicPos;
+    memcpy(dest, p->dic + dicPos, outSizeCur);
+    dest += outSizeCur;
+    outSize -= outSizeCur;
+    *destLen += outSizeCur;
+    if (res != 0)
+      return res;
+    if (outSizeCur == 0 || outSize == 0)
+      return SZ_OK;
+  }
+}
+
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->probs);
+  p->probs = 0;
+}
+
+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
+{
+  alloc->Free(alloc, p->dic);
+  p->dic = 0;
+}
+
+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
+{
+  LzmaDec_FreeProbs(p, alloc);
+  LzmaDec_FreeDict(p, alloc);
+}
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
+{
+  UInt32 dicSize;
+  Byte d;
+  
+  if (size < LZMA_PROPS_SIZE)
+    return SZ_ERROR_UNSUPPORTED;
+  else
+    dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
+ 
+  if (dicSize < LZMA_DIC_MIN)
+    dicSize = LZMA_DIC_MIN;
+  p->dicSize = dicSize;
+
+  d = data[0];
+  if (d >= (9 * 5 * 5))
+    return SZ_ERROR_UNSUPPORTED;
+
+  p->lc = d % 9;
+  d /= 9;
+  p->pb = d / 5;
+  p->lp = d % 5;
+
+  return SZ_OK;
+}
+
+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
+{
+  UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
+  if (p->probs == 0 || numProbs != p->numProbs)
+  {
+    LzmaDec_FreeProbs(p, alloc);
+    p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
+    p->numProbs = numProbs;
+    if (p->probs == 0)
+      return SZ_ERROR_MEM;
+  }
+  return SZ_OK;
+}
+
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
+{
+  CLzmaProps propNew;
+  SizeT dicBufSize;
+  RINOK(LzmaProps_Decode(&propNew, props, propsSize));
+  RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
+  dicBufSize = propNew.dicSize;
+  if (p->dic == 0 || dicBufSize != p->dicBufSize)
+  {
+    LzmaDec_FreeDict(p, alloc);
+    p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
+    if (p->dic == 0)
+    {
+      LzmaDec_FreeProbs(p, alloc);
+      return SZ_ERROR_MEM;
+    }
+  }
+  p->dicBufSize = dicBufSize;
+  p->prop = propNew;
+  return SZ_OK;
+}
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc)
+{
+  CLzmaDec p;
+  SRes res;
+  SizeT inSize = *srcLen;
+  SizeT outSize = *destLen;
+  *srcLen = *destLen = 0;
+  if (inSize < RC_INIT_SIZE)
+    return SZ_ERROR_INPUT_EOF;
+
+  LzmaDec_Construct(&p);
+  res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
+  if (res != 0)
+    return res;
+  p.dic = dest;
+  p.dicBufSize = outSize;
+
+  LzmaDec_Init(&p);
+  
+  *srcLen = inSize;
+  res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
+
+  if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
+    res = SZ_ERROR_INPUT_EOF;
+
+  (*destLen) = p.dicPos;
+  LzmaDec_FreeProbs(&p, alloc);
+  return res;
+}
diff --git a/drivers/video/wmt/bootanimation/LzmaDec.h b/drivers/video/wmt/bootanimation/LzmaDec.h
new file mode 100755
index 00000000..98cdbe94
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/LzmaDec.h
@@ -0,0 +1,223 @@
+/* LzmaDec.h -- LZMA Decoder
+2008-10-04 : Igor Pavlov : Public domain */
+
+#ifndef __LZMADEC_H
+#define __LZMADEC_H
+
+#include "Types.h"
+
+/* #define _LZMA_PROB32 */
+/* _LZMA_PROB32 can increase the speed on some CPUs,
+   but memory usage for CLzmaDec::probs will be doubled in that case */
+
+#ifdef _LZMA_PROB32
+#define CLzmaProb UInt32
+#else
+#define CLzmaProb UInt16
+#endif
+
+
+/* ---------- LZMA Properties ---------- */
+
+#define LZMA_PROPS_SIZE 5
+
+typedef struct _CLzmaProps
+{
+  unsigned lc, lp, pb;
+  UInt32 dicSize;
+} CLzmaProps;
+
+/* LzmaProps_Decode - decodes properties
+Returns:
+  SZ_OK
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+
+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
+
+
+/* ---------- LZMA Decoder state ---------- */
+
+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
+   Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
+
+#define LZMA_REQUIRED_INPUT_MAX 20
+
+typedef struct
+{
+  CLzmaProps prop;
+  CLzmaProb *probs;
+  Byte *dic;
+  const Byte *buf;
+  UInt32 range, code;
+  SizeT dicPos;
+  SizeT dicBufSize;
+  UInt32 processedPos;
+  UInt32 checkDicSize;
+  unsigned state;
+  UInt32 reps[4];
+  unsigned remainLen;
+  int needFlush;
+  int needInitState;
+  UInt32 numProbs;
+  unsigned tempBufSize;
+  Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
+} CLzmaDec;
+
+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
+
+void LzmaDec_Init(CLzmaDec *p);
+
+/* There are two types of LZMA streams:
+     0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
+     1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
+
+typedef enum
+{
+  LZMA_FINISH_ANY,   /* finish at any point */
+  LZMA_FINISH_END    /* block must be finished at the end */
+} ELzmaFinishMode;
+
+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
+
+   You must use LZMA_FINISH_END, when you know that current output buffer
+   covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
+
+   If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
+   and output value of destLen will be less than output buffer size limit.
+   You can check status result also.
+
+   You can use multiple checks to test data integrity after full decompression:
+     1) Check Result and "status" variable.
+     2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
+     3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
+        You must use correct finish mode in that case. */
+
+typedef enum
+{
+  LZMA_STATUS_NOT_SPECIFIED,               /* use main error code instead */
+  LZMA_STATUS_FINISHED_WITH_MARK,          /* stream was finished with end mark. */
+  LZMA_STATUS_NOT_FINISHED,                /* stream was not finished */
+  LZMA_STATUS_NEEDS_MORE_INPUT,            /* you must provide more input bytes */
+  LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK  /* there is probability that stream was finished without end mark */
+} ELzmaStatus;
+
+/* ELzmaStatus is used only as output value for function call */
+
+
+/* ---------- Interfaces ---------- */
+
+/* There are 3 levels of interfaces:
+     1) Dictionary Interface
+     2) Buffer Interface
+     3) One Call Interface
+   You can select any of these interfaces, but don't mix functions from different
+   groups for same object. */
+
+
+/* There are two variants to allocate state for Dictionary Interface:
+     1) LzmaDec_Allocate / LzmaDec_Free
+     2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
+   You can use variant 2, if you set dictionary buffer manually.
+   For Buffer Interface you must always use variant 1.
+
+LzmaDec_Allocate* can return:
+  SZ_OK
+  SZ_ERROR_MEM         - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+*/
+   
+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
+
+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
+
+/* ---------- Dictionary Interface ---------- */
+
+/* You can use it, if you want to eliminate the overhead for data copying from
+   dictionary to some other external buffer.
+   You must work with CLzmaDec variables directly in this interface.
+
+   STEPS:
+     LzmaDec_Constr()
+     LzmaDec_Allocate()
+     for (each new stream)
+     {
+       LzmaDec_Init()
+       while (it needs more decompression)
+       {
+         LzmaDec_DecodeToDic()
+         use data from CLzmaDec::dic and update CLzmaDec::dicPos
+       }
+     }
+     LzmaDec_Free()
+*/
+
+/* LzmaDec_DecodeToDic
+   
+   The decoding to internal dictionary buffer (CLzmaDec::dic).
+   You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (dicLimit).
+  LZMA_FINISH_ANY - Decode just dicLimit bytes.
+  LZMA_FINISH_END - Stream must be finished after dicLimit.
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_NEEDS_MORE_INPUT
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+*/
+
+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- Buffer Interface ---------- */
+
+/* It's zlib-like interface.
+   See LzmaDec_DecodeToDic description for information about STEPS and return results,
+   but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
+   to work with CLzmaDec variables manually.
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+*/
+
+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
+    const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
+
+
+/* ---------- One Call Interface ---------- */
+
+/* LzmaDecode
+
+finishMode:
+  It has meaning only if the decoding reaches output limit (*destLen).
+  LZMA_FINISH_ANY - Decode just destLen bytes.
+  LZMA_FINISH_END - Stream must be finished after (*destLen).
+
+Returns:
+  SZ_OK
+    status:
+      LZMA_STATUS_FINISHED_WITH_MARK
+      LZMA_STATUS_NOT_FINISHED
+      LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
+  SZ_ERROR_DATA - Data error
+  SZ_ERROR_MEM  - Memory allocation error
+  SZ_ERROR_UNSUPPORTED - Unsupported properties
+  SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
+*/
+
+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
+    const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
+    ELzmaStatus *status, ISzAlloc *alloc);
+
+#endif
diff --git a/drivers/video/wmt/bootanimation/Makefile b/drivers/video/wmt/bootanimation/Makefile
new file mode 100755
index 00000000..f0d021a8
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/Makefile
@@ -0,0 +1,19 @@
+#
+# This is a modified version of zlib, which does all memory
+# allocation ahead of time.
+#
+# This is only the decompression, see zlib_deflate for the
+# the compression
+#
+# Decompression needs to be serialized for each memory
+# allocation.
+#
+# (The upsides of the simplification is that you can't get in
+# any nasty situations wrt memory management, and that the
+# uncompression can be done without blocking on allocation).
+#
+lzma_dec-objs := LzmaDec.o 
+
+obj-$(CONFIG_LOGO_WMT_ANIMATION) += lzma_dec.o buffer.o animation.o
+
+
diff --git a/drivers/video/wmt/bootanimation/Types.h b/drivers/video/wmt/bootanimation/Types.h
new file mode 100755
index 00000000..60cfe05e
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/Types.h
@@ -0,0 +1,237 @@
+/* Types.h -- Basic types
+2010-03-11 : Igor Pavlov : Public domain */
+
+#ifndef __7Z_TYPES_H
+#define __7Z_TYPES_H
+
+#include <stddef.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifndef EXTERN_C_BEGIN
+#ifdef __cplusplus
+#define EXTERN_C_BEGIN extern "C" {
+#define EXTERN_C_END }
+#else
+#define EXTERN_C_BEGIN
+#define EXTERN_C_END
+#endif
+#endif
+
+EXTERN_C_BEGIN
+
+#define SZ_OK 0
+
+#define SZ_ERROR_DATA 1
+#define SZ_ERROR_MEM 2
+#define SZ_ERROR_CRC 3
+#define SZ_ERROR_UNSUPPORTED 4
+#define SZ_ERROR_PARAM 5
+#define SZ_ERROR_INPUT_EOF 6
+#define SZ_ERROR_OUTPUT_EOF 7
+#define SZ_ERROR_READ 8
+#define SZ_ERROR_WRITE 9
+#define SZ_ERROR_PROGRESS 10
+#define SZ_ERROR_FAIL 11
+#define SZ_ERROR_THREAD 12
+
+#define SZ_ERROR_ARCHIVE 16
+#define SZ_ERROR_NO_ARCHIVE 17
+
+typedef int SRes;
+
+#ifdef _WIN32
+typedef DWORD WRes;
+#else
+typedef int WRes;
+#endif
+
+#ifndef RINOK
+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
+#endif
+
+typedef unsigned char Byte;
+typedef short Int16;
+typedef unsigned short UInt16;
+
+#ifdef _LZMA_UINT32_IS_ULONG
+typedef long Int32;
+typedef unsigned long UInt32;
+#else
+typedef int Int32;
+typedef unsigned int UInt32;
+#endif
+
+#ifdef _SZ_NO_INT_64
+
+/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
+   NOTES: Some code will work incorrectly in that case! */
+
+typedef long Int64;
+typedef unsigned long UInt64;
+
+#else
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+typedef __int64 Int64;
+typedef unsigned __int64 UInt64;
+#else
+typedef long long int Int64;
+typedef unsigned long long int UInt64;
+#endif
+
+#endif
+
+#ifdef _LZMA_NO_SYSTEM_SIZE_T
+typedef UInt32 SizeT;
+#else
+typedef size_t SizeT;
+#endif
+
+typedef int Bool;
+#define True 1
+#define False 0
+
+
+#ifdef _WIN32
+#define MY_STD_CALL __stdcall
+#else
+#define MY_STD_CALL
+#endif
+
+#ifdef _MSC_VER
+
+#if _MSC_VER >= 1300
+#define MY_NO_INLINE __declspec(noinline)
+#else
+#define MY_NO_INLINE
+#endif
+
+#define MY_CDECL __cdecl
+#define MY_FAST_CALL __fastcall
+
+#else
+
+#define MY_CDECL
+#define MY_FAST_CALL
+
+#endif
+
+
+/* The following interfaces use first parameter as pointer to structure */
+
+typedef struct
+{
+  Byte (*Read)(void *p); /* reads one byte, returns 0 in case of EOF or error */
+} IByteIn;
+
+typedef struct
+{
+  void (*Write)(void *p, Byte b);
+} IByteOut;
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) < input(*size)) is allowed */
+} ISeqInStream;
+
+/* it can return SZ_ERROR_INPUT_EOF */
+SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
+SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
+SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
+
+typedef struct
+{
+  size_t (*Write)(void *p, const void *buf, size_t size);
+    /* Returns: result - the number of actually written bytes.
+       (result < size) means error */
+} ISeqOutStream;
+
+typedef enum
+{
+  SZ_SEEK_SET = 0,
+  SZ_SEEK_CUR = 1,
+  SZ_SEEK_END = 2
+} ESzSeek;
+
+typedef struct
+{
+  SRes (*Read)(void *p, void *buf, size_t *size);  /* same as ISeqInStream::Read */
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ISeekInStream;
+
+typedef struct
+{
+  SRes (*Look)(void *p, const void **buf, size_t *size);
+    /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
+       (output(*size) > input(*size)) is not allowed
+       (output(*size) < input(*size)) is allowed */
+  SRes (*Skip)(void *p, size_t offset);
+    /* offset must be <= output(*size) of Look */
+
+  SRes (*Read)(void *p, void *buf, size_t *size);
+    /* reads directly (without buffer). It's same as ISeqInStream::Read */
+  SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
+} ILookInStream;
+
+SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
+SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
+
+/* reads via ILookInStream::Read */
+SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
+SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
+
+#define LookToRead_BUF_SIZE (1 << 14)
+
+typedef struct
+{
+  ILookInStream s;
+  ISeekInStream *realStream;
+  size_t pos;
+  size_t size;
+  Byte buf[LookToRead_BUF_SIZE];
+} CLookToRead;
+
+void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
+void LookToRead_Init(CLookToRead *p);
+
+typedef struct
+{
+  ISeqInStream s;
+  ILookInStream *realStream;
+} CSecToLook;
+
+void SecToLook_CreateVTable(CSecToLook *p);
+
+typedef struct
+{
+  ISeqInStream s;
+  ILookInStream *realStream;
+} CSecToRead;
+
+void SecToRead_CreateVTable(CSecToRead *p);
+
+typedef struct
+{
+  SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
+    /* Returns: result. (result != SZ_OK) means break.
+       Value (UInt64)(Int64)-1 for size means unknown value. */
+} ICompressProgress;
+
+typedef struct
+{
+  void *(*Alloc)(void *p, size_t size);
+  void (*Free)(void *p, void *address); /* address can be 0 */
+  int  private;
+} ISzAlloc;
+
+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
+#define IAlloc_Free(p, a) (p)->Free((p), a)
+
+EXTERN_C_END
+
+#endif
diff --git a/drivers/video/wmt/bootanimation/anim_data.h b/drivers/video/wmt/bootanimation/anim_data.h
new file mode 100755
index 00000000..1932ee0d
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/anim_data.h
@@ -0,0 +1,911 @@
+static const unsigned char __initdata anim_data[] = 
+{
+	0x21,0x43,0x34,0x12,0x01,0x01,0x01,0x00,0xAA,0x38,0x00,0x00,0x05,0x01,0x00,0x00,
+	0x20,0x00,0x00,0x00,0x20,0x02,0x00,0x00,0x01,0x02,0x00,0x00,0xD8,0xFF,0x01,0x00,
+	0x64,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x7E,0x38,0x00,0x00,0x5D,0x00,0x00,0x40,
+	0x00,0x00,0xC4,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6F,0xFD,0xFF,0xFF,0xA3,
+	0xB7,0xFE,0xD9,0xBF,0x11,0xE8,0x0D,0x8B,0xC0,0xF6,0x05,0x19,0xBF,0x01,0x86,0x8C,
+	0xCB,0xE9,0x9E,0xEA,0x0E,0x25,0xB9,0x55,0xEB,0xCF,0x2E,0x7F,0x12,0xC1,0x7D,0xF3,
+	0x20,0x9F,0xCE,0x4B,0xD3,0xA1,0xC5,0x29,0x2E,0x78,0x11,0x91,0x41,0x01,0x5D,0xC2,
+	0x66,0xAC,0x26,0xA8,0x42,0xCD,0x15,0xCC,0x13,0xE0,0xEA,0x77,0xC5,0x42,0x67,0xF8,
+	0xFF,0x3B,0x44,0xE6,0x50,0xF4,0xDB,0xB4,0x8A,0x44,0x71,0x36,0x27,0xCB,0xE8,0xA3,
+	0x23,0x09,0x64,0x82,0x3C,0x54,0x6C,0x86,0x3A,0xE4,0x8C,0x3D,0x85,0x9C,0xEE,0x88,
+	0x9A,0x23,0x2F,0xE7,0x15,0x39,0x0E,0x48,0x6B,0x5B,0xA3,0x69,0x8E,0xA9,0xF6,0x30,
+	0xC2,0x2A,0x04,0x6C,0x1F,0x9B,0x02,0xC6,0x88,0xFC,0x40,0x8F,0x59,0xE7,0x6F,0x09,
+	0x95,0x00,0x16,0xE1,0x6D,0xC4,0x52,0x5F,0x28,0x64,0x9E,0x6B,0xFA,0x9C,0x3C,0x35,
+	0x33,0xC1,0x06,0xFB,0xB7,0x79,0x2B,0xAA,0xCE,0xD9,0xA1,0x3E,0x38,0xC7,0xF2,0x53,
+	0xFB,0x23,0x82,0x76,0xDD,0x2B,0x3E,0x0C,0x8D,0xA6,0xAC,0xD6,0x27,0x4F,0x24,0xC1,
+	0x6B,0x2D,0xF8,0xD1,0xE1,0xE2,0xC2,0x54,0x8D,0x7A,0xC7,0x4C,0x35,0x4B,0x09,0x7A,
+	0x73,0xDE,0xB5,0xF1,0xB7,0x11,0xCE,0xAD,0x34,0x7F,0x23,0xC7,0x48,0xC5,0x41,0xB2,
+	0x25,0xD6,0x68,0x29,0xD7,0xDA,0x92,0xAF,0x11,0x60,0x07,0xDB,0xCA,0xA1,0x59,0xD4,
+	0xF1,0xC2,0x70,0x2A,0xC8,0xDF,0x2B,0xA4,0xD4,0x0B,0x5E,0xFA,0x30,0x27,0x1E,0xDB,
+	0x68,0xB0,0xD6,0x25,0x11,0xEF,0xDC,0x48,0xD4,0x1C,0xF7,0xB8,0x7E,0xF0,0xBF,0x2C,
+	0x4D,0x61,0xF0,0x94,0x20,0xA2,0x4C,0xF1,0x6F,0x52,0xEC,0x30,0xF0,0x92,0x7D,0xCB,
+	0x4A,0x8E,0xA3,0x06,0x6F,0xBB,0x7A,0x6B,0xCB,0x5F,0xE7,0xE4,0x5D,0x3D,0x0B,0x5A,
+	0xB5,0xC7,0x81,0x59,0x35,0x72,0x6C,0x21,0xED,0x5C,0xF4,0xBF,0xD7,0xEA,0x20,0xCC,
+	0x3F,0x72,0x85,0x51,0xF9,0xE2,0x44,0xB6,0x73,0xD1,0xE0,0x07,0x90,0x41,0x94,0xC5,
+	0x40,0xCD,0xBC,0x21,0xD4,0x9D,0x86,0xE5,0x1F,0xDE,0xDE,0x38,0xB3,0x30,0x23,0x15,
+	0x6F,0x99,0x4F,0x12,0x12,0x5B,0x39,0x4F,0x98,0x34,0x2B,0x69,0x11,0xBF,0xF8,0x8E,
+	0xDD,0x77,0x8E,0x63,0x9F,0xEE,0xD7,0x60,0xE9,0x2B,0x84,0x9B,0x4F,0xDE,0xD5,0x5D,
+	0xF6,0x76,0x6D,0x3A,0x0C,0xD3,0x21,0xBA,0x98,0xD9,0x62,0xA4,0xA3,0x88,0xF4,0xB4,
+	0x8C,0x2B,0x67,0xE6,0x49,0x0A,0x89,0x72,0x09,0x90,0xAD,0x14,0x31,0xA1,0x18,0x79,
+	0xC9,0x6F,0xCF,0x41,0xDD,0x74,0x01,0x43,0x8B,0x38,0x71,0x0B,0xD4,0x23,0x8C,0x4B,
+	0x83,0x17,0xBC,0x56,0xEB,0x1E,0x2C,0x7E,0x6F,0x86,0x9B,0x49,0xFF,0x38,0x01,0xC1,
+	0xE7,0x2A,0x94,0xA4,0x7D,0x37,0xB8,0xBA,0xE1,0x8F,0xCA,0x0B,0x78,0xC5,0xD2,0x0A,
+	0x36,0xA6,0xE6,0xC9,0x92,0x08,0xE5,0x4E,0xCD,0xF2,0xB7,0xB8,0xEF,0xEC,0x9F,0x37,
+	0xDC,0x7B,0x24,0x0C,0x6B,0xB4,0xB4,0xAB,0x04,0x5A,0x2C,0x84,0x95,0xC6,0xCE,0x5D,
+	0x02,0x2A,0x74,0x78,0xB0,0xDB,0x30,0xFA,0xDA,0x67,0x84,0xF3,0x57,0x8E,0x6D,0x67,
+	0x7D,0xAE,0x28,0x03,0x31,0x05,0x0E,0xD4,0x5F,0x64,0x4D,0xC7,0xDE,0x89,0x8D,0xB8,
+	0x07,0xC1,0x38,0xE9,0x01,0x53,0x3D,0xEE,0xFB,0x0A,0x0A,0x20,0x6F,0xF3,0x2B,0x83,
+	0xD9,0xD4,0x31,0xB4,0x33,0xAD,0x5D,0x74,0xBC,0xF8,0x67,0x3A,0xCC,0x7A,0xA3,0x10,
+	0x8F,0x45,0x31,0x34,0x58,0xC3,0x44,0xD8,0x03,0x18,0xF9,0xD2,0xFA,0xC5,0xDB,0x0B,
+	0x0C,0xB9,0x15,0x09,0xEE,0xB0,0x07,0x80,0xF6,0x04,0xDF,0x0B,0x41,0x08,0xE0,0x3C,
+	0x5E,0xF5,0x82,0xDC,0x20,0x40,0x22,0x96,0x1C,0x31,0xD6,0x4E,0x7C,0x13,0xD8,0x17,
+	0xC5,0x1A,0xFB,0xB0,0x7B,0x9B,0xE8,0x45,0xA9,0x53,0x98,0x21,0xB3,0xE8,0xD2,0x3F,
+	0xDE,0x4A,0xF2,0xF9,0x0F,0xBF,0xBE,0x62,0x56,0xB7,0x90,0xBA,0xA4,0x43,0x39,0x60,
+	0x0A,0x4B,0xCE,0xD2,0x46,0xBC,0x90,0x04,0xE1,0xAD,0x12,0xCB,0xBE,0x17,0xC3,0x9A,
+	0x9F,0xE4,0xAD,0x0B,0xE0,0x21,0x6B,0x42,0xD6,0x52,0xBB,0x51,0xFE,0xFB,0x50,0x09,
+	0xA3,0x77,0xC7,0x06,0x49,0xDC,0xCC,0x5C,0xBB,0xA8,0x5A,0x87,0x11,0xFA,0x67,0x17,
+	0x1A,0x41,0x12,0x71,0x88,0xE1,0x99,0xEC,0xEB,0xE5,0xBC,0x4E,0x8F,0x8F,0x51,0x8E,
+	0xFC,0x0C,0xC4,0x5A,0xCB,0x09,0x9A,0xDA,0x24,0xCB,0x13,0xAC,0x82,0x77,0xC6,0x8F,
+	0x4C,0x08,0xF4,0xEE,0x80,0x01,0xEF,0xEC,0xE1,0x47,0x22,0xEC,0xEE,0xF9,0x7D,0x56,
+	0xAF,0x8E,0xF2,0xF2,0x85,0xA3,0x9C,0xB5,0x1E,0xD7,0xFF,0xB1,0xEA,0x12,0xB5,0xE2,
+	0xDF,0x01,0x13,0x3A,0x8F,0xAA,0x67,0x7A,0x06,0xE0,0x7F,0xC2,0xF1,0xF5,0x35,0x3F,
+	0x5E,0x68,0x72,0x1C,0x6B,0x49,0x8D,0xD6,0xC0,0xCA,0xCC,0xFF,0xC8,0xD9,0xE2,0x75,
+	0x1C,0x50,0x1A,0xEC,0xB0,0xDB,0x7B,0x88,0xD1,0x81,0xE2,0xEA,0xA8,0x1C,0xB2,0x64,
+	0xFC,0x3C,0x66,0x40,0xDC,0xB0,0x39,0x57,0x2E,0x80,0x65,0x34,0x0F,0xA0,0xBE,0xFF,
+	0x6D,0x5D,0x1A,0xEE,0xF3,0x18,0x77,0x06,0x00,0x49,0x9D,0xDC,0x27,0xD8,0xB9,0x2E,
+	0xA5,0xC8,0x52,0x9B,0xBE,0xA1,0x32,0x83,0xA2,0x35,0x1A,0x42,0xA4,0xA8,0x95,0x98,
+	0x31,0xE7,0x14,0xFC,0xBA,0xD5,0x70,0x0C,0x33,0x33,0x21,0x30,0xB9,0xD2,0xDA,0x4C,
+	0x21,0x05,0xA4,0x0F,0xD2,0x73,0x7D,0xC0,0xD3,0xD3,0xED,0x67,0x11,0x0B,0xD3,0xCF,
+	0x9E,0xBE,0xDF,0x91,0x2C,0x3F,0x3D,0x50,0xBF,0x02,0xE2,0xC6,0xC5,0xE0,0xA3,0xB4,
+	0x60,0x6A,0x6C,0xC0,0x57,0x7E,0x4B,0x84,0x0B,0x6B,0x4E,0xDE,0x70,0x04,0xED,0xE0,
+	0x2B,0xEB,0x95,0xDB,0xDF,0xA6,0x65,0x0C,0xF0,0x90,0x39,0x06,0xE0,0x6D,0xB8,0xDB,
+	0x21,0x42,0xA9,0x0F,0x35,0x8C,0x32,0xD3,0xCC,0x1E,0x49,0x3D,0xC9,0xBB,0x04,0x08,
+	0x14,0x94,0x9F,0x2A,0x10,0xF9,0x60,0xAE,0x91,0xEF,0x88,0xDA,0x4B,0xA1,0x57,0xDA,
+	0xD8,0xD4,0x81,0x67,0x8B,0x4D,0x19,0xCD,0x04,0x0D,0xFE,0x18,0xDD,0x40,0x09,0xCE,
+	0x31,0x77,0xEB,0xDC,0xD0,0xB8,0xB1,0x8B,0x31,0x36,0x1A,0xF0,0xD7,0xF3,0xC3,0xD2,
+	0x7B,0x37,0xDC,0x34,0xBA,0x31,0xAF,0xC6,0x87,0x4E,0x0B,0x2D,0x30,0x33,0xA9,0xEA,
+	0xC2,0x68,0x8C,0xCF,0x41,0xD5,0x93,0x22,0x2A,0x94,0x46,0x6D,0xF7,0x2A,0x89,0x83,
+	0x2A,0xD0,0x13,0xE8,0xAD,0xE9,0x82,0x61,0xA4,0xD8,0x94,0xFC,0xFF,0x9D,0x9B,0xD9,
+	0x68,0x36,0x8E,0x05,0xA5,0x61,0x9B,0x7C,0x6F,0x01,0x7E,0x90,0xC9,0x57,0x2B,0x6C,
+	0x9C,0xC0,0xD3,0xEC,0xB7,0x89,0x43,0x97,0xF5,0xA0,0x64,0x89,0xB1,0x1D,0xF9,0x5A,
+	0x69,0x92,0x16,0x3E,0x5E,0x52,0x53,0x78,0x61,0x03,0xFB,0xA3,0x3F,0x97,0x46,0xFE,
+	0x98,0xE2,0xB6,0x7B,0x2A,0x48,0x73,0x91,0x11,0xC5,0xF0,0xAF,0xF8,0xE3,0x2E,0xF6,
+	0xD8,0x81,0xE7,0xA0,0x44,0x15,0x56,0x19,0x43,0xF0,0xAC,0x40,0x51,0xBD,0x9F,0xFD,
+	0x14,0x58,0x63,0x68,0x3A,0x91,0x94,0xF0,0x0F,0x94,0xE8,0xA0,0x8E,0xFB,0xC4,0x46,
+	0xF4,0x0F,0xD3,0x92,0xD9,0xCC,0x19,0x6C,0xE9,0x52,0x4A,0x56,0xD5,0x82,0xA7,0x00,
+	0x0B,0xB2,0xC9,0x99,0xD8,0xA4,0xA7,0x5B,0xC6,0x99,0xC4,0x87,0xCE,0xE5,0x45,0xE6,
+	0xC4,0xBA,0xE1,0x26,0x84,0x03,0x0C,0x34,0x97,0xD9,0xC2,0xE3,0x1C,0xE6,0xF4,0x78,
+	0x9F,0x1A,0x29,0xEB,0x5B,0x88,0x85,0x4A,0xE9,0x06,0xEE,0x5A,0x61,0xCF,0x47,0xE5,
+	0xA5,0x68,0x99,0xFD,0x58,0x13,0x49,0x96,0xA4,0xA1,0xEC,0xF1,0xB7,0x0C,0x96,0x92,
+	0x5D,0xC9,0x46,0x38,0xA3,0x97,0x71,0x92,0x5F,0x5E,0x2D,0xB6,0x8C,0x96,0x0B,0xE6,
+	0xF8,0x8D,0x46,0x61,0x78,0xAD,0xD4,0x62,0x2F,0xD2,0x3B,0x0F,0x46,0x65,0x1F,0x3B,
+	0x0F,0x2B,0xD3,0x98,0x4D,0x90,0x34,0xD5,0x5E,0x11,0x88,0x93,0x46,0xE8,0x57,0x1A,
+	0x47,0xA7,0xDB,0xA9,0xC5,0x5B,0x49,0xAB,0x1A,0x52,0xF4,0xDB,0xE0,0x4E,0x0C,0xA2,
+	0x28,0x1C,0xCB,0x04,0xF1,0xCF,0x2B,0x41,0xBF,0x46,0xC5,0x92,0x4E,0x49,0x82,0x5B,
+	0xD4,0x36,0x3F,0xFC,0x7D,0xCD,0x8A,0xCB,0xEC,0x75,0xE7,0x2E,0xA9,0x1A,0x5A,0xFD,
+	0x4C,0x15,0x0E,0x82,0x2A,0x8C,0x15,0x14,0x5D,0x70,0x70,0xE6,0x05,0xAE,0x5C,0x67,
+	0xF7,0xF0,0x09,0x23,0x0A,0x27,0xA0,0x1D,0x7F,0x7D,0x01,0x50,0x7E,0xEB,0x35,0x79,
+	0x39,0xA9,0x83,0xCB,0x89,0xDC,0x76,0xB1,0x77,0x96,0x1E,0xF8,0x71,0xD5,0x58,0xD9,
+	0x93,0x6E,0x99,0x6A,0xBB,0x89,0x39,0xDF,0x48,0x18,0xDB,0xE7,0xD3,0x78,0x55,0x94,
+	0x35,0xAA,0x84,0x1C,0xBD,0xD5,0xF4,0xED,0x94,0x9C,0x23,0x6B,0x48,0xE6,0xB7,0x66,
+	0xFE,0x14,0x38,0xCE,0xB1,0x05,0x3D,0xBF,0xC9,0x3F,0x97,0x60,0x3C,0xB0,0xD7,0xD7,
+	0x2B,0xAA,0x1C,0x6C,0x03,0x99,0xD9,0x41,0x42,0x4A,0x5F,0xFF,0x6B,0x2C,0x22,0x31,
+	0xAE,0x65,0xB8,0xB2,0x70,0x19,0x8A,0xA6,0x2C,0xDC,0xA3,0xF5,0x84,0x8C,0x3B,0x4D,
+	0xF6,0xA3,0x65,0x60,0x8E,0x30,0x79,0x51,0x77,0xC0,0x1E,0xCC,0x5D,0xC4,0x31,0x07,
+	0xEE,0x28,0xC3,0x1D,0x9C,0xC8,0xD4,0x70,0x51,0xA9,0xE6,0x64,0x78,0x7D,0x6A,0x3A,
+	0xE3,0xDE,0xD3,0x08,0x3A,0x01,0x9A,0x01,0x4D,0x81,0x49,0x5B,0xF4,0xEE,0xCE,0x6A,
+	0x4C,0x31,0xB9,0x42,0xCC,0x29,0x71,0x08,0x1F,0x15,0xF5,0xCC,0x34,0x24,0xD5,0x93,
+	0x18,0x8F,0x04,0x0F,0x7D,0xEB,0xC7,0x09,0x90,0x1A,0xE9,0xC6,0x01,0xDB,0x1A,0x84,
+	0x33,0x5D,0x4D,0x04,0x02,0xB9,0xC4,0x8D,0xCA,0xCF,0xC6,0xCE,0x7C,0x61,0x0D,0xFF,
+	0x18,0x87,0xEE,0x58,0x81,0xCE,0x13,0x43,0x18,0xA6,0xF2,0x80,0xAB,0x14,0xAF,0x49,
+	0x60,0x34,0x4A,0xE4,0x6B,0x31,0xCD,0x6E,0x17,0x0D,0x6D,0x52,0xC6,0x47,0x66,0x1B,
+	0x44,0x59,0xD7,0x49,0x2E,0x94,0x65,0x88,0x09,0x38,0x52,0xC5,0x94,0x98,0x84,0x1F,
+	0xDD,0xFF,0xE9,0x47,0x2C,0xB7,0xE7,0x94,0x6A,0x9D,0x56,0x9F,0xAE,0xBC,0x2E,0x3E,
+	0x97,0x15,0xA1,0x29,0xA2,0xB4,0xD5,0x8A,0x60,0xFA,0xB0,0x08,0xBD,0xF7,0xD4,0xDC,
+	0x92,0x40,0x5B,0x85,0x75,0x50,0x0F,0x42,0x45,0x3D,0xEF,0xE9,0x9B,0xF9,0x09,0x5C,
+	0x63,0xD3,0xF5,0x93,0xFE,0xC5,0xA0,0x1E,0x39,0xCC,0x98,0x40,0xC1,0xEE,0x21,0x7E,
+	0x20,0xFD,0xBD,0xF7,0xEE,0xC6,0x9D,0x3B,0xD1,0xD7,0x73,0xCB,0x07,0x97,0xF9,0x0E,
+	0xBB,0xBA,0x79,0xD0,0x23,0xE7,0x36,0x0F,0xE0,0x9A,0x15,0x79,0x6A,0x6A,0x37,0xFB,
+	0xC9,0x20,0x7D,0xFD,0x39,0x6F,0x79,0x2F,0xD0,0x24,0x94,0x41,0xE3,0xA3,0x68,0x0A,
+	0xDD,0x15,0x22,0x9C,0xC9,0x87,0xD6,0x4F,0x08,0x4C,0xDA,0x3F,0x9B,0xBC,0x40,0x9A,
+	0x08,0xAE,0xBB,0x07,0x41,0xEC,0x75,0x2B,0x90,0xA9,0x0D,0x9A,0xBF,0x98,0xCC,0xB3,
+	0x15,0x4B,0x3A,0x6A,0x00,0x59,0xB4,0x85,0x17,0xB8,0xAE,0xA5,0xDB,0x79,0xB7,0x6D,
+	0x92,0x30,0x7B,0xF4,0x37,0xA3,0x4E,0xDE,0x7D,0xF7,0xFC,0x7B,0x72,0x30,0xD0,0x11,
+	0x1F,0x05,0xD8,0xF4,0xD8,0xAE,0x6E,0x52,0x5A,0xFF,0xF4,0xE3,0xCF,0x92,0xA0,0x90,
+	0x76,0xCC,0xFB,0xFF,0x60,0xEF,0xAE,0xF6,0x86,0x50,0x36,0x5C,0x56,0x86,0x00,0x37,
+	0x2F,0xB1,0xAD,0xA7,0x0C,0xFA,0xE1,0x74,0x93,0x5C,0x63,0xB2,0x52,0xE3,0xBA,0x1D,
+	0x2C,0x83,0x5C,0x00,0x5A,0x7C,0xB2,0x12,0x4C,0x7D,0x81,0x45,0x30,0xD0,0x53,0xE1,
+	0xD7,0x9F,0x02,0xC3,0x2A,0xB9,0x9A,0x9E,0x61,0xBD,0x6C,0x3B,0x0A,0xA7,0xB3,0xF9,
+	0xFB,0x51,0xB7,0x33,0x26,0x77,0x4F,0x78,0x3E,0xA0,0xF9,0xA2,0x15,0xEA,0x3E,0xFF,
+	0x48,0x5A,0x4B,0x05,0x3A,0xFF,0x28,0x24,0x18,0x7F,0xF9,0xF9,0x69,0x5C,0x01,0xC7,
+	0x5F,0xB7,0x78,0xD2,0x3D,0x7F,0xF0,0x07,0xD0,0xCC,0x4C,0x42,0x9C,0x87,0xC9,0x12,
+	0xDB,0x45,0x8B,0xC1,0x26,0x00,0xE4,0x47,0x01,0x81,0x5B,0x3F,0x38,0x2B,0x70,0x18,
+	0x15,0x86,0xC5,0x9C,0x22,0x0B,0xE6,0x93,0x99,0x7B,0x32,0xB9,0x1A,0xA6,0x4B,0x6F,
+	0xAA,0xEC,0x06,0xFA,0x8B,0xCD,0xEE,0x80,0xB2,0xE7,0xE0,0x5F,0x5F,0x09,0x33,0xBD,
+	0x18,0x5B,0x90,0xEA,0xD1,0x4A,0x27,0xC3,0xD0,0x64,0x8A,0x03,0x8E,0x53,0x13,0xDD,
+	0x96,0x61,0x4E,0xC0,0xCE,0x3A,0xA2,0x54,0xBB,0x56,0x6C,0x91,0xF9,0xF8,0xD5,0x35,
+	0x86,0xE1,0xA0,0x8C,0xBA,0xDB,0x79,0xF4,0x22,0xC5,0x4A,0x1E,0x99,0x74,0x49,0x94,
+	0xDE,0x64,0x1F,0x0F,0x6E,0x4A,0x5F,0x07,0xB9,0xBE,0xE0,0xCE,0x07,0xF9,0xA1,0x7A,
+	0xA3,0x91,0x4B,0x0E,0x64,0xED,0x06,0xAE,0x98,0xC8,0xBA,0xB5,0x00,0x38,0xA7,0xE3,
+	0x68,0xAD,0x2F,0x5A,0xAF,0xD8,0xDE,0x21,0xF1,0x0D,0x6A,0x00,0xEF,0x7F,0x9B,0x94,
+	0x6A,0xE5,0xEC,0x2B,0xA3,0x4F,0x2D,0x7F,0xD4,0x26,0x87,0x98,0x66,0x76,0x2B,0x2C,
+	0xFC,0x11,0x62,0x0D,0xEB,0x1C,0xE9,0xA7,0x97,0xAC,0x4D,0x24,0xB7,0x5A,0x87,0x1D,
+	0x30,0xF8,0x38,0xE3,0x59,0x5A,0x61,0xA0,0x67,0x6A,0x15,0x56,0x25,0xA6,0xFC,0x0E,
+	0x51,0x55,0xDB,0x5C,0xE0,0xFC,0x59,0x78,0x76,0x27,0x07,0x68,0xEF,0xF4,0xDA,0xBA,
+	0x52,0x7E,0x5F,0xA9,0x2E,0x21,0x9C,0xBD,0x6B,0xBB,0x64,0x27,0x66,0x0B,0x63,0xC2,
+	0x3C,0x77,0xA9,0x9B,0x2C,0x48,0x93,0xF5,0xC9,0x48,0x2C,0x70,0x05,0xA0,0x75,0x81,
+	0x0E,0xBD,0x21,0x54,0x68,0xC4,0x93,0x78,0x77,0x1D,0xCD,0x90,0x92,0x99,0x53,0x94,
+	0x82,0xFE,0x09,0x0C,0x77,0x2D,0x3F,0x30,0xFF,0xF1,0xC0,0x0D,0xEC,0xC4,0xBA,0xFD,
+	0x94,0x50,0xB7,0x15,0x51,0x09,0xB5,0xD0,0x7C,0x1E,0xF8,0x1B,0xD1,0x89,0x45,0xD6,
+	0x59,0x56,0xDA,0x69,0x39,0x1A,0x75,0x6C,0x79,0xDE,0xD0,0x42,0x45,0xC0,0xCC,0xDC,
+	0x20,0x7E,0x69,0x6A,0xAC,0xCA,0x46,0x7C,0xB9,0xB6,0x4A,0xC8,0xD8,0x22,0x99,0x63,
+	0xF1,0x76,0x06,0x39,0x8F,0xCA,0xC6,0xA5,0x9E,0x59,0x43,0xDE,0xDF,0xCA,0xE8,0x07,
+	0xAC,0x83,0xC5,0xD1,0xB7,0xF4,0xF2,0x1E,0xAD,0xFB,0x6C,0x30,0x4C,0x26,0xE5,0xEB,
+	0x6E,0x02,0x0A,0xE0,0xC9,0x22,0x93,0xED,0x64,0x98,0x09,0x2A,0x1E,0x01,0x95,0x2B,
+	0x00,0xE3,0xDC,0x62,0x25,0x75,0xC7,0x6C,0xB7,0xC7,0x60,0xE1,0x63,0x2A,0x8D,0xB1,
+	0xBE,0x6C,0xE7,0x80,0xC0,0x03,0x4F,0x45,0x8A,0xE3,0x13,0x4C,0xB9,0x10,0xD1,0x98,
+	0x4B,0xCE,0x94,0x6D,0x03,0x50,0x53,0x16,0xEC,0xEA,0x35,0x6F,0x90,0xE0,0x00,0x83,
+	0x55,0xC3,0xAF,0x72,0xFD,0x78,0xC3,0xA5,0xE2,0x77,0xB4,0x00,0xED,0x21,0x1D,0x8B,
+	0xB3,0xD2,0x0E,0x95,0x88,0x54,0x05,0xD9,0x4E,0x9D,0x4D,0x9B,0xFB,0x77,0x9C,0x6B,
+	0xCF,0x0A,0x0F,0x86,0x9C,0xFE,0x5B,0x4A,0xD3,0x94,0xF9,0x24,0xE1,0x26,0x4E,0x4E,
+	0xC7,0x0A,0x59,0x2E,0xF8,0x03,0x2E,0xA2,0x4E,0x7C,0x43,0x54,0x8B,0xAA,0x4A,0x55,
+	0xF2,0x35,0xFD,0xAC,0xC0,0xCB,0x4A,0x8C,0x52,0x80,0xB8,0x70,0x4F,0x70,0x0D,0xE2,
+	0x48,0x42,0x50,0xA5,0x9A,0x86,0x5D,0x3F,0xD9,0x33,0xE5,0xCE,0x85,0x35,0x72,0xD3,
+	0xF5,0x40,0x3D,0x2C,0x42,0x3E,0x02,0x0B,0x98,0x81,0x59,0x03,0x4E,0x48,0xA0,0xC7,
+	0xA2,0xC0,0xA5,0x3B,0x3C,0xB5,0x88,0x36,0xDC,0xDA,0x48,0x51,0x1A,0x5E,0xF7,0xB6,
+	0xD9,0x7E,0xA2,0xEB,0x94,0xD9,0xA6,0x32,0xC6,0x55,0x74,0x63,0xE2,0xCB,0xB0,0x90,
+	0xEF,0xBA,0xA4,0x1C,0x85,0xB6,0x9C,0x2B,0x79,0x20,0xCD,0x71,0xD9,0x01,0x05,0x42,
+	0x4F,0x6F,0x4E,0x7C,0x09,0x62,0x0C,0x69,0xC7,0x4B,0xC2,0x9D,0xE2,0x36,0x59,0xBE,
+	0xC1,0xE0,0xA8,0x10,0xAD,0x49,0x9D,0xEB,0x1A,0xB0,0x58,0x74,0x66,0xCF,0x32,0x5F,
+	0xD0,0x0A,0x24,0x27,0x73,0x1C,0x36,0x61,0x3A,0xEE,0x7C,0xD7,0x68,0xAB,0xBF,0xEF,
+	0x6A,0x65,0xA6,0xCC,0x1C,0x83,0x50,0x11,0x69,0x6E,0x8A,0x2C,0xBC,0xE8,0xDC,0x5A,
+	0x62,0x41,0x2B,0x93,0xA0,0x97,0x2E,0xFA,0xE2,0x1B,0x39,0x37,0x61,0x38,0xD9,0x3D,
+	0x37,0x8D,0x30,0x3A,0xF6,0x19,0x3D,0x0A,0xCC,0xED,0xD6,0x92,0xA2,0x4A,0xF4,0xD7,
+	0x94,0xEC,0x5F,0xC8,0x65,0x78,0x9F,0xC3,0x1F,0x84,0x7D,0xB1,0xDC,0x9B,0x32,0x79,
+	0x66,0xF2,0x55,0x42,0xA7,0x73,0xFA,0x7A,0xBF,0xFA,0x8B,0x24,0xBE,0x15,0x7F,0xA5,
+	0x1D,0x05,0x0C,0xA8,0x35,0xB2,0x37,0xAC,0x58,0x28,0x24,0x97,0xD2,0x49,0x32,0x3D,
+	0x6E,0xA4,0xCB,0x0B,0x79,0xF7,0x1B,0x10,0x7D,0xA4,0xAD,0x3E,0xDB,0x99,0xE1,0x37,
+	0x0C,0x71,0x90,0x95,0x4A,0x4A,0xE2,0xA6,0x31,0x68,0x94,0xC5,0x13,0xA7,0xF4,0xAE,
+	0x4D,0xF9,0xEC,0x3C,0x80,0x30,0x0A,0x29,0x9E,0x79,0x0A,0x9C,0x42,0xFE,0x1E,0x2F,
+	0x02,0x6D,0xBA,0xF0,0xA3,0x9B,0x89,0xE8,0x56,0xA2,0xB9,0xBE,0xFC,0xC6,0xFE,0x16,
+	0xDF,0x82,0xCD,0x36,0x18,0xA1,0x23,0x44,0x31,0x64,0xBB,0x8C,0x6D,0x3D,0xCD,0xBF,
+	0xC9,0xB3,0xA4,0x15,0xF4,0xA9,0x83,0xD1,0x8B,0x30,0xFB,0xBD,0x32,0xA0,0xC2,0x8E,
+	0xD0,0x0A,0xFC,0xB2,0x99,0x61,0x4C,0x55,0xEF,0x40,0x95,0xD3,0x8F,0x4B,0x0A,0xC3,
+	0x25,0x21,0xAA,0x4F,0xFD,0xF5,0x57,0x22,0x6E,0x5C,0xD2,0x01,0xA6,0x4D,0xDD,0x92,
+	0x7A,0x9D,0xC7,0x38,0x14,0xDF,0x05,0xCF,0xBD,0x95,0x3F,0xC9,0x17,0x44,0x6B,0x6F,
+	0x30,0x02,0xB2,0xCE,0xA2,0x21,0xB8,0x4C,0x07,0x18,0x3A,0x45,0xE9,0xC8,0xFE,0x0F,
+	0xDB,0x29,0x25,0x1F,0x58,0x56,0x08,0x4F,0x1A,0xF6,0x74,0xEF,0x92,0xD1,0x29,0x24,
+	0xC7,0xCD,0x5C,0x22,0x19,0xD3,0x50,0x77,0xC0,0xE8,0x2A,0x5E,0x94,0x3F,0xC8,0x61,
+	0x4E,0x89,0x33,0xB0,0xA3,0xFA,0xB9,0x60,0xCB,0x83,0x81,0x5C,0x52,0x4E,0xC0,0xE5,
+	0x92,0x80,0x9F,0x37,0x93,0xD4,0xDA,0x9B,0x5C,0x3A,0x69,0x5D,0x19,0x81,0x9F,0x9F,
+	0xB7,0xD1,0x8D,0xCF,0xA2,0x9A,0xF7,0xCD,0xAB,0x66,0x6E,0x68,0x93,0x38,0x0A,0x1E,
+	0x0B,0x3D,0xCC,0x0C,0xA9,0xDF,0xDE,0x38,0xF2,0x87,0x3E,0xCE,0x50,0x4A,0x36,0x02,
+	0xD2,0x85,0xD8,0x2A,0x7E,0x1F,0x72,0xAD,0x5F,0x9E,0x28,0xC0,0xE0,0x74,0xC3,0x53,
+	0x7A,0x94,0x49,0xD8,0x6C,0x38,0x06,0xCC,0x15,0x44,0xED,0x76,0x87,0x9D,0x1D,0x82,
+	0x33,0x55,0xD3,0x3A,0x6F,0x25,0x28,0x2E,0x2D,0xE6,0xAE,0x1F,0xA5,0x4C,0x53,0x19,
+	0xE4,0xFD,0x6B,0x62,0x88,0xAA,0xD0,0xC3,0x68,0x58,0x75,0x78,0xB9,0x9F,0x07,0x61,
+	0xFE,0x90,0xE4,0x5F,0x5C,0x1E,0xE4,0x35,0xA6,0xED,0x4E,0xFD,0x1C,0x28,0xEE,0x2E,
+	0x34,0x35,0xFE,0x0B,0x64,0xB4,0xB8,0x93,0xBF,0x44,0x92,0x67,0x0E,0x8E,0x85,0x67,
+	0xD7,0x5F,0xF0,0x1A,0x65,0x7C,0x6E,0xB0,0x01,0xA8,0xCA,0x86,0x10,0x62,0xDB,0x02,
+	0x2F,0x93,0x37,0x07,0xE1,0xBA,0xA9,0x09,0x80,0x6A,0x01,0xE5,0x76,0x8B,0x52,0x8F,
+	0x00,0xC7,0x60,0xEF,0x04,0x4E,0xE6,0x40,0x9D,0xA8,0xDA,0x5B,0xD8,0xD7,0x98,0x39,
+	0xE8,0xB9,0x26,0xCE,0xBE,0xCA,0x30,0xB9,0x11,0x8B,0xEF,0x82,0x37,0x70,0xDC,0xDF,
+	0xC9,0x40,0x10,0xA1,0x28,0x69,0x82,0x64,0x39,0xAF,0x2D,0xD3,0x03,0x91,0x5A,0x86,
+	0x55,0xFC,0xF0,0x55,0x2E,0xEC,0xD8,0x74,0x67,0xF7,0x9C,0x4C,0xB6,0x57,0xAF,0xEC,
+	0x6A,0xE4,0x4B,0x73,0x89,0x3C,0xFE,0x63,0x99,0x3A,0xFF,0xC8,0x21,0x58,0x96,0x24,
+	0xCA,0x11,0xCB,0x71,0x50,0xC9,0x7A,0xBB,0xBB,0x0F,0xFA,0x24,0x3C,0x34,0xBB,0x4E,
+	0xAB,0x37,0x92,0xB9,0x63,0x88,0x5C,0x06,0xB0,0xF0,0x7B,0xD7,0x0C,0xFD,0xB6,0x0B,
+	0x5F,0x78,0xE7,0x9D,0x06,0x7D,0x46,0x59,0x44,0xDD,0x31,0x91,0xC7,0x12,0x80,0xA4,
+	0x33,0x23,0xFC,0xAE,0x62,0xE2,0xE8,0x85,0x3E,0x9C,0x4A,0xC9,0x61,0x9D,0x0D,0x65,
+	0x61,0x72,0x45,0xF1,0xCF,0xA2,0x7F,0x9D,0xC3,0x04,0xB2,0xA5,0x68,0x3E,0xE1,0x56,
+	0xE9,0x49,0x00,0xBF,0x19,0xCB,0x75,0xFB,0xCB,0x05,0x73,0x50,0x7E,0xB2,0x24,0x95,
+	0x0E,0x9D,0x3D,0xA6,0xF3,0x09,0x5C,0x43,0xE8,0x6C,0xFD,0x68,0x8C,0x2F,0x64,0xCD,
+	0xD3,0x4B,0x7E,0x66,0x70,0xB7,0xB2,0x76,0xF3,0xE2,0x63,0x92,0x0F,0x45,0xFE,0x9C,
+	0xFB,0xD4,0x30,0xC7,0x93,0x77,0xEF,0x98,0xBE,0x66,0x56,0x51,0xB6,0xA3,0x7E,0xC7,
+	0xBB,0x4D,0x7A,0xFD,0xCB,0x13,0x01,0x05,0x8C,0x96,0x06,0xF6,0x37,0x1E,0x78,0x70,
+	0x13,0xCC,0x00,0xC3,0x7F,0xB8,0xA5,0xF3,0xB5,0xB3,0x4E,0xD9,0xAB,0x2E,0x1E,0xFE,
+	0xA9,0x2D,0x4B,0xA5,0x9F,0xEB,0xD5,0x07,0x13,0x3D,0xAB,0xA4,0x1B,0xC2,0xD3,0xB3,
+	0x57,0x41,0x96,0xBC,0x5D,0x4F,0xC3,0x5F,0x07,0x06,0x25,0x65,0x19,0xF6,0xD4,0x0D,
+	0x40,0x66,0xA8,0x01,0x62,0x83,0xC7,0xCD,0xA8,0xCE,0xFE,0x03,0x6C,0x58,0x81,0x38,
+	0x80,0xA9,0x0E,0x75,0x5A,0x23,0x41,0x8C,0x20,0x62,0xCA,0x69,0x1A,0x33,0x62,0x0E,
+	0x0B,0x80,0x6E,0xD5,0x85,0x21,0xEB,0xBE,0xC0,0x3E,0x6A,0xC7,0x92,0x51,0xE6,0xDE,
+	0x74,0x63,0xB7,0x01,0x22,0x59,0xB5,0x39,0x8B,0xF4,0xF1,0x0E,0x93,0xBB,0x7F,0xA8,
+	0xAE,0xF2,0xD7,0x9B,0x5A,0xA4,0xFC,0x2D,0xE5,0x5F,0x0D,0x46,0x3F,0x1D,0x2B,0x5A,
+	0xBC,0x3A,0x7D,0x00,0xAC,0x2B,0x38,0x75,0xF6,0x05,0x70,0xFE,0xD7,0xC6,0x2E,0x19,
+	0xF9,0xDF,0xFA,0x77,0xB3,0x24,0xB8,0xB5,0xFF,0xD3,0x2C,0x06,0xD4,0xEA,0x25,0xDB,
+	0x85,0xC9,0xC3,0x59,0x2C,0x90,0x42,0xB9,0x1F,0xB1,0xAB,0x64,0x55,0x25,0xAD,0xD3,
+	0x82,0x5F,0x1B,0x53,0x2B,0xF1,0x51,0x7C,0xFE,0x64,0x02,0x0C,0x72,0x5F,0xD0,0x51,
+	0x36,0x58,0xA3,0xED,0x44,0x59,0x3F,0xDD,0x75,0xEE,0x21,0xF0,0x97,0x3D,0x05,0x38,
+	0x7D,0x29,0xF9,0x88,0x3A,0x42,0x76,0x0C,0x67,0x6F,0x61,0xAB,0x99,0xA2,0x87,0x58,
+	0x74,0x2A,0x1F,0x42,0x25,0x02,0xED,0xD5,0x46,0x99,0x13,0xAE,0x91,0x86,0xAF,0x71,
+	0x95,0xE6,0x93,0x12,0x51,0xF2,0xAA,0x44,0x79,0xE9,0x5B,0x58,0xEE,0xE0,0x9F,0x25,
+	0x25,0xCC,0x39,0xA1,0xCF,0x11,0x98,0xBB,0x2E,0x82,0xBD,0xDE,0x05,0x53,0x50,0x1A,
+	0xFC,0x1B,0x9C,0xE5,0x58,0xF4,0x8D,0xF7,0x6A,0xA3,0xDD,0x68,0xF2,0x42,0x3A,0xE2,
+	0xF3,0xAB,0x7D,0x12,0x5F,0x0C,0x92,0x30,0xE8,0xB5,0xD7,0x22,0xEB,0x70,0x37,0x8B,
+	0x5B,0xE4,0x6D,0x90,0x28,0x14,0x79,0xE4,0x32,0xDD,0x2F,0xE4,0x87,0x8F,0xE8,0xAD,
+	0x3F,0x32,0x42,0x88,0x23,0xA5,0xB6,0x1A,0xD6,0xD4,0x7C,0x47,0xB4,0x19,0x91,0x5D,
+	0x40,0xE6,0xAA,0x32,0x65,0x85,0xD6,0x95,0x77,0x57,0x65,0x82,0xCF,0x40,0xFF,0x02,
+	0x50,0x30,0x81,0x5B,0xD1,0xDE,0x41,0x5D,0xB9,0x7B,0xC7,0xE1,0xFD,0xE0,0x41,0xFF,
+	0x9B,0x66,0x42,0x4A,0x1B,0xAE,0xF6,0xA1,0x2A,0x4F,0x55,0x94,0x73,0x3C,0x05,0x24,
+	0x4E,0xDE,0xBF,0xCC,0xCE,0x02,0xD1,0x16,0xFD,0x81,0x16,0x57,0xF4,0x94,0x2C,0x6C,
+	0x85,0xAC,0x85,0x27,0xB1,0x1E,0x00,0x07,0x63,0xE0,0x0B,0x01,0xFC,0xCF,0x2D,0x40,
+	0x44,0xB2,0x74,0x5B,0xAA,0xED,0x7A,0xB8,0x91,0x3B,0xBE,0x92,0x10,0x02,0xC9,0xDF,
+	0xDB,0x1A,0x87,0x84,0x14,0x61,0x89,0x34,0xD1,0xB4,0x67,0xC2,0x3A,0xBC,0x36,0xE3,
+	0x76,0x3B,0xD3,0x0F,0xDB,0x49,0x1C,0x3D,0x87,0xB2,0x8A,0xF9,0x4D,0x19,0x29,0x07,
+	0x36,0x1C,0x1D,0x8C,0xD8,0x61,0xD3,0xE3,0x7D,0xA7,0xC6,0xC1,0x64,0x07,0xA2,0xDE,
+	0x87,0x0C,0x77,0x82,0xD0,0x96,0x28,0x17,0x82,0x3D,0x88,0xBB,0x4D,0x47,0x08,0xEF,
+	0x29,0x42,0xA7,0x54,0x9F,0x12,0xB8,0xDD,0x89,0x61,0x94,0xB1,0xF4,0xCE,0x5D,0x42,
+	0x1F,0x23,0xC0,0x88,0xDB,0xDA,0xCC,0xA3,0x17,0x20,0x1B,0x8B,0x17,0xE7,0xE5,0x7F,
+	0xC4,0x4D,0xBA,0xC8,0xE4,0x89,0x99,0x00,0x06,0x7E,0x45,0xF3,0x96,0x09,0xB8,0x3E,
+	0xE4,0x74,0x58,0x91,0x7E,0xC7,0x92,0x18,0x28,0xC5,0xF2,0xA8,0x87,0x6E,0x11,0xFB,
+	0x20,0x57,0xD7,0x33,0xBF,0x4B,0x47,0xE9,0xCD,0xF3,0xF2,0xE4,0x95,0xBE,0x5A,0x0B,
+	0x70,0x70,0x51,0x71,0x4E,0x85,0x1E,0x46,0xE5,0xE4,0xE8,0xF2,0x60,0xC0,0x72,0xDA,
+	0x1C,0x74,0xFE,0xC1,0xD8,0x37,0xB4,0x54,0xBE,0xA9,0x59,0x79,0xFD,0xFD,0x31,0xC6,
+	0xB3,0x57,0x9D,0xAB,0xAE,0x0E,0x42,0x91,0x2C,0x44,0x41,0x61,0x07,0x0D,0x7B,0x4F,
+	0x8A,0xD3,0x35,0x1F,0x7E,0x53,0x96,0xE5,0x2A,0x0E,0x02,0xEF,0x87,0xEB,0x83,0xD6,
+	0xA7,0xA2,0xF8,0x16,0x26,0x96,0x60,0xA1,0x3F,0x60,0xD1,0x6C,0x4A,0x69,0x99,0xD8,
+	0x91,0x40,0xCB,0x76,0x5C,0x59,0x62,0x4A,0xF1,0xF0,0x87,0xF5,0x0D,0x15,0x54,0xBD,
+	0x54,0x1D,0xB5,0x7A,0x22,0xE2,0x5F,0x7A,0x35,0x7E,0x6C,0x77,0x56,0x93,0xEE,0x24,
+	0x74,0xFF,0xDB,0x63,0x16,0x80,0x62,0x48,0xD5,0x51,0x45,0xAB,0xDA,0xFF,0x6F,0xAF,
+	0x93,0xDA,0x47,0xD4,0xCA,0x17,0x47,0x28,0x29,0x40,0x83,0x05,0xD0,0x52,0xB5,0xF7,
+	0x74,0x6F,0x0D,0xAB,0x36,0xD3,0x89,0x1F,0x52,0x97,0xFE,0x02,0x8E,0x2D,0x44,0x14,
+	0x52,0x25,0x64,0xAB,0x22,0xE1,0x16,0x16,0x32,0x4A,0xBF,0x09,0x06,0x5C,0x55,0x85,
+	0x02,0x44,0x16,0x02,0x68,0x46,0x74,0x2E,0x53,0x59,0x18,0xA3,0x4B,0x55,0x49,0xF5,
+	0x3A,0x74,0x1F,0x4B,0x90,0x56,0xE4,0x72,0xB2,0x54,0x16,0x41,0x8F,0x52,0x9D,0x7D,
+	0xC8,0x19,0xCC,0xE8,0xC7,0x9C,0x1A,0x30,0x67,0x93,0x3E,0x38,0x7E,0xC4,0x1F,0x73,
+	0x0C,0x1D,0xF4,0x37,0x4C,0x57,0x52,0xDA,0x88,0xB3,0xBB,0x85,0x1F,0x1D,0x6D,0x0B,
+	0x6E,0x6A,0xB8,0x7D,0xEB,0x6B,0x46,0x22,0x9A,0x2E,0x39,0x86,0x0B,0x50,0x95,0xCE,
+	0xB1,0x8F,0xDE,0x34,0x7B,0x1D,0xD7,0x8E,0xD8,0xEB,0x78,0xBE,0x8B,0x3D,0x1A,0xDA,
+	0x83,0xD4,0x8F,0xBD,0xCE,0xF9,0xD9,0x1D,0xE1,0x06,0x16,0xDA,0xA3,0xFD,0x91,0x5E,
+	0x02,0xB5,0xFD,0x2A,0x26,0x5A,0x1E,0xA4,0x06,0x39,0xD4,0xF7,0x17,0x44,0xC9,0x93,
+	0x54,0x59,0x0C,0x8C,0xF2,0xC9,0xFD,0xF3,0x29,0xE2,0x18,0x3D,0xA5,0x7A,0x7F,0x3F,
+	0x27,0x16,0xAE,0x89,0x08,0x7D,0xAA,0xDE,0x2F,0x2D,0xA8,0x45,0xC6,0xAC,0xD0,0xCD,
+	0x92,0x83,0x18,0x53,0x00,0xC7,0x41,0x7D,0xF2,0x80,0xF8,0x5D,0x83,0xE4,0xA1,0x61,
+	0x64,0xC5,0x1F,0x8D,0xA8,0x3F,0xF9,0x4A,0x0B,0xB0,0x45,0xB9,0xD1,0xBA,0x79,0xCB,
+	0xD9,0x67,0x86,0x2C,0x5A,0xB2,0xAE,0xAE,0xE6,0x0A,0x9F,0xA6,0x13,0x00,0x54,0x21,
+	0xEF,0x0E,0x34,0x51,0xE7,0xF3,0x20,0x8C,0x65,0x42,0xE4,0xAC,0x3A,0xC4,0xD2,0x8B,
+	0x54,0x04,0x3C,0xB4,0xDB,0x9F,0x0D,0x13,0x5E,0x66,0x0A,0x0D,0xAD,0x8E,0x97,0x36,
+	0x8E,0x06,0x6F,0x1A,0x63,0x3F,0x84,0xAE,0xC1,0x84,0xF5,0x7D,0xC9,0xCB,0x49,0x79,
+	0xF6,0x64,0x0A,0xC0,0x70,0x60,0x84,0x53,0x71,0x11,0xA8,0x3B,0xB2,0xA2,0xA0,0x05,
+	0x5E,0x9D,0x30,0x64,0x5F,0xB7,0x21,0x7B,0xAE,0x78,0x88,0x5B,0xE9,0xE6,0xCA,0xBF,
+	0x0B,0x5D,0xFF,0x81,0x5F,0xA6,0xDA,0x3D,0xC3,0xCD,0xB8,0xFF,0x7E,0x4A,0x57,0xAB,
+	0x97,0x33,0xE8,0x3E,0x28,0x15,0xF5,0x7E,0x68,0x71,0xDA,0x02,0xEC,0x2A,0x8D,0xF9,
+	0x20,0x78,0xF5,0x56,0x22,0x4B,0x0C,0x50,0xCE,0x5F,0x42,0xEA,0xB7,0x74,0x3D,0xC2,
+	0x5B,0xE2,0x10,0x49,0x62,0x33,0x69,0xAA,0x7A,0x83,0x5D,0x81,0x48,0x43,0x7E,0x26,
+	0xE2,0x34,0xF4,0x24,0x70,0xDC,0x77,0x11,0xFF,0x48,0xC9,0x5F,0x89,0x33,0x61,0xFD,
+	0x18,0xB3,0x98,0x3B,0x17,0x8E,0xB1,0xB1,0xF7,0x14,0xBD,0x73,0x95,0x42,0x02,0x6A,
+	0x27,0xDA,0x44,0x42,0xE2,0xE0,0x2C,0x6B,0x20,0xC5,0x82,0x09,0x22,0x99,0x4A,0xE1,
+	0x85,0xAA,0xD0,0x36,0x11,0x81,0x18,0x70,0x29,0x22,0x27,0xD5,0x04,0x3E,0x7B,0xD3,
+	0xFB,0x12,0x97,0xFA,0xBD,0xF5,0xF0,0xBA,0xBB,0x20,0x7B,0xC8,0x1E,0x30,0xA9,0x96,
+	0xC6,0xD9,0x95,0x6B,0xD1,0x4C,0xA7,0x46,0x58,0x3C,0x29,0x2B,0x8F,0x77,0x39,0xB5,
+	0x9D,0x48,0x73,0x35,0x16,0x82,0xEC,0xBC,0x17,0x2C,0xA5,0x6B,0xA8,0x86,0x28,0x94,
+	0x81,0x5F,0x47,0xC9,0xE1,0x7B,0x5B,0x26,0x42,0xC2,0xF9,0xF7,0x43,0xA4,0x97,0x37,
+	0x2C,0x36,0x82,0x23,0xAD,0x85,0x4B,0xE4,0xBC,0x2B,0xAA,0xCB,0xD4,0xD5,0xFF,0x78,
+	0xCA,0xD9,0x19,0x76,0xEA,0x63,0x81,0x1B,0x24,0xC4,0xD8,0x06,0x61,0xEF,0x4F,0x8B,
+	0x3D,0x7A,0x28,0x33,0x5D,0x83,0x8F,0xB1,0x8E,0x57,0x10,0xAB,0x84,0x2A,0x48,0xC8,
+	0x8C,0x95,0xE2,0x4B,0x67,0x87,0xD8,0x17,0x5A,0x06,0xAB,0xF9,0xD4,0xC8,0xBB,0xAC,
+	0xF2,0xBA,0xD2,0x71,0x23,0x3B,0xDA,0x82,0xE0,0x0F,0x40,0x6E,0x8D,0x84,0x7D,0x6C,
+	0xA8,0xFE,0xFC,0x3B,0xE1,0xA4,0x66,0x2A,0x8F,0x46,0xDC,0x89,0x6B,0x3A,0x15,0xEB,
+	0xB1,0x3F,0x09,0x8C,0x2F,0xE7,0x74,0x8C,0x13,0x4B,0x5B,0xA7,0xCC,0x72,0xF1,0x26,
+	0xA9,0x32,0xF6,0x9C,0xC2,0xF6,0x57,0x6A,0xEB,0x42,0xAD,0x31,0xF2,0xD8,0x02,0x2D,
+	0x13,0xA4,0x1C,0xE4,0x02,0x08,0x5D,0x89,0x12,0xCF,0x7E,0xF8,0xFA,0xB1,0xBB,0x79,
+	0xA0,0x8A,0x24,0x7C,0xB9,0xCE,0x07,0x3D,0x6E,0x85,0x53,0xCC,0x66,0xC9,0xAE,0xC0,
+	0x94,0x75,0xAB,0xFF,0xE3,0x2D,0x2C,0xC9,0xC9,0x37,0x17,0x17,0xDF,0x4D,0xED,0x56,
+	0xE3,0x6E,0xF4,0xF9,0x24,0xDC,0x42,0x99,0xCD,0x6A,0x61,0x4F,0x54,0x9E,0xCC,0x98,
+	0x91,0x73,0xD4,0x7F,0x22,0xB6,0xB0,0x40,0x09,0x18,0x10,0x60,0x9A,0x3C,0xFB,0x53,
+	0x1A,0x0A,0x4A,0x78,0xA8,0x91,0x64,0x6F,0x2F,0x5F,0x44,0xD8,0x27,0x87,0xB7,0x51,
+	0x43,0xE5,0x00,0xAC,0xC2,0x79,0x33,0xC9,0xC1,0xD1,0xD8,0x37,0x85,0xDC,0x80,0xFD,
+	0xF0,0xB2,0x89,0x93,0xE0,0x71,0x5B,0x72,0x3C,0xD3,0xBB,0xE4,0xA5,0xCD,0x13,0x7C,
+	0x90,0x5D,0x17,0x81,0x8D,0xD4,0x50,0x26,0x4D,0x16,0x19,0xB8,0x47,0x93,0x14,0x24,
+	0xBB,0x13,0xA5,0x30,0xEA,0xCA,0xCA,0x24,0x5F,0x5F,0x12,0xB7,0x1B,0xD4,0x1C,0xCA,
+	0x3F,0x2B,0x37,0x2F,0x05,0x80,0x4C,0xEA,0x5C,0x74,0x59,0xA7,0x44,0xFE,0x3C,0x32,
+	0xE7,0xDF,0x3F,0xAC,0x48,0x72,0x43,0x7A,0x73,0xCB,0x3B,0x45,0x9C,0x08,0xA0,0xB2,
+	0xD1,0x99,0xE6,0x7E,0xEE,0x86,0xF3,0x8F,0xB9,0x9C,0xA7,0xC6,0x69,0xBF,0xD6,0x1C,
+	0x0F,0xDF,0x50,0x96,0x82,0x69,0x28,0x13,0x28,0xA0,0x8F,0xB1,0x9D,0x65,0x0C,0xC9,
+	0xC5,0xE2,0xA8,0x6D,0x3C,0xA3,0xA5,0x07,0x8C,0xDF,0x66,0xAE,0xF2,0x06,0x64,0x66,
+	0xC8,0x1C,0xB8,0x9B,0x09,0xC5,0xA2,0x95,0x3B,0x14,0x5B,0x58,0x42,0x17,0x23,0x5A,
+	0x2E,0x1E,0x27,0x22,0xD7,0x72,0x92,0x15,0x2F,0x53,0xAA,0x73,0xCE,0x8C,0xB3,0xBD,
+	0xA7,0x4A,0x6C,0x46,0x2F,0x22,0x6B,0x61,0xAF,0x2B,0xD8,0xAB,0x51,0x8A,0x9A,0x84,
+	0x48,0x30,0xFF,0x84,0x09,0xEA,0x00,0x27,0xC6,0x24,0x7D,0xC2,0x4C,0x32,0x23,0xCF,
+	0x59,0x01,0x67,0xA3,0x7A,0x80,0x09,0x69,0x7E,0xEC,0x42,0x51,0x09,0xD2,0xEC,0xAC,
+	0x8D,0x67,0x7E,0x1D,0xC4,0x1E,0xFE,0x80,0x83,0x94,0xFC,0x25,0x8D,0x84,0x55,0x97,
+	0xC8,0x4A,0xD5,0x10,0x73,0x10,0xAF,0x74,0x51,0x27,0xA4,0x4C,0x2E,0x42,0x4F,0x69,
+	0xFC,0x02,0xEA,0x03,0x66,0xDC,0x19,0xC3,0x5D,0x12,0x70,0xED,0x69,0x57,0x91,0xCB,
+	0xCB,0xE3,0xFC,0x09,0x31,0x68,0x1A,0x34,0xDE,0xEB,0x9D,0x20,0x9E,0x26,0xED,0x13,
+	0x2E,0xB8,0x62,0xCF,0x8B,0x93,0xB9,0x2F,0xDF,0xC4,0x73,0x5E,0x1C,0x08,0xAC,0x32,
+	0x5F,0xA1,0x56,0xE9,0xBE,0x0C,0x5D,0xD3,0x6F,0x96,0x24,0x40,0xBA,0x37,0xAE,0x10,
+	0x89,0xE5,0x3F,0x51,0x2A,0xC9,0x34,0xB2,0xA9,0x23,0xAE,0xE1,0x5B,0xA4,0xF2,0xFD,
+	0x9F,0xDA,0x22,0xFF,0x37,0x2F,0x4A,0x96,0x24,0x20,0xCE,0xA6,0xBD,0x42,0x79,0x5D,
+	0xE5,0x55,0xFC,0xDB,0x9D,0x83,0xDD,0xB9,0xC7,0xC9,0xDE,0xEF,0x94,0x02,0xC6,0xDD,
+	0xFC,0x71,0x22,0x73,0xD2,0x71,0xA7,0xFF,0x5C,0x0A,0x66,0xDE,0xD2,0x8E,0x35,0x3E,
+	0xD6,0x8A,0x26,0x94,0x6D,0x44,0x41,0xF3,0x1D,0x7F,0x6E,0xFC,0x45,0x60,0x98,0xB5,
+	0x4A,0x47,0x03,0xF1,0x65,0x9D,0x7C,0x36,0x36,0xF8,0xE9,0x2F,0x67,0x1A,0x73,0xE6,
+	0x11,0x58,0x9D,0xC6,0x85,0x91,0x3A,0xC1,0x3F,0x95,0xE1,0x34,0xE7,0x84,0x1B,0x8A,
+	0x47,0x05,0xCC,0x4E,0xAA,0xA3,0x89,0x6B,0x17,0xC0,0xB3,0xB2,0x99,0x2B,0xE4,0x71,
+	0x50,0xA1,0x9A,0x99,0x32,0x00,0x63,0xBB,0x96,0x80,0x9E,0xE6,0x67,0x31,0x26,0x83,
+	0x1D,0x7E,0x5A,0x07,0x2E,0x1C,0x79,0x8E,0x0B,0x6C,0x8A,0x86,0x8B,0x22,0x71,0x68,
+	0xBD,0x54,0x36,0xD9,0x2E,0xF4,0xF3,0xAE,0xEF,0x9C,0x8A,0x63,0x63,0x65,0x74,0xB1,
+	0x4D,0xDD,0xE1,0xFA,0x38,0x49,0x5A,0xF9,0x89,0x9C,0x85,0xF7,0xB8,0x19,0xA9,0x78,
+	0xEF,0x68,0x9E,0xAE,0x49,0xC8,0x8A,0x18,0xC6,0xAF,0xE0,0x40,0xCA,0xC8,0x1E,0x24,
+	0x55,0xBE,0x9C,0x80,0x18,0x7D,0x08,0xBA,0x51,0x79,0x68,0x5C,0x78,0x0C,0xC7,0x83,
+	0x62,0x8B,0xCC,0x2D,0x01,0xA0,0xC5,0xE3,0x30,0xE5,0xDB,0x3F,0x53,0xD8,0x76,0xE6,
+	0x1C,0x27,0x19,0xE0,0x52,0xEE,0x2D,0x4C,0x7D,0x30,0x88,0xEB,0x56,0x72,0xCA,0xD5,
+	0xA8,0xD5,0xDF,0x54,0x00,0x7C,0x19,0x44,0x2A,0xB6,0xA4,0x10,0x48,0x3E,0xDB,0xF6,
+	0xA0,0x90,0xFB,0x75,0xF5,0x36,0xF1,0x8B,0xC8,0xE5,0x89,0x25,0x8A,0x63,0xA0,0xF1,
+	0xB2,0xD3,0xEB,0x9C,0xF6,0x55,0xC0,0xE6,0x42,0x7C,0x93,0x9A,0xC5,0xE4,0x91,0x93,
+	0xBB,0x60,0xA2,0x92,0x1A,0x6E,0x97,0x5C,0xD8,0x64,0x96,0xE6,0x87,0xFA,0x19,0x93,
+	0xA9,0x03,0x38,0x50,0x2F,0xBF,0x22,0x81,0x3C,0xA9,0x45,0xE9,0xF7,0x28,0x27,0x3A,
+	0x4A,0xAD,0xE9,0x57,0xA6,0xD1,0xD2,0x66,0x05,0xFE,0xC8,0x92,0x40,0x24,0x06,0x29,
+	0x3A,0xBC,0x97,0x8F,0x9D,0x74,0x61,0xE6,0xBB,0x8D,0x8F,0xE7,0xA2,0xDC,0x0C,0xFC,
+	0xD1,0xD3,0x3B,0x89,0x60,0x0F,0xA6,0x83,0xDF,0xB1,0xEE,0xE7,0x9B,0xA4,0xF6,0x74,
+	0x1C,0x8A,0x36,0x3D,0x70,0xEC,0xE3,0xF5,0x25,0xE7,0x1A,0xD9,0x65,0x20,0x9A,0x52,
+	0x8A,0x01,0x00,0xE2,0x52,0x56,0x1D,0xDB,0x22,0xF0,0x5A,0xE7,0x63,0xE4,0x52,0xF2,
+	0x0C,0xFA,0xA8,0x5C,0xA1,0xBC,0xF0,0xA7,0xDF,0x29,0x97,0x25,0x92,0xD8,0x38,0x37,
+	0xAE,0xE0,0xA4,0xD9,0x03,0x74,0x69,0x88,0xF5,0x53,0xED,0x05,0xE2,0x6B,0x8A,0x89,
+	0x75,0x25,0xCC,0x91,0x3C,0x09,0x37,0xCC,0xF6,0x6A,0x1C,0xDE,0x5C,0xCD,0x48,0x7E,
+	0x23,0xD8,0xEC,0xEB,0x68,0x8C,0x40,0xF0,0x12,0xAD,0x79,0x53,0x68,0xB7,0xB4,0x31,
+	0xF6,0x79,0xCE,0x90,0x9D,0x06,0xC5,0xD4,0x37,0x2A,0x4D,0xD9,0xF8,0x71,0xBA,0x8B,
+	0x7B,0xEB,0xDE,0x3F,0xD5,0x63,0x1C,0x8C,0xFF,0xB6,0xA1,0xF6,0xCD,0xB1,0xEA,0x5E,
+	0x65,0xCF,0xEE,0xDA,0x59,0x72,0x69,0x7A,0x67,0x99,0x80,0x31,0x7E,0x88,0xCA,0x1B,
+	0x9E,0x6E,0x41,0xBE,0x52,0xFA,0xC3,0x46,0x6D,0x1C,0x2F,0xA1,0xF8,0xC3,0x0A,0xF8,
+	0x5E,0x01,0x2E,0x75,0xFD,0xA5,0x34,0xA5,0xEF,0xD7,0xB6,0x5A,0x91,0xC0,0x48,0x9E,
+	0xE1,0xA6,0x18,0xC4,0xAF,0x34,0xF7,0x5E,0xBD,0xC0,0x10,0x8D,0xC6,0x81,0x37,0x9F,
+	0x5C,0xE9,0x26,0x86,0x31,0x25,0xB3,0x4C,0x1B,0x84,0xBB,0xB6,0xBC,0xF2,0x2E,0x64,
+	0xD4,0x68,0x21,0xC1,0x1A,0x21,0x13,0xBC,0x07,0xD0,0x91,0xC3,0x8A,0x42,0x3F,0xFF,
+	0x66,0xCE,0x55,0x2B,0x34,0x4F,0x17,0x7E,0xCF,0x00,0x5E,0x6E,0xD3,0xB0,0xDC,0x3F,
+	0x6B,0x33,0xD9,0x3B,0x9C,0x5F,0x4E,0x3E,0xB2,0x5B,0x8C,0x72,0xC2,0xCE,0xFF,0xF0,
+	0xC8,0xAC,0xB3,0x6D,0x49,0x8D,0x13,0x7C,0x71,0xA9,0x69,0x9C,0x23,0xA5,0x6C,0xC4,
+	0xD9,0x36,0x67,0x31,0xE0,0x30,0x9A,0x0F,0x4E,0x57,0x0F,0x49,0x0B,0x34,0xEC,0x7C,
+	0xDD,0xFE,0xCA,0x9A,0x6F,0x64,0xB7,0x8E,0xB7,0x8E,0xD8,0xE1,0x58,0xE5,0xBB,0x05,
+	0x27,0x4F,0x4A,0x16,0xD7,0x7D,0x51,0x37,0x00,0x68,0xAB,0x6B,0x5C,0xF0,0x72,0xAD,
+	0x4F,0x4F,0x8F,0x59,0x9A,0x47,0xC0,0xAF,0xB2,0x6D,0x5F,0x13,0x20,0x91,0xFB,0x77,
+	0xC6,0x8B,0xB3,0xD2,0x69,0xAF,0x44,0xA5,0x5D,0x0C,0x46,0x62,0x00,0xEA,0x2D,0x8F,
+	0x7B,0x87,0x9C,0xDC,0x45,0xFB,0xCC,0x03,0xD6,0xFF,0xC6,0x79,0x10,0x4D,0x77,0x41,
+	0xBF,0xA8,0x79,0xE0,0xFC,0xB4,0xAF,0x8C,0x64,0xFE,0x13,0x92,0x04,0x55,0x99,0x56,
+	0xFB,0x5D,0xEE,0x5A,0x35,0x77,0xB0,0x96,0xC0,0x61,0xA8,0xB2,0xCA,0x7D,0x6C,0x84,
+	0x26,0x70,0x91,0xA9,0x6F,0xC5,0xBE,0x80,0xA8,0x43,0x21,0x74,0x59,0xF6,0xE5,0xAA,
+	0xB4,0x4C,0xC3,0x4B,0xE3,0xEB,0xE1,0xA9,0xFF,0xE2,0x3B,0x5C,0x35,0xA5,0xCB,0xF6,
+	0x24,0x6B,0x3F,0x0F,0xED,0x94,0x93,0xDE,0x08,0x55,0xAC,0x20,0x1A,0x28,0xEE,0xFE,
+	0xD7,0x77,0x3F,0x62,0x88,0x1F,0x19,0x65,0x66,0x30,0x64,0xB0,0x90,0xDD,0x50,0x46,
+	0x88,0xFA,0xE0,0x7F,0x10,0xC8,0x84,0xC3,0xA0,0xC0,0x15,0x5B,0x20,0xA7,0x93,0x1D,
+	0xA2,0xA3,0xFF,0x05,0x9C,0xB2,0xE8,0x59,0x3B,0xFC,0x57,0xF8,0xD3,0xF9,0xDD,0xFD,
+	0xD9,0xCA,0x65,0xC2,0xC7,0xDE,0xD8,0xB5,0x8C,0xE3,0x5B,0x20,0x22,0x4B,0xC9,0x3D,
+	0xE5,0x38,0x0B,0xC5,0x6B,0x08,0x43,0x6B,0x49,0xFF,0xF0,0x08,0x09,0xE4,0x71,0x53,
+	0x00,0xD4,0x13,0x39,0x18,0xED,0x40,0x64,0x22,0x05,0x2B,0x86,0x4E,0x3C,0xC0,0xD7,
+	0x1C,0xC0,0x88,0x2E,0x98,0xEF,0xC3,0x9B,0xF3,0xB6,0x6D,0x69,0xDF,0x65,0x89,0x09,
+	0xFA,0xA9,0x49,0xE9,0xF9,0x04,0x3F,0x79,0xCF,0x7B,0x4F,0x23,0xB7,0x53,0xD8,0xDE,
+	0xDC,0xE7,0xAF,0xE3,0x8B,0x0C,0x68,0x3B,0x60,0xD8,0xC5,0xFA,0x6D,0x54,0x69,0x7B,
+	0xDC,0x34,0x84,0x99,0x0B,0xB9,0x41,0xBB,0x30,0x76,0x78,0xD4,0x68,0x08,0x35,0x8A,
+	0xA0,0x90,0xBF,0xC8,0xF0,0x74,0xA4,0xAD,0x8D,0xA5,0xB2,0xAA,0x29,0x2C,0xF4,0x20,
+	0x12,0x06,0x09,0x9A,0xB7,0x82,0xB6,0xA2,0x5F,0x6D,0xAA,0x23,0x44,0xBB,0x19,0x7C,
+	0x01,0x7D,0xCC,0xEE,0x9F,0x8F,0x4F,0x3D,0x81,0x05,0x38,0xFF,0xD5,0x1C,0xF2,0x0E,
+	0xBC,0x0F,0x76,0x87,0x2B,0xD3,0xD0,0x5C,0x5D,0x38,0x7B,0x57,0x63,0xA1,0x81,0xB7,
+	0xCF,0x45,0xE4,0xA8,0xE9,0x63,0x1F,0xDD,0xC7,0xCB,0xFD,0x31,0x85,0x88,0xD8,0x1C,
+	0x94,0x10,0x47,0xD2,0x38,0x12,0xD8,0xEC,0xBB,0x92,0x29,0x93,0x2C,0xD0,0x08,0xB8,
+	0x2B,0x3E,0x5C,0x8D,0x5B,0xF5,0x20,0x97,0xF5,0x31,0xA6,0x16,0x88,0xE4,0x62,0xE0,
+	0xC7,0x13,0x2B,0x33,0xE5,0xD3,0xB5,0x1A,0xAF,0x56,0x02,0xE6,0xA4,0xDF,0x67,0xC5,
+	0x44,0x65,0xBD,0x50,0xF0,0x16,0xE8,0x7E,0x6A,0x20,0x4E,0xC8,0x28,0xD6,0x76,0x01,
+	0x83,0x84,0xDE,0xC1,0xA1,0xF5,0xE2,0x3F,0xA1,0x93,0x25,0x4F,0x6D,0x4D,0x87,0xE5,
+	0xDB,0x7D,0x36,0x93,0xF1,0xC8,0x45,0x6A,0x2B,0x37,0x81,0x75,0x44,0x74,0xD2,0xD0,
+	0xC0,0x29,0x2F,0xBD,0xB8,0xA3,0xB8,0x72,0x0E,0x90,0xDE,0xFF,0xF2,0x32,0x0A,0x9F,
+	0xBD,0x55,0xA7,0xB5,0xFC,0xED,0x6A,0x8B,0x77,0xB2,0x84,0x54,0x21,0xF7,0xC7,0x55,
+	0x61,0x68,0x44,0x2A,0x77,0x49,0xA2,0x50,0xE7,0xFB,0x88,0x5B,0x09,0xC6,0x3B,0x3F,
+	0x5F,0x81,0x35,0x64,0x71,0x31,0xF6,0xAF,0xF2,0x8A,0x12,0xC6,0x3C,0xDA,0x78,0x6C,
+	0xFC,0x36,0x23,0xAF,0x54,0xBD,0x66,0x5E,0x93,0xA9,0xA3,0xE9,0x68,0x95,0x39,0x42,
+	0xE0,0xBD,0xC5,0x67,0xAE,0x98,0x2E,0x38,0x91,0x6E,0x34,0xFD,0x5D,0xBD,0xC1,0xCB,
+	0xE0,0x92,0x1B,0xE1,0x5A,0x91,0x64,0x76,0xF1,0x3B,0x0B,0xD7,0x64,0x30,0x1D,0x07,
+	0x7D,0x7B,0x6F,0xAE,0x72,0x1B,0x57,0xB0,0xD2,0x7E,0xC8,0xC7,0x78,0x0C,0xD7,0xB5,
+	0xB5,0xCE,0x62,0x15,0xA1,0x1C,0x7C,0x18,0xB5,0xA9,0x07,0x7B,0xEC,0xEF,0x3F,0xF5,
+	0xB0,0xDF,0x50,0xB4,0xA9,0x67,0xD3,0xCC,0xD8,0x9D,0x92,0xE0,0x64,0xE1,0xFD,0xF1,
+	0x89,0x81,0xCD,0xE1,0x0A,0x89,0xAD,0x54,0xBD,0x74,0x54,0xE3,0x65,0x34,0x32,0x5D,
+	0x6E,0xAC,0xB3,0x68,0x39,0xDA,0x6E,0xB2,0xD3,0xB8,0x5D,0xB6,0x7A,0xBA,0xE1,0x38,
+	0x9A,0xBD,0xD0,0x06,0xF9,0xEA,0x7F,0xA3,0x18,0xB6,0xDD,0xDE,0xEC,0x1A,0x8E,0x70,
+	0x85,0xA1,0xC5,0x35,0xE8,0x7E,0x06,0x7F,0xEE,0x62,0x65,0x92,0xAF,0xC2,0x44,0x2A,
+	0xA4,0x41,0x3D,0xAD,0x1F,0x37,0x24,0xAC,0x4D,0x6A,0x6E,0x99,0x3D,0xAA,0x4B,0xE2,
+	0x3A,0x7A,0x2C,0x28,0x53,0x18,0x84,0x32,0x30,0x02,0x0B,0x05,0xF9,0xEF,0xD5,0x25,
+	0x6A,0xA5,0x1A,0x04,0x18,0xEB,0x1B,0xAF,0x12,0x15,0x01,0x8C,0x44,0x44,0xA5,0xB7,
+	0x66,0xDE,0x59,0x41,0x1F,0x9A,0x2D,0x7D,0xEB,0xDF,0x17,0x81,0xC7,0x3A,0x20,0xA1,
+	0x33,0xCB,0x57,0xC9,0x72,0xDD,0xB9,0x76,0x3A,0x90,0x05,0xDC,0x83,0xCF,0x04,0x39,
+	0x1C,0x5E,0x13,0x58,0x70,0x32,0x66,0x0D,0x36,0xEE,0x75,0x42,0x4B,0xFF,0xE7,0x5D,
+	0x1B,0x38,0x7D,0xD8,0x2A,0xFC,0x83,0xF4,0xD2,0x9B,0xF9,0x2C,0xE2,0x2E,0xF8,0x60,
+	0x2C,0xAE,0xFC,0xF9,0x48,0x80,0xC0,0xC7,0x80,0xC6,0xCE,0xBA,0x12,0xDC,0xCD,0x14,
+	0xD2,0xF6,0xB0,0x16,0x2F,0x4A,0xBB,0x30,0xDA,0x32,0xBF,0x01,0x6F,0x6E,0x8B,0x09,
+	0x01,0xD2,0x28,0x9E,0xEA,0xF3,0xCA,0xB6,0xBC,0x5A,0x66,0x93,0xF0,0x62,0xA5,0x62,
+	0x8F,0x20,0x63,0x06,0x42,0x06,0x1E,0xD0,0x97,0x6C,0x11,0xA0,0x36,0x0F,0xCB,0xC7,
+	0xCA,0x15,0x88,0xE3,0x50,0x77,0xDC,0xAA,0x81,0x57,0xFD,0x70,0x88,0xF2,0x45,0x89,
+	0x41,0x2F,0x6C,0x2F,0x92,0x03,0x31,0x29,0x93,0x17,0x51,0xFD,0x15,0x49,0xC4,0xEE,
+	0xCA,0xC8,0x62,0xE1,0xCC,0x08,0x12,0x37,0x3E,0x84,0x11,0x66,0x01,0x7F,0xE5,0x21,
+	0x92,0x79,0xF0,0x56,0xAA,0x2B,0xFA,0xAE,0x16,0xA0,0xAB,0xFC,0x97,0x8E,0x50,0xEE,
+	0x49,0xDD,0x8E,0xC1,0x07,0x2B,0xEB,0x14,0x80,0xFF,0x0B,0x35,0x40,0xC9,0x5E,0x2F,
+	0x98,0x0D,0xBA,0x72,0x3B,0x3B,0xB1,0x50,0x79,0x9F,0x88,0x2A,0x7D,0x35,0x7B,0xBF,
+	0x9A,0x98,0xE1,0xFE,0xF0,0xFF,0x5D,0xE5,0xB0,0xB7,0x75,0x89,0xA4,0x05,0xDC,0xE2,
+	0xD0,0xC3,0xCA,0xC1,0x08,0x80,0x0D,0x6F,0x0A,0xBB,0x72,0x8A,0x8D,0x01,0xEB,0x37,
+	0x8E,0xA6,0x90,0x30,0x48,0xE6,0x52,0x54,0x8F,0xF4,0x5C,0x22,0xF8,0x58,0xEC,0xCC,
+	0x45,0x40,0xDD,0x80,0x10,0xC5,0xB0,0x35,0xB4,0xFB,0x69,0xF9,0x36,0x29,0xFD,0x95,
+	0xC4,0x5B,0xCB,0x13,0x8A,0x1D,0xD7,0xE9,0x76,0x08,0x69,0x73,0x63,0xF7,0xAE,0x1B,
+	0x42,0x8C,0x0F,0xC1,0xA0,0x7A,0xEE,0x1D,0xC0,0xD6,0x32,0xC7,0x2E,0xDA,0xC4,0x6F,
+	0x29,0x3B,0xB5,0xC8,0x47,0xDB,0x7D,0x7D,0xA9,0x36,0x4D,0x3B,0x89,0x09,0x05,0x60,
+	0x1F,0x50,0xD7,0x52,0x99,0xEA,0x16,0x45,0x64,0xAE,0x49,0xF4,0xE4,0x76,0xB3,0xB5,
+	0x50,0xFB,0x52,0x05,0x0F,0xA5,0x5B,0x7D,0x5A,0xC3,0x42,0x36,0xAD,0xCB,0x65,0xAE,
+	0xBC,0x1E,0x46,0x8F,0xAB,0x14,0x3F,0x30,0x7A,0xA2,0x28,0x7C,0xA9,0x36,0xCE,0xAB,
+	0x8F,0x62,0x6B,0xCC,0xD2,0x28,0x0C,0x78,0x9F,0x3C,0x01,0xCB,0x9B,0xBA,0x47,0xA7,
+	0xF5,0x84,0x8C,0xE6,0xC0,0x00,0xFC,0x08,0x49,0x59,0x4B,0x17,0x33,0xB0,0xD3,0xBA,
+	0xC3,0x0B,0xD8,0xCF,0x7B,0x70,0x7A,0xE3,0x6B,0xD8,0xCC,0xD5,0xFA,0xA6,0x99,0x3A,
+	0x06,0xF5,0x86,0xE0,0xE6,0xA5,0x16,0x92,0x09,0x6E,0x6B,0xBA,0x59,0xD2,0x74,0x2A,
+	0x5B,0x27,0x81,0x64,0x60,0x8D,0x9F,0x34,0xAC,0x23,0x4A,0x52,0xFF,0xEB,0x98,0x9A,
+	0x88,0x06,0x6D,0xB7,0x23,0x05,0xE6,0xB6,0x4C,0x73,0x24,0x53,0x5E,0xB7,0xEF,0x87,
+	0x00,0xB1,0xB6,0xE1,0x4E,0x41,0xB1,0x2C,0x1D,0xF2,0x68,0x54,0x55,0xA3,0xE8,0x52,
+	0x9C,0x43,0x98,0x25,0x77,0x42,0xDD,0x8B,0x78,0x55,0x40,0x38,0x69,0xDB,0x2E,0xAE,
+	0x3F,0xDC,0x5F,0xDE,0xEF,0x49,0x23,0xB3,0x05,0xE5,0x64,0x53,0x5A,0xA1,0xCD,0xD2,
+	0xCC,0xDB,0x53,0x0A,0x98,0x99,0x01,0x06,0x48,0xFD,0x2F,0x97,0x44,0xED,0xEC,0x53,
+	0xF5,0x16,0x44,0xAB,0xE2,0xC6,0x2E,0xF9,0x0B,0x84,0x40,0x0B,0xCC,0xAE,0x1A,0xA1,
+	0x25,0xDC,0xC0,0xEA,0x1A,0x31,0x30,0x60,0x94,0x73,0x87,0xEA,0xE7,0x5F,0xCC,0x5F,
+	0xF9,0x21,0xAB,0x65,0x0C,0xB5,0x02,0xF0,0x9B,0x9B,0xDA,0x06,0x40,0x91,0x7A,0xFD,
+	0xED,0xBF,0xFB,0xD6,0x98,0xF7,0x97,0x6E,0x40,0xF9,0x83,0x33,0xF1,0xD4,0x50,0xAB,
+	0x54,0x15,0x12,0x42,0x5C,0xDB,0x31,0x4E,0x6D,0x5C,0xA7,0x06,0x7C,0xD7,0xA6,0x40,
+	0xF0,0xF4,0x14,0x8E,0xF3,0x0E,0x56,0x75,0x20,0x40,0x1C,0xA8,0xCF,0x75,0x46,0x83,
+	0x8A,0xB4,0xF1,0xBA,0x5C,0x7D,0x7B,0x91,0x4F,0x1E,0xE8,0x88,0x84,0xC5,0x04,0x55,
+	0x6B,0x82,0x35,0x03,0xD3,0x23,0x2F,0x9C,0x5C,0x55,0x13,0x83,0xD1,0x2C,0xB5,0x31,
+	0x07,0x0D,0x6F,0x1E,0x11,0x24,0x3E,0x9F,0x45,0x34,0xB2,0xCB,0xAA,0x12,0xFD,0x06,
+	0x2C,0x31,0x2A,0x8D,0x7E,0x02,0xE6,0xAF,0x3B,0x93,0x89,0x50,0x98,0xA3,0x01,0xD4,
+	0x07,0x75,0x65,0x87,0x0B,0x5F,0xC6,0x83,0x47,0x5A,0x7A,0x87,0x0C,0xCC,0x37,0x10,
+	0x27,0xF2,0x42,0xD8,0xBA,0x58,0x62,0xF8,0xBA,0x14,0x14,0xD3,0x41,0x20,0xB8,0x40,
+	0xD3,0xB8,0x2E,0x1E,0x53,0x42,0xB4,0x40,0xD0,0x99,0xF4,0xAC,0xD8,0xF3,0x6C,0x85,
+	0x27,0xE9,0x56,0xDA,0xF2,0x4E,0x9F,0xA4,0x3B,0xCE,0xA1,0x7A,0x2D,0x18,0x2D,0x1B,
+	0x48,0x70,0xBE,0x17,0x10,0x47,0xB0,0x0F,0x89,0x8A,0x58,0xAB,0x75,0x5A,0xE8,0x4F,
+	0xB3,0xAC,0x28,0x13,0x31,0x63,0x09,0x7D,0xE8,0xDB,0xF5,0x85,0xEE,0xC1,0x6F,0x08,
+	0xD7,0x51,0x5C,0xD6,0xC6,0x4C,0x0A,0x40,0xEA,0x53,0x46,0x9B,0xE2,0x81,0xA9,0x9D,
+	0x66,0x80,0x32,0x7A,0x83,0x5A,0x7C,0xCC,0xEE,0xAA,0x5F,0xA5,0x0C,0x35,0x3D,0x20,
+	0xFC,0xD7,0x54,0xE9,0x58,0x19,0x81,0xFB,0xE0,0x47,0x30,0xA8,0x95,0xE1,0x74,0x37,
+	0xFE,0x37,0xF0,0x63,0x7A,0x2E,0x74,0xF3,0x3A,0x77,0xE6,0xA1,0xCA,0x16,0x07,0xE8,
+	0x94,0x9E,0xFE,0xA5,0x25,0x5D,0x08,0x02,0xEE,0x64,0x43,0x02,0x51,0xBB,0xD4,0xF2,
+	0xD2,0xBF,0x80,0x65,0xA0,0xC5,0x55,0x23,0x1E,0xD5,0x2C,0x06,0x95,0x9A,0xFE,0xCD,
+	0xDA,0x3B,0x9D,0x34,0xFB,0xF8,0xEF,0x78,0x7B,0xF4,0x46,0xEE,0xE5,0xC9,0xA8,0x90,
+	0xA5,0x38,0xEC,0x21,0x46,0x95,0x8C,0xE7,0x54,0xE9,0x93,0xF4,0x44,0x38,0x04,0x6E,
+	0x01,0x7D,0xB9,0xA1,0xBB,0x49,0x3B,0x11,0xDD,0x0D,0x54,0x90,0xCD,0x9C,0xBF,0xBE,
+	0xC0,0x98,0x6A,0xC7,0x30,0x0B,0x30,0xD6,0x19,0x0C,0x02,0x1C,0x24,0xC4,0xAF,0x7C,
+	0x10,0xF8,0x67,0x07,0x2E,0x84,0x7F,0x0A,0x25,0xE0,0x1C,0x5E,0x4F,0x51,0x9F,0x66,
+	0x99,0x3C,0x93,0x55,0x3F,0x47,0x98,0x7A,0x99,0x2D,0x15,0x0C,0x22,0xD4,0x9A,0x82,
+	0x4F,0x43,0x3B,0x49,0x6A,0x83,0x2A,0x36,0xEE,0xAD,0xDE,0xEE,0x75,0xEC,0xF5,0x7E,
+	0xF4,0xA8,0xEB,0xD1,0x70,0x51,0x47,0xB6,0x4C,0xEA,0x66,0x88,0x82,0x02,0x19,0xF5,
+	0x53,0xAF,0xC4,0x41,0xC1,0x89,0x72,0x42,0x2C,0xB2,0x32,0xCC,0x09,0x12,0x0B,0xA9,
+	0x7F,0x8A,0x97,0x6C,0xB3,0x58,0xA5,0x2D,0xE4,0xE8,0x91,0xD6,0xFD,0xB7,0xC9,0x7E,
+	0x32,0x3B,0x8A,0x9F,0x93,0xFA,0xBA,0x4A,0x26,0x2A,0x0E,0x83,0xDD,0x4E,0x55,0x12,
+	0xA8,0xC7,0x73,0xCB,0xBC,0x78,0xD3,0xB5,0x7C,0x73,0x77,0x1F,0x6F,0x9E,0xB7,0xDA,
+	0x7F,0xBA,0xD9,0x91,0xE9,0x52,0x63,0x1F,0x36,0xC5,0x5D,0x2C,0x18,0x7A,0x7E,0xF4,
+	0x1A,0x16,0xBA,0x79,0xEF,0xE2,0x20,0x03,0xEA,0x20,0xED,0x65,0x73,0x90,0x11,0x2F,
+	0xD7,0x92,0x90,0x7C,0xE4,0xA1,0xA8,0x6A,0x24,0x6D,0x66,0x6D,0xDC,0xB2,0x61,0xDC,
+	0xCD,0xA5,0xB5,0xFF,0x2F,0x3A,0xF2,0xF0,0x22,0x02,0x2B,0x84,0xB1,0x49,0xA1,0xE7,
+	0xC8,0x7C,0x85,0x28,0xB8,0xCD,0x00,0x17,0x22,0x3E,0x23,0x44,0x8E,0xCA,0xD3,0xDC,
+	0x77,0x5A,0xA7,0x6D,0xDF,0x67,0xFB,0x41,0x33,0x92,0x11,0xB3,0x87,0x02,0xA4,0x89,
+	0x09,0xF6,0xBF,0xE0,0x81,0x99,0x07,0xF9,0x3D,0x18,0x5A,0xE2,0x7C,0x5D,0xBD,0x16,
+	0xE8,0xA4,0x92,0x2A,0xAC,0x3A,0xFE,0xB0,0x75,0x17,0xD5,0x48,0x9A,0xCA,0x81,0x9F,
+	0x27,0x06,0x19,0x81,0xE3,0x6C,0xCA,0x12,0x0C,0x6D,0xC9,0x88,0xFF,0x10,0x55,0x77,
+	0x1A,0x49,0xE7,0xEB,0xFB,0x6D,0xD8,0x6C,0x31,0x58,0x8D,0x13,0x7A,0xFE,0x3C,0x39,
+	0x90,0x1D,0x59,0x51,0x62,0xBE,0xA2,0xEC,0xE9,0x05,0x65,0x95,0xF9,0xBC,0x2C,0x2B,
+	0x8F,0xA6,0x98,0xA4,0x99,0x03,0xB9,0x7C,0xAC,0x50,0x69,0x3B,0x8D,0x3E,0x96,0x60,
+	0x47,0xE9,0x2C,0x96,0xAB,0x35,0x68,0xBC,0xA0,0x1B,0xB1,0x1C,0x93,0x9A,0x8D,0xFE,
+	0x9A,0x48,0x6B,0xC2,0x7C,0xA7,0xE9,0xC0,0x37,0x53,0xBA,0xCB,0xF2,0x3D,0x7C,0xC1,
+	0xD6,0xAE,0xAD,0x66,0x69,0x96,0xB9,0x3B,0x7D,0x9F,0x72,0x11,0xC9,0xC0,0xA7,0x9C,
+	0xCD,0xA1,0x06,0x71,0xB5,0x19,0x7D,0x76,0x3E,0xAD,0x87,0xDB,0x63,0xCD,0x00,0x86,
+	0x6B,0x71,0x62,0x5E,0xB5,0x78,0xB6,0x1E,0x22,0xAA,0x2B,0x23,0x37,0xBF,0xCC,0xEC,
+	0x90,0x08,0x9C,0xBE,0xBD,0x4B,0x8D,0xC3,0x58,0xF5,0xA6,0x6C,0x99,0xC0,0xCE,0x61,
+	0x34,0xBE,0x6F,0xB1,0x47,0xA8,0x12,0x2A,0x67,0x6D,0x37,0x64,0x37,0xA2,0x0D,0xD7,
+	0x40,0xF8,0x9B,0xC0,0xEA,0x94,0x45,0xD1,0xD6,0x88,0xFF,0xD9,0x0A,0x91,0xC3,0xE6,
+	0xFF,0xD6,0xF6,0x4D,0x20,0xFD,0xFF,0x63,0x54,0xBC,0x3E,0x2C,0x09,0x04,0x4D,0xE3,
+	0xC8,0xD7,0xCA,0x44,0x47,0x99,0x24,0x63,0xAB,0xFA,0x8D,0x3B,0xFF,0x3F,0xE2,0x91,
+	0xC8,0xEA,0xF2,0xCC,0x25,0xF7,0xB2,0xEE,0xCB,0xD8,0x84,0x8A,0xA4,0xF9,0x16,0x6B,
+	0xF7,0xC0,0xA7,0x0A,0xAD,0xD7,0x21,0x2C,0x99,0xB5,0x0D,0x3D,0xA3,0xEC,0x3C,0xB1,
+	0xD9,0x27,0xC5,0x1E,0x09,0xB8,0xCB,0x3B,0x6E,0x6A,0xBF,0xCE,0xF3,0x8E,0x5C,0xBF,
+	0xCC,0xBD,0xFB,0x8E,0x5B,0x0E,0xA3,0x23,0xED,0x91,0x40,0x03,0x47,0x75,0x7E,0xF3,
+	0x54,0x8A,0x10,0xD7,0x91,0x2B,0x59,0x88,0x8B,0xF7,0x27,0xB2,0x07,0xFE,0x3C,0xB3,
+	0x72,0xFA,0x56,0xE0,0x52,0x6B,0x4E,0x7E,0x5F,0xF8,0xCB,0x04,0x7D,0x16,0xA9,0x24,
+	0x6F,0xDA,0x0B,0x20,0x39,0x4B,0x3E,0x63,0xF5,0xF7,0xDB,0xCA,0xF9,0xE9,0x1F,0xE7,
+	0xB4,0xE1,0xAA,0xF6,0xD0,0x39,0x21,0x43,0x15,0x71,0x6D,0xB0,0x0D,0x74,0x8A,0xE4,
+	0xCC,0xB2,0xCD,0x36,0x20,0x7C,0xF2,0x4E,0x22,0x0F,0xBF,0x79,0xD1,0x89,0x1A,0xC6,
+	0x95,0x0E,0xA5,0xF4,0x37,0x51,0x9B,0xF2,0xCA,0xD6,0xDE,0x25,0xD8,0x24,0x57,0x1E,
+	0xF4,0x2B,0xBE,0x68,0x7D,0xE4,0xB2,0xC7,0x61,0x0E,0x67,0xD4,0x8C,0x3B,0xD8,0x9D,
+	0x24,0xAD,0x14,0x55,0xF8,0x4A,0x9B,0xB9,0x4A,0x7C,0x11,0xA5,0x6F,0x1B,0xB2,0x94,
+	0x56,0x18,0xC7,0x1C,0xB2,0xF9,0xBA,0x36,0xDF,0xB6,0x3A,0x84,0xB0,0x7E,0xF0,0xAB,
+	0x6D,0xFD,0x7C,0x60,0x62,0xEE,0x2A,0x0C,0x89,0xF8,0x5E,0xDE,0xA6,0xDF,0x86,0x75,
+	0x18,0x03,0x84,0xDE,0x77,0x25,0x85,0x57,0xAE,0x11,0x88,0xE6,0xC3,0x18,0x0D,0xE2,
+	0x9F,0x58,0x89,0x20,0xB5,0xAC,0x17,0xD6,0x67,0x36,0xE3,0x11,0x92,0xF8,0xA2,0xE2,
+	0x78,0xDE,0x63,0x06,0x67,0x0D,0x24,0x4D,0x6F,0x84,0x10,0x79,0xBD,0x68,0x11,0x3D,
+	0xA9,0xA7,0x20,0x5B,0x39,0xCE,0xEE,0xDF,0x80,0xDC,0xC8,0xB8,0xF1,0xFA,0x01,0xA2,
+	0x62,0x01,0xB2,0x5D,0x1E,0xEF,0x07,0x00,0x0E,0xA3,0x3A,0x8F,0x69,0xDF,0x36,0xF8,
+	0x1F,0x55,0x34,0x30,0x09,0x22,0x7E,0x7C,0x83,0xFC,0xDA,0x7A,0x36,0x1A,0xEF,0x70,
+	0x33,0xC6,0xF5,0x00,0x0F,0x01,0x49,0x7E,0xA0,0xF9,0x26,0x9A,0xD9,0x6E,0x19,0xC6,
+	0x16,0x3C,0xB0,0xC2,0x4C,0xBF,0xDA,0xAD,0xDC,0xE3,0x93,0x87,0x9D,0xE6,0x11,0x8A,
+	0x86,0xCA,0x03,0x6A,0x83,0x4E,0x86,0x6F,0x00,0x76,0xE6,0x9D,0xCF,0xF3,0x24,0x5B,
+	0x04,0xD8,0xCE,0xD5,0xF2,0x1A,0x49,0x66,0xB3,0xD0,0x9F,0x25,0x79,0x4B,0x2C,0xF5,
+	0x36,0x85,0xAB,0x80,0x5F,0x27,0x36,0xBD,0x84,0xD0,0x19,0xA1,0xD2,0x92,0xB5,0x98,
+	0x62,0x5F,0x9A,0x32,0xC8,0x2A,0xEC,0x6A,0x5D,0x72,0x75,0x73,0x56,0x99,0xE8,0x77,
+	0x15,0x9C,0x7D,0xA0,0x7A,0x18,0x3D,0x55,0x1F,0x66,0xFC,0xA6,0x74,0x47,0xE6,0xA2,
+	0x10,0xBD,0xC3,0xC3,0x8F,0x85,0xE1,0xFB,0xA8,0x0C,0x61,0x78,0xA3,0x53,0x4D,0xF7,
+	0x75,0x3E,0xAB,0x8B,0x2D,0x3B,0x1B,0x2C,0x40,0xE6,0xB5,0xFC,0x3C,0x64,0x22,0xF6,
+	0x3B,0xB8,0x65,0x93,0x5A,0xE9,0xD6,0x95,0xAD,0xCB,0xC6,0x8E,0xD5,0x27,0xBC,0xD3,
+	0xEC,0x65,0x61,0xE8,0xF7,0x68,0x91,0x61,0x24,0xB2,0x22,0xF3,0x64,0xE4,0xF8,0x8C,
+	0x24,0x0E,0xE4,0xC4,0x4A,0xAD,0xCC,0x6B,0x5D,0xA5,0x42,0x46,0x3E,0xDF,0x3D,0xEE,
+	0x8D,0x2E,0x22,0xEC,0x41,0x52,0xAE,0xB1,0xFF,0xE4,0xF2,0xE7,0xF2,0xC4,0xCF,0x4D,
+	0x3D,0x76,0x3A,0xF0,0xC5,0x89,0x7F,0xFF,0xCB,0xAC,0x7F,0xCD,0xB3,0x60,0x61,0x18,
+	0xDF,0x0B,0x8B,0x45,0x05,0x89,0xB6,0x6A,0x4E,0x23,0x10,0xF4,0xD2,0x75,0xF0,0x25,
+	0xB0,0x7F,0x4E,0xF2,0x68,0x44,0x7E,0x34,0x9C,0xE5,0x02,0xC4,0xA0,0xB2,0x65,0x65,
+	0xA9,0xD5,0xD4,0xE9,0xAE,0xC4,0x84,0x07,0x4D,0x76,0x85,0x44,0xEF,0x75,0xD3,0xCF,
+	0x8E,0x5A,0xF9,0x5B,0x71,0x9E,0x31,0xEC,0xBC,0xFE,0x7B,0xD8,0x7E,0x32,0xE0,0xB0,
+	0x44,0x72,0x4A,0xFD,0x6D,0xFA,0xBE,0xAC,0x67,0x59,0x53,0x87,0xBF,0x43,0x71,0xCE,
+	0x49,0x09,0xD9,0x0D,0x99,0xE4,0xE6,0xDC,0x55,0xFA,0xF4,0x43,0x9C,0x00,0x36,0x0D,
+	0xF5,0xE4,0x28,0xD5,0x98,0x36,0x6A,0x20,0xB0,0x81,0x7C,0x39,0x6A,0x9F,0x09,0xBD,
+	0x13,0xC0,0x3B,0x6A,0xD4,0xF8,0x79,0x3A,0x53,0x6F,0xBF,0xC9,0x1F,0xE5,0x3C,0x70,
+	0x35,0xD1,0x31,0x61,0x5C,0xA8,0x99,0x62,0xA2,0x6B,0x83,0xB6,0x7B,0x01,0x93,0x88,
+	0x65,0x4C,0x59,0x95,0xEB,0x68,0x45,0xCD,0xDC,0xEC,0x8F,0x6B,0x6A,0xF0,0x79,0xF4,
+	0xC1,0xD8,0x68,0xE6,0x93,0x60,0xC0,0xA8,0xE8,0xE6,0xE0,0x12,0x51,0xDC,0x88,0xDF,
+	0x1B,0xE8,0xE2,0xFB,0x19,0x91,0xD4,0xE1,0xB8,0x6F,0x27,0x17,0x84,0xB4,0x78,0x4E,
+	0x9D,0x7A,0x0A,0x78,0x52,0x4A,0x4D,0x03,0x87,0xAF,0x94,0xF8,0xF8,0xA7,0x24,0x12,
+	0xD7,0xF0,0xF2,0xA5,0x56,0xF0,0x24,0xC6,0x48,0x40,0x29,0x3A,0xE2,0x8F,0x0D,0x60,
+	0x0A,0xA8,0x0D,0x23,0x74,0xC9,0x03,0x1B,0xD3,0x37,0x15,0x04,0x61,0xE8,0x2F,0x05,
+	0x9F,0x29,0x22,0x6F,0x22,0xBB,0xB6,0x0C,0x11,0xB1,0xC0,0x43,0x68,0xC0,0x08,0x23,
+	0xB2,0xCD,0x32,0xA2,0xBB,0xAE,0x6E,0x88,0xE5,0xDD,0x27,0xE5,0x78,0xEF,0x62,0x35,
+	0x67,0x72,0x89,0xE3,0xB3,0xC3,0xF9,0xE8,0xA6,0x33,0x74,0x42,0x3D,0xB5,0x1F,0xAE,
+	0x18,0xF5,0x1E,0xD4,0x9D,0x58,0x74,0xE9,0x0F,0x9A,0x62,0x25,0xFD,0x73,0x6F,0x9D,
+	0x29,0x60,0x0A,0xB4,0xBA,0x06,0xFE,0x82,0x5A,0xA7,0x23,0x02,0x77,0x06,0x66,0x10,
+	0x1C,0x36,0x10,0x37,0xAC,0x73,0x66,0x98,0x36,0x4A,0xCD,0x6F,0x15,0xA4,0x19,0xF7,
+	0x4A,0xD7,0x03,0x38,0x9B,0xE4,0x61,0x1E,0x5D,0x79,0x87,0x2D,0xA2,0xA5,0xB1,0x2D,
+	0xCE,0x91,0x2D,0xD0,0xAE,0x20,0xAB,0xA9,0x37,0x5F,0x22,0x0A,0x2C,0x34,0xEC,0xB3,
+	0xE0,0xC7,0xD3,0xC4,0x68,0x49,0x42,0x1E,0x1C,0x2D,0xCD,0x54,0xEA,0x91,0xB0,0x6F,
+	0x6D,0xC6,0x25,0x06,0x31,0x0C,0x76,0xA1,0x56,0x10,0x5E,0x77,0x57,0x80,0xEE,0x57,
+	0x45,0x2A,0x00,0x22,0x6B,0x60,0xDD,0x8E,0xB8,0x06,0x8F,0x9F,0x03,0x64,0xC4,0x88,
+	0x63,0xEF,0xCE,0x35,0x95,0xC1,0xA9,0x15,0xB1,0xC7,0x69,0xE2,0xD0,0x58,0xD5,0x57,
+	0xE0,0x5E,0x87,0x51,0xFB,0x22,0xF4,0xFA,0x80,0xFF,0xA0,0x01,0x0C,0x3F,0x82,0xFB,
+	0xC6,0x31,0x02,0xB0,0xBD,0xA3,0x78,0x59,0x32,0xC3,0x3E,0xC1,0x92,0xBD,0xE6,0x7C,
+	0x1D,0xF9,0x5F,0x34,0x06,0x39,0xA0,0x11,0x91,0x19,0x16,0x39,0x10,0x90,0x56,0xE8,
+	0xF2,0x99,0x03,0xDE,0x9F,0x7C,0x12,0x5C,0x11,0x66,0x25,0x23,0x44,0x81,0xB2,0x08,
+	0xFB,0xC1,0x13,0x5B,0x76,0x64,0x91,0x93,0x2A,0x6A,0x2C,0x04,0xAD,0x5E,0x19,0xD4,
+	0x33,0x4A,0x6D,0x2B,0x28,0x64,0xEE,0xA6,0xFD,0xFB,0x12,0xC8,0x99,0x75,0x42,0x09,
+	0x35,0xC4,0xF7,0xDF,0x10,0x5D,0xBF,0xDB,0xBE,0xA6,0x72,0x14,0x82,0xF7,0xE4,0x92,
+	0x18,0x10,0x5B,0x03,0xA3,0xDC,0x13,0x03,0x82,0x76,0x57,0x64,0x2D,0x20,0xAB,0xBB,
+	0x3A,0x88,0xF5,0x53,0xC2,0x16,0x20,0xA3,0x31,0xEB,0xC2,0x4E,0xDC,0xA7,0xE4,0x38,
+	0x4A,0x24,0xED,0x2F,0xCF,0x5E,0xF8,0x33,0xA2,0xA4,0x46,0x5A,0x5B,0x8A,0x6D,0xA7,
+	0xB1,0xA6,0xD6,0x0E,0x02,0x11,0xB8,0xD6,0x7C,0x81,0xAE,0x72,0x22,0x60,0x35,0x09,
+	0xAE,0x88,0xE5,0x4C,0x3D,0x08,0x70,0x7E,0x3C,0x8A,0x79,0xAD,0xFC,0xF3,0x73,0x2E,
+	0x6B,0x10,0xA1,0x74,0xCC,0x4D,0x5D,0xAA,0x9C,0x73,0x67,0x7A,0xEA,0x8E,0x6F,0x9F,
+	0x75,0x88,0xD8,0xB3,0x39,0xE2,0xF9,0x55,0x82,0xFA,0x30,0x7F,0x6F,0xA3,0x6F,0x94,
+	0x0D,0x6E,0xBD,0xBF,0xA7,0x48,0x49,0x68,0x22,0x04,0x34,0x6C,0x5A,0xAD,0x4B,0x68,
+	0x10,0x6B,0x5B,0xE1,0xD8,0x4A,0x45,0x4A,0x5F,0x1D,0xF6,0x49,0x2A,0xDA,0x87,0xC1,
+	0x72,0x04,0x6F,0x34,0x2B,0x6E,0x22,0x97,0xBD,0xD4,0x52,0x76,0xF0,0x1D,0xEA,0x85,
+	0x4B,0x39,0x55,0xE6,0x86,0xAA,0x40,0x42,0xC8,0xC7,0xAF,0x47,0x14,0xD1,0xC2,0x40,
+	0xA2,0x1F,0xA7,0x58,0xEE,0xD9,0xFC,0x12,0xD8,0x47,0x99,0xEF,0xA1,0x5A,0xE0,0x23,
+	0x1C,0xA4,0x3A,0x19,0x1A,0xCA,0x08,0xAA,0x04,0xF4,0x7D,0x16,0x8B,0xCA,0xD1,0x4A,
+	0xF4,0x9D,0x8C,0x7A,0xBC,0x26,0x33,0x78,0xD4,0x5D,0x6F,0x7C,0xC9,0x69,0x7C,0x3E,
+	0xB3,0xC6,0x18,0x05,0x3C,0xB7,0x3D,0x84,0xBB,0x0F,0xAB,0x0B,0xEA,0x85,0x6F,0xD7,
+	0x4E,0x83,0x35,0x61,0x40,0x5A,0x14,0xD3,0x08,0x8B,0x36,0xE3,0xC4,0x81,0x84,0xA5,
+	0x80,0x3E,0x92,0x6C,0x1E,0x64,0xB9,0xDD,0x3D,0xFF,0xFC,0xC6,0x82,0x14,0xA7,0x4C,
+	0xB1,0x04,0xCA,0xCA,0x94,0xA0,0x5B,0x7A,0xBA,0x50,0xC1,0xA6,0x60,0x5B,0x67,0x71,
+	0xBB,0xE1,0x5C,0xAA,0xB3,0x4D,0xA9,0x20,0x2F,0xE0,0x44,0x37,0x8D,0xFC,0xF4,0x5A,
+	0xFE,0x14,0xDE,0xAD,0x6C,0x81,0x95,0x3A,0x3B,0x49,0xDC,0x40,0x28,0x8A,0x2D,0xC5,
+	0x78,0x6A,0x03,0x51,0x3B,0xA8,0xA6,0x96,0x7D,0x34,0xE9,0x83,0x2B,0x65,0x85,0x98,
+	0xBB,0x71,0x02,0xE0,0x95,0xC2,0x2E,0xCD,0x22,0xBB,0xE6,0xBD,0x58,0x97,0x57,0x81,
+	0x57,0x38,0x24,0x49,0x84,0x20,0xC9,0x67,0xCC,0x27,0x4E,0xEF,0x15,0xE5,0xAD,0x49,
+	0x12,0x23,0x4C,0x09,0x91,0x1C,0x85,0xB6,0x3D,0x30,0x68,0xCD,0xC3,0x08,0x49,0xD6,
+	0x32,0x9F,0xD1,0xC3,0xC7,0x0E,0x41,0xEB,0xB7,0x83,0xAB,0x2A,0x2B,0xE3,0x96,0x87,
+	0x01,0x5A,0xEA,0x67,0x03,0x4B,0x75,0x23,0x5A,0xD8,0x1F,0x07,0x29,0x38,0x0A,0xB4,
+	0x27,0xD6,0xBA,0x8A,0xF3,0xE5,0xF1,0x73,0x62,0x24,0xA3,0xB2,0x99,0x96,0x8C,0xD3,
+	0x10,0x06,0x1E,0x3A,0xED,0x51,0x83,0xD8,0xD4,0x71,0x48,0x64,0x4A,0x59,0x4A,0xBF,
+	0xC3,0xB1,0x77,0x69,0xC2,0x85,0xFD,0xF4,0x78,0x44,0xA9,0x52,0xAF,0x70,0xF4,0x5B,
+	0x0B,0x83,0x8F,0x4C,0x29,0x2C,0x08,0xE3,0x92,0xDE,0x38,0x05,0x25,0xEF,0x64,0x03,
+	0x52,0xC1,0x40,0x50,0x94,0x75,0xF0,0xB1,0x3C,0xEE,0x3E,0x27,0x76,0x40,0x81,0x97,
+	0x12,0xBC,0x9E,0x8E,0x55,0x1C,0x97,0xF2,0x3B,0xC7,0xDB,0xFB,0x12,0x38,0xA1,0xA8,
+	0xE8,0xD0,0xAC,0x4F,0xBE,0x91,0x29,0x4B,0x06,0xC5,0x35,0xE7,0xA4,0x7B,0x1B,0x9C,
+	0x8D,0xD5,0xD5,0x4B,0xA4,0x17,0xA2,0xF4,0x49,0xFC,0xCD,0x89,0xEB,0xA1,0xEA,0x95,
+	0xBC,0xF6,0x85,0x45,0xF9,0x42,0x56,0x8B,0x4E,0x28,0x55,0xE6,0x3D,0x91,0xC6,0x66,
+	0x1E,0x1A,0x85,0xF4,0x50,0xEA,0x77,0x28,0x66,0x9D,0x7E,0x20,0xFC,0x6E,0x5D,0x8A,
+	0xF9,0xA4,0x95,0x52,0x89,0xF9,0x68,0x06,0x65,0x0E,0x37,0xD5,0xB0,0x0C,0x7D,0x6E,
+	0x73,0x4A,0x6E,0xA0,0xA2,0x96,0xDD,0xE4,0xB2,0xA8,0x2D,0xFE,0xD0,0x55,0xF5,0x06,
+	0x62,0x60,0x1E,0x0E,0xD7,0x83,0xB7,0xE1,0x36,0xFE,0x2C,0x1E,0x4D,0x84,0x15,0x6F,
+	0xFC,0x80,0x9A,0x05,0xB9,0x1D,0xF7,0xFC,0x3F,0x2C,0x36,0x78,0x6E,0x62,0x03,0xA1,
+	0x30,0xF4,0xA8,0xA9,0x79,0x4E,0xB7,0x09,0xC9,0x5E,0xEA,0x77,0x2C,0xFB,0x55,0xB2,
+	0x2D,0x29,0x8E,0x0C,0x5A,0xF5,0x5C,0x00,0x3B,0x2E,0x89,0x01,0xAA,0xB2,0xE2,0x15,
+	0x30,0x9B,0x45,0xA3,0x12,0xFA,0x88,0xA5,0x0D,0x61,0xC3,0xBC,0xB8,0xA1,0xC0,0x59,
+	0x19,0x1B,0xA6,0xA9,0x91,0x5E,0x8D,0xC3,0x49,0x76,0xDE,0x1B,0x51,0x12,0xD2,0xB2,
+	0x46,0x5B,0x2A,0xE6,0xD4,0x7C,0x9F,0xA1,0x50,0xA9,0xAE,0x92,0x8F,0x0B,0xFC,0xEB,
+	0x0B,0xCB,0xE5,0xE6,0xAE,0xD4,0x7D,0xAB,0x60,0x2D,0x2A,0xAC,0x71,0x23,0xD1,0x91,
+	0xB5,0x99,0xCF,0x34,0x2C,0xD3,0xC6,0xF0,0xED,0x38,0xA2,0x70,0x50,0xA3,0xDF,0xCD,
+	0xA0,0x0F,0x28,0x41,0xB2,0x74,0x43,0x69,0x33,0x42,0xEB,0x43,0x3E,0x46,0x7C,0x1C,
+	0x24,0xD0,0xCF,0x19,0xAF,0x86,0xB8,0xE4,0x1C,0x96,0x02,0xAF,0xEB,0xD1,0xCC,0x67,
+	0x74,0x07,0x42,0xF7,0x8D,0x69,0x58,0x42,0x7D,0xDE,0x09,0x65,0x79,0xEE,0x86,0xC2,
+	0x81,0x3D,0x96,0x3D,0x38,0xF0,0xB2,0x4C,0x29,0xB3,0xAB,0xA5,0x91,0x93,0x4C,0x9A,
+	0xD7,0x78,0xCD,0xFA,0x7C,0x4E,0x4B,0x58,0x87,0x49,0x1D,0xED,0xC0,0x4E,0x48,0x63,
+	0x01,0x0A,0xE0,0x68,0x9E,0xFB,0x50,0xCE,0xE4,0x16,0xCF,0xAC,0xAA,0x33,0x4E,0x5C,
+	0xAC,0x57,0xE6,0xE2,0xFE,0x56,0x8E,0xFD,0xC4,0x5D,0x34,0x2F,0x3E,0x10,0x47,0xC6,
+	0x47,0xF9,0xA8,0xDA,0xA2,0x13,0xF2,0x20,0x71,0x4C,0x2A,0x24,0x90,0x5D,0xC1,0x00,
+	0xA4,0xB3,0x87,0x75,0xF2,0xF1,0x8A,0x2A,0x38,0x81,0xC6,0x6B,0x4D,0xEA,0xEE,0xAC,
+	0x2E,0xEA,0xAE,0xF6,0x73,0x9B,0x59,0xF9,0xD1,0x0F,0x0C,0xF8,0x92,0x95,0xB8,0xAA,
+	0xC3,0xAE,0x80,0x9A,0xD1,0x32,0x4A,0xC0,0x02,0xCD,0xA3,0xDE,0x4D,0xC5,0x2D,0x0E,
+	0x9D,0x6C,0xE2,0x24,0x91,0x98,0x9D,0xE2,0x3B,0x8A,0x95,0xC7,0x33,0xC1,0xB1,0x46,
+	0x62,0x12,0x12,0x64,0xC8,0x1E,0x39,0x01,0x5C,0x10,0x05,0x6F,0x37,0xE3,0xCC,0xC8,
+	0xA3,0x38,0xD3,0xB9,0xE8,0xAD,0xD4,0x6C,0xCB,0x7A,0x1D,0x5A,0x9B,0x5C,0xB1,0x8F,
+	0x04,0xAB,0xAE,0x82,0xA7,0xA2,0xC8,0x02,0x5D,0x82,0xF9,0xBC,0x70,0xF1,0x19,0x93,
+	0x24,0xAD,0x14,0x33,0x92,0x0D,0x7E,0x14,0xDE,0xB1,0x1A,0x7B,0x64,0x85,0x5F,0x11,
+	0xD0,0x90,0x7F,0xE3,0xB6,0xAE,0x1D,0x41,0xF4,0xC3,0x21,0x92,0x77,0x59,0xE5,0x95,
+	0xDD,0xD5,0x53,0xB3,0x13,0x67,0x67,0xAC,0x59,0xB3,0x85,0x2A,0x01,0xB7,0xEA,0x21,
+	0x8D,0x00,0xDB,0x14,0xE2,0x97,0x0B,0xB5,0x53,0x8A,0x9C,0x51,0x10,0x8A,0x11,0xE6,
+	0xDA,0x78,0x8F,0xCD,0xFF,0x9D,0x4B,0x15,0x4F,0xC7,0x5C,0x6F,0x87,0x3C,0xDE,0x31,
+	0x86,0xEA,0x21,0x6A,0xB0,0x67,0x19,0xF4,0xFD,0x45,0xF3,0x74,0x8D,0x4C,0x89,0x0E,
+	0x21,0x24,0x35,0xD0,0x48,0xE8,0xD0,0x18,0x49,0xFC,0x99,0x02,0xB4,0xFC,0x5E,0x81,
+	0x2E,0x53,0xD7,0xBF,0xD3,0x6A,0x3F,0x96,0x2D,0xB3,0x90,0x7B,0x50,0xAA,0xD6,0x86,
+	0x1D,0x9D,0x33,0xA6,0x23,0xD6,0xBA,0xDF,0xA7,0x1B,0x12,0x91,0x24,0x29,0x56,0xC0,
+	0xFD,0x4F,0x1B,0x7B,0xB3,0x81,0x9F,0x08,0x52,0xDC,0x48,0xDE,0x02,0x1E,0xEC,0xD6,
+	0x3B,0xCC,0xB9,0x19,0x6C,0xC8,0x21,0x26,0x25,0xD1,0x29,0x55,0x4D,0xE1,0xD7,0xA0,
+	0x6E,0x63,0x4A,0xB9,0xC7,0x71,0x2D,0x25,0xAF,0x8E,0x1E,0x20,0xC7,0xFA,0xA2,0xAE,
+	0xC5,0x7F,0x84,0x04,0x30,0x9D,0x01,0x46,0xB7,0xAD,0x28,0x49,0x7C,0x75,0x5D,0x2F,
+	0xAB,0x0F,0xB6,0x02,0x55,0x70,0x0F,0x8D,0xC0,0x84,0x52,0x87,0xDF,0xED,0xE4,0x85,
+	0xC6,0xED,0x56,0x6E,0x50,0xE3,0xB7,0x95,0xFB,0xAA,0x03,0x4E,0x60,0x8E,0x02,0x2C,
+	0x8E,0xEC,0x35,0x02,0x77,0xF9,0xCE,0xD1,0x27,0xA2,0x8A,0x00,0x6C,0x97,0xAA,0x7B,
+	0xAD,0x7E,0x2D,0xBF,0xCB,0x99,0x54,0xCB,0xAD,0x3C,0x76,0xCA,0x01,0xA0,0x7F,0xF8,
+	0xC1,0x93,0x91,0x1A,0xE7,0x5D,0xF5,0x3D,0x61,0x30,0x24,0x17,0x9B,0x5B,0xC2,0x59,
+	0x7B,0xA1,0x4A,0x68,0x47,0xC0,0xD0,0x2C,0xDB,0xC1,0x5F,0x61,0x71,0xBE,0xAF,0x6E,
+	0x8F,0xCB,0x5B,0xD0,0xAE,0xF1,0x75,0xE4,0x94,0x92,0xB0,0x9E,0x43,0xE8,0x1C,0x50,
+	0xEE,0x31,0xA8,0xA2,0x5E,0xC1,0x44,0xF6,0x85,0x02,0x29,0x07,0x2B,0x9A,0x59,0xEA,
+	0x94,0x55,0xC5,0xB6,0xB3,0x4F,0xF8,0xE3,0x97,0xF6,0x32,0x09,0x08,0x0D,0x84,0x1B,
+	0xA6,0x01,0x8E,0xB0,0x66,0xA7,0xB2,0xE8,0x66,0xFA,0x5C,0x05,0x14,0x59,0xB4,0x31,
+	0xC5,0xB7,0xF4,0xF4,0xFB,0xB1,0x93,0x3E,0xA7,0x81,0x56,0x95,0xD9,0x7D,0xDE,0x3E,
+	0x04,0x16,0xD2,0x74,0x90,0x77,0x4E,0x79,0x36,0x3D,0x11,0xBE,0x3D,0xBC,0x81,0x1E,
+	0xD6,0x39,0x05,0x87,0xB6,0x77,0xFD,0x12,0x27,0x47,0x25,0x24,0x78,0xB2,0xC7,0x88,
+	0xA9,0xB0,0xBE,0x80,0x52,0xCF,0x0E,0x04,0xB7,0x0B,0xC3,0x9F,0x9E,0x4F,0xAC,0x06,
+	0x16,0x63,0x04,0xD6,0x97,0xEE,0x26,0x94,0x94,0x54,0xB4,0x4B,0xE8,0x8D,0x6F,0x6C,
+	0x37,0x60,0x45,0x27,0x23,0xF2,0x0E,0x9E,0x82,0x4E,0x7A,0x2A,0x6F,0xE0,0xF9,0xDE,
+	0x0A,0xDA,0x44,0x39,0x2A,0x89,0x4A,0x14,0x53,0xFC,0xE4,0x3A,0xFD,0x27,0x5E,0x79,
+	0x04,0x25,0x87,0xC0,0xD5,0x0A,0xBE,0xAC,0x3D,0x98,0xAA,0x90,0x08,0x12,0x39,0xEB,
+	0x9B,0x88,0x89,0xE9,0xC2,0xB7,0xD4,0x84,0x05,0x73,0x6F,0xA1,0xC7,0x23,0x64,0x9E,
+	0xD8,0xBA,0xFB,0xBF,0xD7,0xDA,0x2F,0x94,0xEE,0x2C,0xF5,0x16,0x4C,0xF0,0x1A,0xB9,
+	0x96,0xAE,0xB5,0x52,0xA5,0xF3,0xBB,0x12,0x5E,0x43,0x03,0xC0,0xB8,0x70,0x54,0xDA,
+	0xAA,0x6D,0x4F,0xDF,0x8B,0x42,0x6D,0xC4,0x3B,0x6E,0x9A,0xFE,0x8A,0x6F,0xE2,0x9D,
+	0xB7,0x1D,0xFF,0xE5,0x10,0x96,0x0E,0xA9,0x68,0x6A,0xDA,0xAE,0x6C,0x95,0xF0,0xF2,
+	0xC3,0xC0,0x8B,0x60,0xE4,0xF1,0xCF,0x39,0x2B,0x44,0xE7,0x92,0x08,0x09,0x24,0xD7,
+	0x98,0x94,0x43,0x59,0x57,0x30,0x75,0xF5,0x10,0x38,0x51,0x7F,0x33,0x2B,0x01,0x97,
+	0x9A,0x87,0x68,0x57,0x5A,0xB8,0xF6,0x8A,0xC2,0xEB,0xE4,0x6D,0x24,0x61,0x24,0x6B,
+	0x12,0xEF,0xB6,0x82,0xC1,0x3F,0x5B,0x37,0xFC,0xBC,0x01,0x4D,0x8D,0x8A,0x25,0xA2,
+	0xBA,0x1B,0x3C,0xD4,0x10,0xEF,0x72,0x5B,0xDD,0xAD,0xAB,0x57,0x50,0x00,0x8D,0x3A,
+	0x34,0xCC,0xB7,0xF2,0xA6,0xA4,0x75,0x90,0x51,0x91,0xA9,0x28,0xE1,0x0B,0x8C,0xBC,
+	0x8E,0xA9,0x9C,0x06,0x6E,0xDF,0x56,0xD0,0x25,0x09,0x0C,0x00,0x59,0x89,0xDF,0x56,
+	0x41,0x09,0x96,0xC7,0xFA,0x1F,0x92,0x39,0x61,0x9C,0x62,0xF9,0x47,0x0E,0x89,0x9E,
+	0xF4,0x72,0xC6,0x8C,0x8B,0xD5,0x40,0x94,0x32,0x98,0xEC,0xE8,0x52,0xBB,0xE6,0x32,
+	0xA1,0x74,0xD0,0x2B,0xF1,0x39,0x37,0xF1,0x77,0x97,0x4D,0x1C,0x20,0xD2,0xA5,0x30,
+	0x7C,0xA9,0x0D,0xD4,0x64,0x47,0xEB,0xD2,0x5D,0x09,0x0D,0x12,0x5D,0xA1,0x37,0xED,
+	0xCC,0xB1,0x52,0x09,0x2E,0x64,0xED,0x90,0x4D,0xDA,0xCB,0xB7,0x7D,0xEC,0xEB,0xBC,
+	0x8F,0xDB,0x19,0xA8,0xF0,0x13,0xE2,0x3D,0xE9,0x21,0xA1,0xCD,0x3A,0x80,0x79,0x44,
+	0xC0,0x18,0x2F,0xC6,0x5C,0x57,0x6E,0x77,0x60,0x7B,0x89,0x71,0xFF,0x2C,0xEB,0x3D,
+	0x40,0x68,0x9F,0x2E,0xF6,0x70,0xA5,0xD9,0x83,0x05,0x6A,0xF3,0xE3,0x4B,0x80,0x04,
+	0xA4,0x88,0xCC,0x15,0x10,0x77,0xC9,0x6C,0xF4,0x7A,0x50,0x2C,0xB0,0x3A,0x6D,0x01,
+	0x04,0x65,0x67,0x24,0x99,0xA5,0x08,0x34,0x5F,0xC1,0x53,0xA2,0x4C,0x5D,0x79,0xF7,
+	0x62,0x1A,0xC2,0x04,0x28,0x0B,0x6D,0x67,0xD4,0xCF,0xC8,0xED,0xC8,0xCE,0x16,0x12,
+	0x8E,0x0C,0xBF,0xF0,0x06,0xEE,0xBE,0x38,0xED,0x96,0xF5,0xED,0xC9,0x5D,0xD1,0xBB,
+	0x8A,0xFC,0x2C,0x3C,0x5B,0xEA,0x80,0x5E,0xDC,0x11,0xA6,0x9A,0x24,0x16,0xB8,0x3E,
+	0xD2,0x50,0x37,0x15,0xC7,0x68,0xB6,0x53,0xA3,0x31,0xE7,0xD3,0x3A,0x37,0xE9,0x3B,
+	0x7E,0xAC,0x05,0x03,0x68,0x47,0x30,0x45,0x59,0x5A,0x59,0x2B,0xED,0xB1,0x66,0xE6,
+	0x34,0x82,0x7D,0xD2,0x2C,0x1C,0x26,0xFB,0x89,0x8B,0x8A,0x31,0x3F,0x5D,0x6B,0x25,
+	0xE4,0x21,0x5F,0xEB,0xC2,0x51,0x2A,0xD0,0xDF,0x41,0x2E,0x7E,0x42,0x16,0xAD,0x6A,
+	0x86,0xB6,0x3D,0xC0,0x0D,0xF0,0x83,0x5B,0x17,0xA8,0x00,0x24,0xD7,0xD9,0x04,0x04,
+	0xA3,0xAE,0x81,0xAA,0x20,0x30,0x2C,0xA3,0x84,0x2D,0x5A,0x1C,0x9D,0xA1,0x81,0x74,
+	0x5C,0x79,0x3E,0x0B,0xE1,0xA9,0x69,0xE3,0x45,0xF6,0xAE,0x32,0x49,0x18,0xB2,0xCB,
+	0x73,0x5E,0x27,0xA1,0x31,0x97,0x38,0x49,0xB1,0x7B,0x75,0x91,0xCC,0x92,0xD0,0xB5,
+	0xA1,0xBB,0xDB,0x7C,0x89,0x51,0x38,0xAA,0xCC,0xCF,0x7F,0xCA,0xE7,0xA0,0x98,0x7B,
+	0xA8,0xEE,0x58,0x36,0x23,0x2C,0x98,0xC4,0x42,0xAB,0x42,0x0F,0x09,0x42,0xDE,0xB2,
+	0xFB,0x28,0x1D,0xCA,0x85,0xB6,0x31,0xA2,0xD3,0x19,0x53,0x3A,0xA3,0x0B,0xB6,0x13,
+	0x64,0x46,0x14,0xD1,0x09,0xB5,0xFC,0x69,0x5B,0xD2,0x16,0x59,0xF0,0xCA,0x8F,0x33,
+	0x1B,0x2E,0xA5,0xB6,0x2A,0x76,0xAD,0xB5,0x31,0x53,0xAD,0x12,0xF5,0xFE,0x5E,0x5C,
+	0x58,0x93,0xFE,0x77,0x3B,0x92,0x25,0xF2,0x15,0x8D,0xE5,0xAF,0x21,0xAA,0x56,0x2E,
+	0xF5,0x1A,0xF9,0x0D,0x49,0x4E,0x24,0xCF,0xD8,0x21,0xC6,0x30,0x96,0xBF,0xD5,0x0B,
+	0x2D,0xCE,0xC2,0x76,0x35,0xBD,0x5D,0xF2,0x88,0x12,0x8F,0x2A,0xB6,0xDB,0xB1,0x8C,
+	0x3C,0x07,0x95,0x9C,0x6D,0xA6,0x0E,0xF7,0x29,0x22,0x4A,0x26,0xF7,0x50,0x6A,0x2B,
+	0x27,0x98,0x49,0xB1,0xED,0x22,0xF3,0x61,0xCE,0x10,0x1C,0x64,0x61,0x1B,0xDE,0x54,
+	0xF7,0x20,0xAB,0x87,0x01,0x17,0xA4,0x52,0xC7,0xF6,0x8F,0x67,0xFD,0x12,0x51,0x4E,
+	0x9F,0x6E,0xCD,0x7B,0xB9,0xCB,0x55,0xDC,0xFD,0xAB,0x59,0x96,0xCC,0xB8,0x98,0x3C,
+	0x48,0xB0,0x47,0x2C,0xF1,0xC4,0xCF,0xC4,0xDC,0xED,0x4E,0x0C,0xF4,0x63,0xA9,0x7F,
+	0x0B,0x83,0x39,0x50,0xD7,0xAD,0xB6,0x34,0x2F,0x31,0x57,0x93,0xCD,0xCE,0x68,0x4D,
+	0x9B,0x92,0x12,0x4E,0xF9,0x76,0xB1,0xE7,0x32,0x95,0x66,0x1F,0xAD,0x3D,0x24,0x10,
+	0x45,0xF7,0x3D,0xFC,0x01,0x66,0x71,0x35,0x43,0xDF,0x60,0xDE,0x57,0xBD,0x77,0x1E,
+	0xD5,0x81,0x1C,0x6A,0xDE,0xCE,0x27,0xAC,0xCA,0x7F,0xD6,0x70,0x70,0xA5,0x83,0xBD,
+	0xCF,0x24,0x72,0x99,0xE2,0x78,0x32,0x97,0x1A,0xCA,0x00,0xE3,0x45,0x28,0xC1,0x76,
+	0xC9,0x65,0xE7,0x5E,0x20,0xC3,0x0B,0xE9,0x88,0x87,0x93,0x90,0x58,0x97,0x2F,0x00,
+	0x7D,0x7C,0x42,0x45,0xE2,0x25,0xFA,0xAF,0x22,0x34,0x8B,0xBF,0x4E,0x68,0x6C,0x47,
+	0xC0,0x20,0x00,0x4A,0x84,0xF9,0x6A,0xC0,0x75,0xF9,0x78,0x7A,0x41,0xAC,0x7A,0xFF,
+	0xF6,0x03,0x4A,0x23,0xA5,0x02,0x9C,0x8F,0x7A,0x31,0xE5,0xC9,0x49,0xB3,0x62,0xCB,
+	0xBA,0xC4,0x8B,0x57,0x0D,0x83,0xB0,0xA1,0x70,0x5E,0x84,0x44,0x7D,0x0C,0xD6,0x9D,
+	0x12,0xEF,0x94,0xFF,0x08,0xED,0xFC,0xEF,0xD9,0x4B,0x19,0x4B,0x34,0xC8,0x71,0x34,
+	0x67,0x73,0xA0,0x96,0xCC,0x8B,0x5D,0x1B,0x2A,0xA6,0x96,0x55,0xAE,0x28,0x18,0x3C,
+	0x8A,0xCD,0x16,0x63,0xD7,0x4C,0x3E,0xF0,0xEC,0xAE,0x3A,0xFE,0x2C,0x34,0x5E,0xAD,
+	0x3F,0xDE,0x18,0xAE,0xE2,0xEB,0x2C,0x6E,0xE4,0xCC,0x53,0xD6,0x50,0xD7,0xFE,0xCD,
+	0x62,0x72,0x4D,0x9E,0x47,0x3B,0x29,0xF2,0x88,0x0E,0x1C,0x5D,0xD5,0xB6,0x9C,0x0F,
+	0x43,0x27,0x8F,0x46,0x21,0x76,0xAC,0x1E,0x2A,0xE0,0xA5,0x71,0x24,0x91,0x2F,0xD9,
+	0xD7,0x9B,0x37,0xB3,0x4F,0x92,0xC1,0x66,0x54,0x54,0x3F,0x38,0xD7,0xEE,0x75,0x54,
+	0x12,0x9B,0x62,0x0D,0xFB,0x7D,0xD3,0x02,0x42,0x47,0x81,0x46,0x91,0x4D,0x8A,0xE5,
+	0xF7,0xD0,0xFB,0xCC,0x0D,0x9D,0x2D,0xEF,0x6D,0x24,0x5F,0xC5,0x75,0x6C,0xB6,0xD4,
+	0xF2,0xE1,0x90,0xBB,0xAD,0x90,0xC2,0x63,0xE7,0x93,0x21,0x76,0xFB,0xD5,0x9D,0x78,
+	0x2F,0xD5,0xC3,0x08,0x9E,0xAE,0xB3,0xE7,0x21,0xCE,0x57,0x6F,0x12,0x57,0x01,0x44,
+	0xB1,0x44,0x89,0x88,0x89,0x15,0xDB,0x66,0xD7,0x7F,0x8F,0x26,0x4D,0x7C,0x95,0xC3,
+	0xEE,0xAE,0x79,0xED,0xD9,0xBE,0x82,0xC8,0xFA,0xEE,0x8A,0x9D,0x57,0xFC,0x11,0xCA,
+	0xF0,0x94,0x95,0x76,0xDF,0x52,0x86,0x05,0xF4,0x6C,0x0E,0x2C,0xA0,0xF2,0xC6,0x72,
+	0x39,0x2F,0xA9,0xF1,0x69,0x8D,0x2D,0xC9,0xC3,0xE2,0xBC,0x2B,0x36,0xFB,0xCB,0xD6,
+	0xED,0x8D,0x2D,0xD6,0xFE,0x26,0x98,0xC9,0x87,0x95,0x63,0xDF,0xBE,0xD4,0x8B,0x4A,
+	0x1F,0x9A,0x51,0x92,0x51,0x57,0xDB,0xFD,0x17,0x73,0xE5,0x6D,0x21,0x62,0x01,0xA2,
+	0x94,0xEE,0xFF,0xCE,0x15,0xD8,0x68,0x62,0x31,0x56,0xD3,0x74,0x34,0xF1,0xC7,0x75,
+	0x23,0xAC,0xE7,0x91,0x50,0x15,0x15,0x4E,0xE8,0xA8,0xD8,0xFE,0xE5,0x2A,0xCF,0x84,
+	0x7E,0xB0,0x48,0x9F,0xF4,0xC0,0x86,0xA2,0x9D,0xD6,0x1F,0x90,0xCC,0x55,0x24,0x1E,
+	0xDE,0x29,0x1E,0x91,0xCD,0xBF,0x62,0x00,0x86,0xF6,0xDB,0xB6,0x58,0x91,0x26,0x8C,
+	0xD4,0xAA,0xF5,0xCE,0xC0,0x8B,0xED,0x70,0xF9,0x5F,0x47,0x7B,0x04,0xDE,0x8D,0x2E,
+	0x3E,0x29,0x9D,0x55,0x8A,0x2A,0x3B,0x3E,0x99,0x51,0xE9,0xF2,0xC1,0xC3,0x77,0x55,
+	0x36,0xC2,0x8C,0xD6,0x1F,0x58,0xB3,0x64,0xC9,0x83,0x53,0x76,0x20,0xC7,0x5D,0x3B,
+	0xFA,0xE9,0x3D,0x8A,0xBA,0xDC,0x04,0x15,0x7C,0x21,0x6E,0x43,0x6B,0xD1,0xB9,0xAE,
+	0xBF,0x6C,0x8B,0xCC,0xBF,0x83,0x2D,0x5F,0xD7,0x04,0x01,0x92,0x37,0xA1,0x09,0xF4,
+	0xAD,0x11,0x8B,0x26,0x08,0x8D,0x8D,0x7F,0x13,0xA6,0x8E,0xE7,0xD4,0x36,0xB0,0x6A,
+	0x71,0x92,0x18,0x6B,0x87,0x85,0x02,0x34,0x9B,0x63,0xF9,0xA2,0x65,0x15,0x4E,0xE6,
+	0x8F,0xBB,0x54,0x22,0x91,0x81,0x0F,0x5C,0xA7,0xCE,0x02,0x26,0xA0,0x8D,0x11,0x1F,
+	0x83,0x87,0xB3,0xEF,0x6A,0x03,0x49,0x02,0x13,0x32,0x25,0x55,0x43,0x8C,0xED,0x27,
+	0x8D,0x13,0xD1,0x92,0x4F,0xBD,0x04,0xA2,0x0E,0x07,0x32,0x58,0x6F,0x46,0xC2,0xFA,
+	0x37,0x1D,0xF1,0xC2,0x7C,0xE7,0x63,0xBC,0x92,0xB0,0x9A,0xCC,0x18,0x6E,0x7C,0xD9,
+	0x36,0x2F,0x8B,0xF1,0xEB,0x8B,0x4E,0xDA,0x9E,0xC1,0x8D,0xE2,0x94,0xF0,0x7C,0xA4,
+	0x1D,0x70,0xDB,0x87,0x2A,0xFC,0x0D,0xDE,0xC2,0xFF,0x00,0x3F,0x19,0x80,0xDA,0xFB,
+	0x66,0xF0,0xB5,0xFD,0x22,0x76,0xE5,0xBD,0x36,0x15,0xBD,0xC7,0xCD,0x90,0xB7,0xC5,
+	0x1B,0x01,0xCA,0xC8,0x9B,0x8E,0x83,0x4E,0xE6,0xA5,0x25,0xCE,0x56,0x18,0x3E,0xB1,
+	0x4A,0xC2,0xC6,0x35,0xA1,0x4A,0x91,0x53,0x1E,0x92,0x25,0x6B,0x0E,0xD0,0x97,0x9C,
+	0xCF,0xAA,0xA4,0x3C,0xAE,0xE8,0x74,0xB0,0xC8,0x43,0xFE,0xFA,0x04,0x11,0xA5,0xBB,
+	0x23,0x15,0x4F,0x90,0x40,0x90,0xB6,0x67,0x26,0x5B,0x6A,0x4A,0x3A,0x2E,0xA9,0x8C,
+	0x82,0x51,0x20,0x86,0x00,0x2B,0x61,0x38,0x53,0x35,0x0E,0xFC,0x59,0x3C,0xE1,0xA4,
+	0x15,0xB6,0x6A,0xFE,0x2F,0x80,0xE6,0x6D,0xBC,0xD4,0xAB,0x34,0xAD,0x2B,0x35,0x99,
+	0x62,0x66,0x35,0x5A,0xFF,0xE8,0x40,0x34,0xBE,0xDE,0x8A,0xB2,0x78,0x24,0x90,0x46,
+	0x7F,0x27,0x00,0xE7,0x31,0x30,0x1C,0x5E,0x16,0x1E,0x78,0xE5,0x9F,0x80,0x66,0x97,
+	0xEE,0xF3,0x49,0x24,0xD8,0x22,0x2C,0x8B,0x68,0xA5,0x38,0x37,0xA4,0x46,0x59,0x3A,
+	0x51,0x7B,0xB4,0x77,0x91,0x72,0xDA,0x83,0x95,0xF5,0xC9,0xEB,0x40,0x70,0xA1,0xE6,
+	0x8B,0x92,0xE7,0xEF,0x5E,0x80,0xB4,0x39,0xCC,0x47,0x28,0x98,0x12,0x81,0xEE,0x8E,
+	0x8F,0xF6,0x76,0x5D,0xB7,0x25,0x4A,0x9C,0xE1,0x4B,0xD1,0xAA,0x0C,0xF0,0xC8,0x2B,
+	0xE3,0x24,0xAB,0x58,0x7B,0x95,0x71,0x57,0x26,0xC4,0x1C,0x12,0x27,0x75,0x59,0x41,
+	0xC5,0xF1,0x10,0xDE,0xEC,0x4F,0xE1,0x17,0xCA,0x38,0xB5,0x7D,0x17,0xC4,0x7C,0x0B,
+	0xDF,0xEB,0x9F,0xF8,0xDB,0x34,0xE4,0xC6,0x6F,0x70,0x68,0xEF,0xA7,0x4B,0x11,0x33,
+	0xEC,0xF8,0x01,0x91,0x35,0x0A,0x24,0x6F,0xB2,0x5A,0xED,0x67,0x70,0x4B,0x0F,0x11,
+	0xE9,0x5E,0x66,0x47,0x51,0x2A,0xF6,0xED,0xB5,0xA6,0x7A,0x5E,0x24,0xB3,0xC9,0x18,
+	0x46,0x1C,0x15,0x6D,0x2C,0x6B,0xE4,0x01,0x21,0x8D,0x36,0xDB,0x0A,0xDB,0x59,0xFB,
+	0x5F,0x14,0x8B,0x3A,0x3E,0x59,0x8E,0x1D,0x9F,0x3C,0xAA,0x67,0x49,0x44,0xD7,0xA4,
+	0x32,0x9E,0xE6,0x3D,0xCA,0x5B,0x59,0xEF,0xBB,0x0B,0xB5,0x14,0x97,0x9A,0x49,0x84,
+	0x3D,0xC5,0xE0,0x3D,0xFB,0xEA,0xD2,0x03,0xC4,0xE7,0xC3,0x26,0x28,0xC5,0xCC,0x5E,
+	0xAA,0x00,0xB8,0x66,0x38,0xF3,0x23,0xC4,0x00,0xD8,0x39,0x90,0xBF,0x16,0x72,0x85,
+	0xFA,0xA9,0xEF,0x5C,0xD5,0x02,0x93,0x89,0xC4,0x3B,0x28,0x5A,0x8E,0xFC,0x36,0x32,
+	0x46,0x2A,0x26,0x74,0x3D,0xD3,0x3D,0x42,0x3A,0x71,0x5D,0x2F,0x63,0x83,0xB6,0x57,
+	0x4A,0x24,0xB6,0x0C,0x2F,0xFA,0xAD,0x25,0xFF,0x43,0xE4,0x68,0xDD,0x60,0xDF,0x1C,
+	0x60,0xB1,0xC2,0x00,0xE4,0xD8,0xDC,0x7E,0xDC,0x0E,0x85,0xDA,0x1E,0x94,0xE6,0x8D,
+	0x9A,0x38,0x35,0xE5,0x3C,0x5C,0x81,0x68,0x66,0x5E,0x6C,0x71,0x36,0xFE,0xD8,0x1B,
+	0x38,0x96,0x60,0x05,0x5D,0x35,0x27,0x02,0x17,0x03,0x34,0x34,0x9D,0x85,0xB9,0xA0,
+	0x11,0x9F,0x49,0xF3,0x7A,0xB5,0xF1,0x78,0xAD,0x3A,0xE3,0x58,0x2C,0x08,0x15,0xBD,
+	0xCE,0xB9,0x54,0xFA,0x84,0xB2,0x25,0xD0,0x6F,0x5F,0x62,0xF7,0xE1,0xD6,0x2A,0x15,
+	0x14,0x3D,0xFC,0xAF,0xD5,0xFD,0x9F,0x80,0xB8,0xF6,0x37,0x63,0x52,0xB1,0x35,0xAF,
+	0x00,0x2F,0xE8,0xB2,0x5A,0xAF,0x03,0x4F,0xE4,0x14,0x28,0x94,0xA1,0xE8,0x63,0x7B,
+	0xA5,0x80,0x9E,0x37,0x10,0x94,0x1C,0x1F,0x77,0x76,0x1C,0x09,0x13,0x87,0x43,0x2F,
+	0x55,0xDD,0x45,0x24,0x0C,0x58,0x2E,0x38,0x34,0x2F,0x97,0x08,0x17,0xB4,0x79,0xBD,
+	0x88,0x2A,0x07,0x84,0xEB,0x6E,0x18,0x7A,0x54,0xA3,0xBF,0x65,0x8E,0x3E,0xBE,0xEC,
+	0x93,0xB7,0xAF,0xCF,0xA8,0x93,0x82,0x30,0x2C,0x62,0xC0,0x68,0xA5,0x8F,0x36,0xA0,
+	0xB6,0x49,0x4D,0x52,0x7D,0x6E,0xC3,0x60,0x88,0x12,0x9B,0x94,0x46,0x7F,0xFA,0x00,
+	0xE4,0x45,0x00,0xB8,0x14,0x3C,0x7F,0x54,0xA8,0x71,0x9E,0x01,0xE4,0x67,0x00,0x98,
+	0xBC,0x86,0xCA,0x58,0x82,0xD5,0xBB,0x35,0x51,0x35,0x4D,0x3B,0xB2,0x43,0xFD,0xBA,
+	0x7F,0xDA,0x68,0x2C,0x0D,0xDB,0xC9,0xC2,0x79,0x8F,0x43,0xED,0x7B,0x5A,0x45,0xA9,
+	0x89,0xE3,0xA7,0x5F,0x62,0xD9,0x29,0x48,0x6F,0x97,0x6A,0x2B,0xB6,0x96,0x0E,0x2F,
+	0x8E,0xB5,0x25,0xBB,0x63,0x1E,0xB1,0x2F,0x6D,0xF5,0x7A,0xE9,0x1A,0x58,0xF7,0xA9,
+	0xC9,0x98,0x35,0xCB,0xD9,0x98,0x20,0xDB,0x35,0x67,0xD3,0x55,0xF3,0xA9,0x32,0x31,
+	0xBE,0x69,0x9A,0x4E,0x43,0xD6,0x9E,0x95,0x0F,0xB8,0x66,0x70,0x83,0xD6,0xC7,0x31,
+	0x86,0x96,0x0D,0xCD,0x09,0x07,0x48,0xAC,0x02,0x6F,0xE1,0x00,0x57,0xBF,0xCD,0x64,
+	0x71,0x71,0xED,0x3F,0xDC,0x7F,0x0E,0x80,0x08,0x68,0xE3,0xE3,0xAC,0xEC,0x13,0x90,
+	0x9C,0xEC,0x8D,0x87,0x92,0x37,0xAF,0xC2,0xB6,0xDF,0x45,0xBE,0xA1,0x99,0x1F,0x9F,
+	0x09,0xF4,0xA9,0x72,0xEB,0x87,0x77,0x7C,0x77,0x0F,0x7A,0xE7,0xFD,0x7C,0xC5,0xEB,
+	0x83,0xCC,0x1C,0x56,0xA2,0xD3,0x67,0x19,0x80,0xD8,0x22,0xE8,0xC4,0x8A,0x31,0x2C,
+	0x86,0x15,0xCD,0x9C,0x58,0xED,0x02,0xD8,0x06,0x9B,0x0A,0xEB,0x67,0x66,0x5C,0x28,
+	0x4F,0xFE,0xC4,0x68,0xCA,0xB5,0x6B,0xDB,0x2D,0x91,0x72,0x6F,0x86,0x66,0x12,0x2F,
+	0xA5,0xF0,0x16,0x47,0x84,0x0C,0xCC,0x42,0xFA,0xF7,0x9A,0x3B,0x43,0xCC,0x73,0x41,
+	0x92,0xB4,0xB5,0x6E,0x18,0xDE,0x6F,0x4D,0x37,0x8C,0xCC,0x4C,0x02,0x8B,0x08,0xFC,
+	0x2A,0x6C,0x9F,0x2C,0x8D,0x3C,0xD4,0x29,0x31,0x53,0xE0,0x24,0x8D,0xD6,0xAC,0x8C,
+	0xA6,0x6E,0xFE,0xD1,0xFC,0xE4,0x9B,0x7D,0xC6,0x6D,0xD1,0x63,0x61,0xB7,0x30,0xCC,
+	0xCF,0x33,0xA3,0x6A,0x51,0x6A,0x4A,0x1C,0x98,0x42,0xF1,0x73,0x6D,0xAB,0x4C,0x7C,
+	0x14,0x62,0x02,0xBC,0x90,0xF8,0x4B,0x9E,0x61,0x64,0x38,0x88,0x2D,0x61,0x76,0x0E,
+	0xF1,0x9E,0x6A,0x8F,0x37,0xC2,0x5C,0xD4,0xAE,0x54,0x67,0xAD,0x4F,0xF4,0xF8,0x59,
+	0x26,0xE6,0x58,0xE6,0xEE,0x2D,0x3A,0x83,0x18,0x6D,0xE0,0x0D,0x72,0x42,0x4B,0x6A,
+	0x59,0xDA,0x25,0xB4,0x8A,0xA9,0xA4,0xA3,0x87,0xDF,0x50,0x8F,0xEF,0x35,0x18,0xC3,
+	0x12,0xCA,0xFD,0xBE,0x82,0x78,0xA9,0xF6,0x8B,0xA1,0x31,0xF7,0xA9,0x3F,0x26,0x59,
+	0x4F,0xAF,0x91,0xFB,0x11,0x81,0xDF,0x47,0x3D,0xC8,0xA5,0x12,0x19,0x60,0xEF,0xAA,
+	0xD5,0xFB,0x93,0xA8,0x4B,0x95,0xD6,0x6A,0xED,0x17,0x57,0x26,0xE2,0x27,0x55,0xAA,
+	0x33,0x2A,0x92,0x81,0xA0,0x14,0xAB,0x12,0x83,0xA4,0xA1,0xE2,0x85,0x15,0x74,0x38,
+	0x9D,0x95,0xE6,0x18,0xD5,0xCD,0x5E,0xC0,0xB9,0x66,0x3C,0x62,0x3A,0xF6,0xCC,0xBB,
+	0xB1,0x88,0x04,0x41,0xAE,0x18,0xCE,0x80,0x61,0xF9,0x5A,0x89,0x8F,0x24,0x0E,0xFC,
+	0x0A,0xDC,0xC2,0x57,0xEB,0x17,0xAE,0x2F,0x51,0x17,0x1F,0xE0,0x95,0xFE,0x08,0x5C,
+	0x05,0xE8,0x0A,0x7D,0x15,0x7A,0xED,0x2E,0xD2,0x3C,0x0D,0x9C,0x4C,0xF3,0x79,0x91,
+	0x86,0x84,0xD3,0x58,0x86,0x9E,0x05,0x16,0x9B,0xA8,0x1B,0x0B,0x2A,0x2F,0x77,0xFC,
+	0xF2,0x0F,0xA0,0xBF,0x40,0xBF,0x15,0xCE,0x2D,0x70,0xD7,0xA4,0xB2,0x1C,0x76,0x08,
+	0x7C,0xF6,0x09,0x3B,0xFF,0x3D,0x2F,0x7B,0x67,0x63,0xCC,0x31,0x27,0xBA,0x82,0xBF,
+	0x59,0xA1,0x57,0x7C,0xBD,0x8F,0x98,0xC5,0x55,0xCA,0xC2,0x0A,0x60,0x7A,0x1D,0x5A,
+	0xC7,0xA5,0xE0,0xFE,0x08,0xB8,0xED,0xB0,0xAA,0xB8,0x2E,0xB1,0x66,0x3D,0xE4,0x32,
+	0xCA,0xF8,0x80,0x21,0xB6,0x2F,0x80,0x55,0x61,0x85,0xA9,0x31,0x69,0x69,0x36,0xA8,
+	0x16,0xE3,0xC5,0xB2,0xA3,0xBB,0x9E,0x16,0x3B,0x3C,0xDE,0xB0,0xE3,0x3D,0x35,0x95,
+	0x70,0x61,0x55,0x2D,0x97,0x78,0xB3,0xA0,0x59,0x40,0x9A,0x7F,0x0A,0xED,0xB8,0x4F,
+	0x2D,0xFC,0x77,0xA2,0x9E,0x58,0x53,0x7C,0xA0,0x9A,0x8F,0xAF,0x3E,0x72,0x1E,0x59,
+	0x31,0xC1,0xF5,0x5D,0x70,0xD8,0xDF,0x7D,0xB2,0x67,0xB0,0x3E,0x5A,0x9B,0xE1,0x67,
+	0x0B,0xC8,0x32,0xD8,0xDF,0xE2,0x02,0x11,0x65,0x57,0xB9,0x4A,0xE4,0x64,0x69,0x36,
+	0x95,0xA6,0xE1,0x0B,0x3D,0x14,0x2C,0x4D,0x88,0x3A,0x6A,0x7E,0x01,0x8C,0x08,0x62,
+	0x0F,0x84,0x0B,0x63,0xC0,0x41,0x0B,0x65,0x17,0x22,0xDE,0x2F,0xFD,0xD6,0xD2,0xFE,
+	0xBA,0x4E,0x2F,0xAC,0x88,0x2B,0x2E,0x98,0x8E,0xD2,0x71,0x3D,0xB2,0x3C,0x19,0x68,
+	0x98,0x54,0x6D,0xD9,0x4C,0xD3,0x0D,0x77,0xE4,0x2B,0xBA,0x4E,0xC0,0xB6,0xD5,0x6D,
+	0x37,0x65,0x7F,0x58,0xF6,0x29,0xDD,0x99,0x35,0x93,0x15,0xBA,0xD1,0x0C,0x31,0x6F,
+	0xEC,0x2B,0x3B,0xAD,0xA9,0xAD,0xD8,0x7F,0x7D,0x91,0x96,0x2A,0x97,0x43,0xF3,0xC4,
+	0x74,0xF6,0x5C,0x8E,0x9A,0xC0,0xA4,0x2A,0x20,0xD0,0xF0,0x6C,0x0E,0x25,0xD9,0x41,
+	0xE2,0x6F,0xA8,0x54,0x65,0xE6,0xF5,0x0E,0xCD,0x8E,0x28,0xB4,0x4B,0x41,0xF5,0x29,
+	0x9C,0xB5,0x84,0xD5,0x2E,0x33,0x82,0xD3,0x71,0x9F,0x94,0x21,0x65,0x06,0x68,0x68,
+	0xDC,0xC4,0x0F,0xA7,0x68,0xAC,0x8E,0x3C,0x7C,0xA0,0x0D,0x34,0xB7,0x8B,0xD3,0x5C,
+	0x05,0x5D,0xC9,0xB9,0x53,0xF8,0x01,0xED,0x9B,0xDC,0x61,0x72,0x38,0xE8,0x4C,0x9A,
+	0x5A,0x9E,0xF9,0x2B,0x86,0x4B,0xB0,0xE4,0x32,0x16,0xC1,0x28,0xD3,0x7C,0x66,0x4D,
+	0x7C,0x49,0x7A,0x39,0x08,0xF3,0x97,0x30,0x38,0xDC,0x5F,0x86,0x18,0xBB,0xB7,0x1E,
+	0xFF,0xB5,0x88,0xF1,0xFF,0x06,0x25,0x8F,0x7C,0xE3,0x27,0xE9,0xF1,0x7C,0x01,0x75,
+	0xCF,0x3B,0x99,0xE3,0x20,0x95,0x81,0xEA,0x9D,0x5E,0xBF,0x55,0x5B,0x5C,0xEE,0x13,
+	0x26,0x84,0x45,0xF1,0x85,0x49,0x3F,0x33,0xC5,0xA0,0x6B,0x03,0x0D,0x26,0xE8,0xCB,
+	0x49,0xF5,0x48,0xF1,0x0A,0x53,0x4C,0x33,0x0D,0x2A,0xAA,0x02,0xB0,0x08,0x38,0xC3,
+	0x6D,0xD8,0x7E,0x8D,0xC1,0xCC,0xF5,0x3B,0xB6,0x0B,0x7D,0x82,0xF0,0x43,0x17,0xDF,
+	0x68,0x4E,0xED,0x10,0xC4,0x1D,0x64,0x05,0x40,0x5F,0xC9,0x26,0xDF,0xE9,0xAB,0x49,
+	0x2E,0x74,0x8E,0x8D,0xF7,0x18,0xD7,0x26,0xEA,0x38,0x28,0x43,0x14,0x35,0x9F,0xCF,
+	0x72,0x59,0x27,0x4F,0x53,0x5D,0x9A,0xB7,0x96,0x8F,0x40,0xD6,0xC4,0x0C,0xB5,0x87,
+	0x42,0xEA,0xD1,0x18,0xEB,0x2E,0xD8,0x39,0xEF,0xD4,0xF0,0x3D,0x74,0x83,0x4B,0x44,
+	0x5E,0xEE,0x2A,0xBC,0x9C,0x73,0x07,0xF2,0xC7,0xEC,0xA5,0xAA,0xBB,0x18,0x92,0xCF,
+	0x0E,0xF4,0xA9,0xBC,0xC6,0xCC,0x47,0x53,0x09,0x35,0x03,0xC9,0xDE,0x82,0x5C,0xAE,
+	0x0C,0x5F,0x06,0x08,0x0E,0x6B,0xEE,0xAD,0x94,0xDD,0x65,0x94,0x46,0x56,0xD2,0xEB,
+	0x39,0xE9,0x71,0x12,0x61,0xE2,0x50,0x64,0x81,0xAF,0xC8,0x16,0x65,0x55,0xF4,0x2C,
+	0x94,0x9F,0x34,0xCA,0xBD,0x51,0x3C,0x68,0x9B,0x08,0x55,0x77,0x8D,0xEB,0x4E,0x31,
+	0x81,0x2D,0xAC,0xB9,0x20,0xF7,0x87,0x2E,0x37,0x1C,0xCD,0x57,0x50,0xEB,0x33,0x60,
+	0xE2,0x03,0x83,0x52,0x47,0xAD,0x0E,0x3F,0xEA,0x3B,0x58,0x11,0x80,0xF4,0x4D,0xCD,
+	0xA6,0x3E,0x8A,0xF1,0x31,0xDC,0x07,0x97,0x74,0x6C,0xBF,0x8F,0x3A,0x74,0xA3,0xB5,
+	0xEE,0x1D,0x0E,0xAC,0x4F,0xEB,0x09,0xB3,0x38,0x8B,0xBA,0xE7,0x54,0x0E,0x6F,0xD4,
+	0xE7,0x9D,0xF3,0x1D,0xB7,0xE1,0x7B,0x46,0x03,0x19,0x16,0x2C,0x4C,0x0D,0x5B,0x98,
+	0x27,0x6D,0x5D,0xA0,0x72,0x07,0x8F,0x39,0xCB,0x48,0x23,0xA2,0x60,0xD0,0x2B,0xFF,
+	0x7A,0x0F,0x0A,0xBE,0xE7,0xCB,0xAF,0xCF,0xDB,0x99,0xB8,0x23,0x07,0xB8,0xC8,0xE8,
+	0xC1,0x08,0xEF,0xD5,0xE8,0xA7,0xC1,0xD0,0x2C,0x48,0x5C,0xEC,0xA7,0x21,0x58,0x01,
+	0x67,0x48,0xE3,0xF0,0xCE,0x46,0xAF,0x01,0x3F,0x7A,0x81,0xD1,0x38,0x10,0xA3,0xDA,
+	0xEC,0xCE,0x52,0xFD,0x54,0x75,0x67,0x83,0x5A,0x9B,0xC7,0x4F,0x8B,0x75,0x7B,0x97,
+	0x47,0x71,0xE3,0x16,0xBC,0x49,0xF7,0x9F,0x4C,0xF2,0xAF,0xE2,0xA6,0x8D,0xBF,0x18,
+	0xA1,0x2D,0x15,0x07,0xB1,0xD6,0xCF,0x79,0xF1,0x16,0x97,0x1E,0xE0,0x6B,0x49,0xA3,
+	0x98,0x86,0x30,0x23,0x0B,0xD0,0xAB,0xD0,0x0E,0x69,0xC1,0xCA,0x1C,0x22,0xA1,0x27,
+	0xB3,0xC3,0x9A,0xC9,0xD5,0xB9,0x27,0x62,0xBD,0xC9,0xB1,0x55,0x66,0xA2,0x3C,0xC1,
+	0x49,0x65,0x68,0x91,0x87,0xBE,0x77,0x83,0x3B,0x40,0x24,0x6F,0x6F,0xF3,0x29,0x79,
+	0xEA,0xCE,0x29,0xB7,0x0C,0x51,0xB8,0xB4,0xFF,0x12,0xB9,0x8C,0x38,0x7B,0x07,0xEB,
+	0x6F,0x96,0xBB,0xC9,0x86,0x25,0x6B,0x07,0x06,0x73,0xDA,0xE8,0x29,0xCD,0xFE,0xD8,
+	0xDB,0x2D,0xC9,0x6C,0xAE,0x78,0x35,0x30,0x32,0xC6,0x11,0x16,0x19,0xD1,0xF4,0x69,
+	0x7E,0xFC,0x8C,0xA7,0x26,0x3A,0x2D,0x46,0xD6,0xB8,0x34,0xC4,0x4F,0x68,0x5A,0x8B,
+	0xAB,0x89,0x3A,0x7A,0x8C,0xED,0xA8,0x54,0x64,0xE6,0x43,0xD0,0xA6,0x2C,0x55,0x82,
+	0xC8,0xB4,0x78,0xC1,0x65,0x1B,0x8B,0xB4,0x74,0xF6,0x0A,0xCD,0xE0,0x04,0x0B,0x8E,
+	0xBB,0xB7,0x6A,0x6A,0x10,0x81,0xCC,0xA1,0x50,0x94,0xFE,0xE7,0xF6,0x33,0xC2,0x06,
+	0x72,0x2C,0x31,0x6A,0x30,0xD6,0x6D,0x15,0x78,0xCD,0xBB,0xAD,0x8E,0x6D,0x18,0xAB,
+	0xCF,0x33,0x81,0xF6,0xF3,0xB5,0x92,0x5D,0xF9,0x95,0xEF,0x34,0xA3,0x09,0xD1,0x3A,
+	0x76,0xF6,0x6E,0x41,0x52,0xAB,0x69,0x03,0x84,0xE7,0x6D,0xE5,0x62,0xC9,0xB7,0xD1,
+	0xB6,0x3F,0xA3,0x82,0x8E,0x37,0x34,0x2C,0xC2,0x6F,0xAD,0x49,0x5C,0xCB,0x3C,0x5B,
+	0x38,0x30,0x6A,0xBB,0xB6,0x6E,0x12,0x7F,0x13,0x63,0xA0,0x0A,0x1D,0xE3,0xC6,0xD4,
+	0x77,0x92,0x75,0x28,0x2E,0x73,0xB7,0x02,0x09,0x09,0xFB,0x31,0x10,0x32,0x4E,0x28,
+	0xDD,0x9B,0x5B,0x22,0x37,0x75,0xB5,0x96,0x66,0x5C,0x33,0xA8,0xF9,0x26,0x2B,0x86,
+	0x8A,0x79,0x3F,0x56,0x1C,0x5E,0x38,0x5E,0x7E,0xEF,0x48,0xDC,0x0D,0x0A,0x88,0x6C,
+	0x3F,0xCB,0x91,0x6A,0xE1,0x4F,0xFC,0x6C,0x2F,0x87,0x89,0x7A,0x9C,0xFE,0x1A,0x88,
+	0xBC,0x12,0x04,0x04,0x35,0x55,0x29,0x99,0xE8,0x0B,0x65,0xD7,0xAE,0x27,0x7C,0x8E,
+	0x19,0x7F,0xD0,0x82,0x73,0x68,0xCF,0x68,0xF3,0x8B,0xCB,0x52,0xEC,0xFB,0xC4,0xDC,
+	0x26,0xC6,0xCA,0x7D,0x10,0x46,0x53,0x0F,0xAA,0x92,0xDA,0x72,0x5D,0xBB,0x15,0x5E,
+	0xF5,0x56,0x7B,0xB8,0xA1,0x34,0xD9,0x65,0xA1,0xC5,0xB0,0x3D,0xD8,0xDA,0x9F,0x81,
+	0xBF,0x33,0xAB,0x7D,0x16,0x95,0xC3,0xC4,0x70,0x7F,0x82,0xDC,0x6C,0x78,0x08,0xBE,
+	0x49,0x81,0xAB,0x81,0x78,0x60,0xDD,0xA3,0x75,0x1C,0xDB,0x97,0xBE,0x4B,0xCB,0x54,
+	0xFD,0xF1,0xB5,0xDD,0xAB,0x81,0x80,0xD0,0x08,0x2D,0x88,0x94,0x07,0x4F,0x3A,0xCB,
+	0x66,0xD0,0xF6,0x2F,0x87,0xAD,0x25,0x81,0x70,0x29,0x13,0xA0,0x83,0x5F,0x5B,0xD1,
+	0x9B,0x00,0x00,0x91,0xB2,0xD7,0x33,0xB6,0x10,0x3A,0xF0,0x9C,0x19,0x13,0xC9,0xB1,
+	0x18,0x1A,0x87,0xF6,0x5A,0xB8,0x80,0x6F,0x48,0x7A,0xC5,0x8D,0x42,0xDD,0x28,0x4B,
+	0xDA,0x32,0xDF,0xEE,0x8D,0x6D,0xD3,0x18,0x3D,0x8C,0x48,0x90,0x87,0xBC,0x3F,0x37,
+	0xCD,0x8A,0xDE,0xCD,0x55,0x0C,0x11,0x5E,0x50,0x92,0xB1,0x85,0x1D,0xD0,0x0A,0xF5,
+	0x20,0xB3,0xC6,0xD1,0xD1,0x26,0xD5,0x8B,0x12,0x3D,0x86,0x0B,0xFA,0x7E,0x4D,0xEF,
+	0xAD,0x72,0x38,0x5B,0xBD,0x97,0x48,0xD4,0x1E,0xB2,0x00,0x5C,0x90,0xE6,0xCD,0xA7,
+	0x5A,0xCA,0x77,0x74,0x54,0xD6,0x34,0x47,0x06,0x48,0xE9,0xBC,0x56,0x13,0x4E,0xE7,
+	0x17,0x6A,0x46,0x38,0xC9,0xDE,0x51,0x4A,0xFB,0x3B,0x73,0xAD,0xCE,0x8E,0x13,0xC9,
+	0x33,0x26,0x50,0xD6,0x66,0xF3,0xA7,0xA2,0xB8,0x60,0x5E,0x14,0x11,0x99,0x4C,0x4D,
+	0x66,0x19,0x99,0xFE,0x59,0x77,0x5B,0xE0,0x20,0xAB,0x36,0xCD,0x91,0x6F,0xE9,0xF8,
+	0x95,0x43,0x41,0x61,0x7D,0xF8,0xFB,0xAD,0x75,0x33,0xA5,0xD2,0xC4,0x67,0x95,0x97,
+	0x97,0xB6,0x07,0xD4,0xB0,0x1A,0x7E,0x4E,0x6D,0xCD,0xA9,0x05,0x00,0x54,0x83,0x6D,
+	0x52,0xA3,0x17,0xD6,0x5A,0xA0,0x83,0xC6,0xD9,0x78,0x29,0xEF,0xD2,0x08,0xA1,0x28,
+	0xCA,0xEA,0x70,0xA1,0x05,0x84,0xB4,0x48,0xF9,0x00
+};
+
diff --git a/drivers/video/wmt/bootanimation/animation.c b/drivers/video/wmt/bootanimation/animation.c
new file mode 100755
index 00000000..de803ccd
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/animation.c
@@ -0,0 +1,448 @@
+/**
+ * Author: Aimar Ma <AimarMa@wondermedia.com.cn> 
+ *  
+ * Show animation during kernel boot stage 
+ *  
+ *  
+ **/
+
+#include <linux/mm.h>
+#include <linux/timer.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/version.h>
+#include <linux/module.h>
+#include <asm/io.h>
+#include <linux/proc_fs.h>
+#include <linux/ioport.h>
+#include "animation.h"
+#include "buffer.h"
+#include "LzmaDec.h"
+#include "../memblock.h"
+
+#include "anim_data.h"
+
+
+#define ANIM_STOP_PROC_FILE "kernel_animation"
+
+#define     MAX_CLIP_COUNT          6
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+//extern void clear_animation_fb(void * p);
+//extern void flip_animation_fb(int pingpong);
+
+
+
+#define THE_MB_USER "Boot-Animation"
+
+#define DEFAULT_BUF_IMAGES  4       //default buffered image count
+
+#undef THIS_DEBUG
+//#define THIS_DEBUG
+
+
+
+#ifdef THIS_DEBUG
+#define LOG_DBG(fmt,args...)	printk(KERN_INFO "[Boot Animation] " fmt , ## args)
+#define LOG_INFO(fmt,args...)	printk(KERN_INFO "[Boot Animation] " fmt, ## args)
+#define LOG_ERROR(fmt,args...)	printk(KERN_ERR "[Boot Animation] " fmt , ## args)  
+#else
+#define LOG_DBG(fmt,args...)	
+#define LOG_INFO(fmt,args...)   printk(KERN_INFO "[Boot Animation] " fmt, ## args)
+#define LOG_ERROR(fmt,args...)	printk(KERN_ERR "[Boot Animation] " fmt , ## args)  
+#endif
+
+
+// MUST match Windows PC tool. Don't change it.
+struct animation_clip_header{
+	int  xres;
+	int  yres;
+    int  linesize;
+	unsigned char x_mode;
+	unsigned char y_mode;
+	short x_offset;
+	short y_offset;
+	unsigned char repeat;
+	unsigned char reserved;
+	int  interval;
+	int  image_count;
+	int  data_len;
+};
+
+// MUST match Windows PC tool. Don't change it.
+struct file_header {
+	int maigc;
+	unsigned short version;
+	unsigned char clip_count;
+	unsigned char color_format;
+    unsigned int  file_len;
+};
+
+
+
+struct play_context {
+    struct animation_clip_header *clip;
+    int xpos;           //  top postion
+    int ypos;           //  left postion
+
+    volatile int  play_thread;
+    animation_buffer buf;
+};
+
+
+//  globe value to stop the animation loop
+static volatile int g_logo_stop = 0;
+static struct       animation_fb_info fb;
+
+static void *SzAlloc(void *p, size_t size)
+{
+    void * add = (void *)mb_alloc(size);
+    LOG_DBG("alloc: size %d, add = %p \n", size, add);
+    return add;
+}
+
+static void SzFree(void *p, void *address) {
+    if (address != 0) {
+        LOG_DBG("free: address = %p \n", address);
+        mb_free((int)address);
+    }
+}
+
+static ISzAlloc g_Alloc = { SzAlloc, SzFree };
+
+
+static int show_frame(struct play_context *ctx, unsigned char *data)
+{
+    unsigned char * dest;
+    int linesize = fb.width * (fb.color_fmt + 1) * 2;
+    int i = 0;
+    struct animation_clip_header *clip = ctx->clip;
+    if (g_logo_stop)
+		return 0;
+
+    dest = fb.addr;
+    
+//    printk(KERN_INFO "dest = 0x%p src = 0x%p\n", dest, data);
+
+    if(data) {
+        LOG_DBG("dest %p, data %p (%d,%d) (%dx%d) linesize(%d,%d)", dest, data, 
+                ctx->xpos, ctx->ypos, clip->xres, clip->yres, clip->linesize, linesize);
+
+        dest += ctx->ypos * linesize;
+        dest += ctx->xpos * (fb.color_fmt + 1) * 2;
+        
+        for (i = 0; i <  clip->yres; i++) {
+            memcpy(dest, data, clip->xres * (fb.color_fmt + 1) * 2);
+            dest += linesize;
+            data += clip->linesize;
+        }
+    }
+ 
+    LOG_DBG("show_frame data %p, fb.addr %p\n", data, fb.addr);
+    return 0;
+}
+
+static int decompress(struct play_context * ctx, unsigned char *src, unsigned int src_len)
+{
+	SRes res = 0;
+	CLzmaDec state;
+    size_t inPos = 0;
+    unsigned char * inBuf;
+    SizeT inProcessed;
+
+
+	// 1)  read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header
+	UInt64 unpackSize = 0;
+	int i;
+
+	unsigned char * header = src;
+	for (i = 0; i < 8; i++)
+		unpackSize += (UInt64)header[LZMA_PROPS_SIZE + i] << (i * 8);
+
+	//  2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
+
+
+	LzmaDec_Construct(&state);
+    RINOK(LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc));
+	if (res != SZ_OK)
+		return res;
+
+	//  3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
+	LzmaDec_Init(&state);
+
+
+	inBuf = header + LZMA_PROPS_SIZE + 8;
+
+	for (;;)
+	{
+		unsigned int outSize;
+		unsigned char * outBuf = animation_buffer_get_writable(&ctx->buf, &outSize);
+
+		unsigned int frame_size = outSize;
+		unsigned int decoded = 0;
+		ELzmaFinishMode finishMode = LZMA_FINISH_ANY;
+		ELzmaStatus status;
+		while(1) {
+            inProcessed = src_len - LZMA_PROPS_SIZE - 8 - inPos;
+
+			res = LzmaDec_DecodeToBuf(&state, outBuf + frame_size - outSize, &outSize,
+				inBuf + inPos, &inProcessed, finishMode, &status);
+
+			inPos += inProcessed;
+			decoded += outSize;
+            unpackSize -= outSize;
+			outSize = frame_size - decoded;
+
+            LOG_DBG("Decoded %d bytes, inPos = %d\n", decoded, inPos);
+
+			if(res != SZ_OK)
+				break;
+
+			if (outSize == 0)
+				break;
+		}
+
+		animation_buffer_write_finish(&ctx->buf, outBuf);
+
+		if (res != SZ_OK || unpackSize == 0 || g_logo_stop)
+            break;
+	}
+
+    //  4) decompress finished, do clean job
+    LzmaDec_Free(&state, &g_Alloc);
+	return res;
+}
+
+static int animation_play(void * arg)
+{
+    unsigned char * data;
+    static int not_first_play;
+    struct play_context *ctx = (struct play_context *)arg;
+
+    LOG_DBG( "animation_play thread start...\n");
+    
+    if(!not_first_play) {
+        msleep(500);        // sleep a while to wait deocde few frames
+//        clear_animation_fb(fb.addr);
+        not_first_play = 1;
+    }
+    
+
+    //  try to get a valid frame and show it
+    while(!g_logo_stop) {
+        data = animation_buffer_get_readable(&ctx->buf);
+        if(data) {
+            show_frame(ctx, data);
+            animation_buffer_read_finish(&ctx->buf, data);
+        }
+        else {
+            if( ctx->buf.eof )       //no data and reach eof
+                break;
+            LOG_DBG("animation_buffer_get_readable return NULL\n");
+        }
+
+        if(g_logo_stop)
+            break;
+
+        //else 
+        msleep(ctx->clip->interval);
+    }
+
+    LOG_DBG( "animation_play thread End\n");
+    animation_buffer_stop(&ctx->buf);
+    ctx->play_thread = 0;
+    return 0;
+}
+
+
+static void decode_clip(struct animation_clip_header *clip, unsigned char * data, int index)
+{
+	//	start timer for animation playback
+    struct play_context ctx;
+    int buf_images;
+
+    LOG_DBG("Start playing clip %d, %dx%d, linesize %d, image %d, data_len %d\n", 
+            index, clip->xres, clip->yres, clip->linesize, clip->image_count, clip->data_len);
+
+    ctx.clip = clip;
+    
+    //  init the decompress buffer
+	if (clip->repeat == 0) {
+        buf_images = DEFAULT_BUF_IMAGES;
+        if(buf_images > clip->image_count)
+            buf_images = clip->image_count;
+	}
+	else {
+        //  for the repeat clip, alloc a big memory to store all the frames
+		buf_images = clip->image_count;
+	}
+
+    if( 0 != animation_buffer_init(&ctx.buf, clip->linesize * clip->yres, buf_images, &g_Alloc)){
+        LOG_ERROR("Can't init animation buffer %dx%d\n", clip->linesize * clip->yres, buf_images);
+        return;
+    }
+
+
+    ctx.xpos = clip->x_mode * (fb.width  / 2  - clip->xres / 2) + clip->x_offset;
+    ctx.ypos = clip->y_mode * (fb.height / 2  - clip->yres / 2) + clip->y_offset;
+
+    kthread_run(animation_play, &ctx, "wmt-boot-play");
+    ctx.play_thread = 1;
+
+	LOG_DBG("Start Decompressing ... \n");
+    decompress(&ctx, data, clip->data_len);
+
+    if (clip->repeat) {
+		while (!g_logo_stop) {
+			//  Fake decompress for REPEAT mode. (Only decompress the clip once so we can save more CPU)
+			unsigned int outSize;
+			unsigned char * outBuf;
+
+            outBuf = animation_buffer_get_writable(&ctx.buf, &outSize);
+			animation_buffer_write_finish(&ctx.buf, outBuf);
+        }
+	}
+
+    LOG_DBG("Decompress finished!\n");
+    ctx.buf.eof = 1;
+    //wait the play thread exit
+    while(ctx.play_thread) {
+        msleep(10);
+    }
+
+    LOG_DBG("Play clip %d finished\n",  index);
+	animation_buffer_release(&ctx.buf, &g_Alloc);
+}
+
+
+static int animation_main(void * arg)
+{
+    unsigned char * clip;
+    int i;
+
+    struct file_header *header = (struct file_header *)arg;
+    int clip_count = header->clip_count;
+	struct animation_clip_header clip_headers[MAX_CLIP_COUNT];
+    unsigned char  *             clip_datas[MAX_CLIP_COUNT];
+
+    if( clip_count > MAX_CLIP_COUNT)
+        clip_count  = MAX_CLIP_COUNT;
+    LOG_DBG( "animation_main thread start, clip_cout = %d\n", clip_count);
+
+
+	clip = (unsigned char *)(header + 1);
+    for (i = 0; i< clip_count; i++){
+        memcpy(&clip_headers[i], clip, sizeof(struct animation_clip_header));
+        clip += sizeof(struct animation_clip_header);
+        clip_datas[i] = clip;
+		clip += clip_headers[i].data_len;
+	}
+
+    LOG_DBG( "Found %d clip(s)\n", clip_count);
+
+	for (i = 0; i < clip_count; i++) {
+        if (!g_logo_stop)
+            decode_clip(&clip_headers[i], clip_datas[i], i);
+	}
+
+
+    g_Alloc.Free(&g_Alloc, arg);
+    LOG_DBG( "animation_main thread finished \n");
+	return 0;
+}
+
+
+static int stop_proc_write( struct file   *file,
+                           const char    *buffer,
+                           unsigned long count,
+                           void          *data )
+{
+    /* 
+    char value[20];
+    int len = count;
+    if( len >= sizeof(value))
+        len = sizeof(value) - 1;
+
+    if(copy_from_user(value, buffer, len))
+        return -EFAULT;
+
+    value[len] = '\0';
+
+    LOG_DBG("procfile_write get %s\n", value);
+    */
+
+    //anything will stop the boot animation
+    animation_stop();
+
+    return count; // discard other chars
+}
+
+struct proc_dir_entry *stop_proc_file;
+
+static struct proc_dir_entry * create_stop_proc_file(void)
+{
+    stop_proc_file = create_proc_entry(ANIM_STOP_PROC_FILE, 0644, NULL);
+
+    if( stop_proc_file != NULL )
+        stop_proc_file->write_proc = stop_proc_write;
+    else
+        LOG_ERROR("Can not create /proc/%s file", ANIM_STOP_PROC_FILE);
+    return stop_proc_file;
+}
+
+int animation_start(struct animation_fb_info *info)
+{
+    struct file_header *header;
+    unsigned char * buffer;
+
+    const void * animation_data = anim_data;
+    if (animation_data == NULL) 
+        return -1;
+
+    if( !create_stop_proc_file() )
+        return -1;
+
+    header = (struct file_header *)animation_data;
+
+    if (header->maigc != 0x12344321) {
+        LOG_ERROR ("It's not a valid Animation file at 0x%p, first 4 bytes: 0x%x\n", animation_data, header->maigc);
+        return -1;
+    }
+
+    buffer = g_Alloc.Alloc(&g_Alloc, header->file_len);
+    if(!buffer) {
+        LOG_ERROR ("Can't alloc enough memory, length %d\n", header->file_len);
+        return -1;
+    }
+
+    memcpy(&fb, info, sizeof(fb));
+
+    //copy it to the new buffer and start the play thread
+    memcpy(buffer, header, header->file_len);
+    g_logo_stop = 0;
+
+    
+    LOG_DBG("Start animation_main thread ...\n");
+    kthread_run(animation_main, buffer, "wmt-boot-anim");
+    return 0;
+}
+
+int animation_stop(void)
+{
+    LOG_INFO("animation_stop\n");
+    g_logo_stop = 1;
+
+    if( stop_proc_file ) {
+        remove_proc_entry(ANIM_STOP_PROC_FILE,stop_proc_file);
+        stop_proc_file = NULL;
+    }
+
+    return 0;
+}
+
+EXPORT_SYMBOL(animation_start);
+EXPORT_SYMBOL(animation_stop);
+
+
diff --git a/drivers/video/wmt/bootanimation/animation.h b/drivers/video/wmt/bootanimation/animation.h
new file mode 100755
index 00000000..e63686ec
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/animation.h
@@ -0,0 +1,15 @@
+#ifndef _BOOTANIMATION_H_
+#define _BOOTANIMATION_H_
+
+
+struct animation_fb_info {
+    unsigned char * addr;    // frame buffer start address
+    unsigned int width;      // width
+    unsigned int height;     // height
+    unsigned int color_fmt;  // color format,  0 -- rgb565, 1 -- rgb888
+};
+
+int animation_start(struct animation_fb_info *info);
+int animation_stop(void);
+
+#endif
diff --git a/drivers/video/wmt/bootanimation/buffer.c b/drivers/video/wmt/bootanimation/buffer.c
new file mode 100755
index 00000000..6b6f1b89
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/buffer.c
@@ -0,0 +1,85 @@
+
+#include "buffer.h"
+
+#define assert(int )
+
+int animation_buffer_init(animation_buffer * buf, int size, int count, ISzAlloc *alloc)
+{
+    buf->buffer = buf->w_pos = buf->r_pos = alloc->Alloc(alloc, size * count);
+    if(!buf->buffer)
+        return -1;
+    
+	buf->frame_count = count;
+	buf->frame_size = size;
+    buf->eof = 0;
+    
+    sema_init(&buf->sem_writable, count);
+    sema_init(&buf->sem_readable, 0);
+    
+    return 0;
+}
+
+int animation_buffer_release(animation_buffer * buf, ISzAlloc *alloc)
+{
+    if (buf->buffer)
+		alloc->Free(alloc, buf->buffer);
+	buf->buffer = buf->w_pos = buf->r_pos = NULL;
+    return 0;
+}
+
+unsigned char * animation_buffer_get_writable(animation_buffer * buf, unsigned int * pSize)
+{
+    down_interruptible(&buf->sem_writable);
+	*pSize = buf->frame_size;
+	return buf->w_pos;
+}
+
+int animation_buffer_stop(animation_buffer * buf)
+{
+	up(&buf->sem_readable);
+    /* up twice for safey*/
+	up(&buf->sem_writable);
+	up(&buf->sem_writable);
+    return 0;
+}
+
+void   animation_buffer_write_finish(animation_buffer * buf, unsigned char * addr)
+{
+    assert(addr == buf->w_pos);
+    
+ //   printk(KERN_INFO "add one buffer 0x%p\n", addr);
+        
+	buf->w_pos += buf->frame_size;
+	if (buf->w_pos - buf->buffer == buf->frame_size * buf->frame_count) 
+		buf->w_pos = buf->buffer;
+  
+	up(&buf->sem_readable);
+ //   printk(KERN_INFO "write <<<<<<<======\n");
+	return;
+    
+}
+
+
+unsigned char * animation_buffer_get_readable(animation_buffer * buf)
+{
+    int ret = down_trylock(&buf->sem_readable);
+	if (ret == 0) {		
+		return buf->r_pos;
+	}
+	else {
+		return NULL;
+	}
+}
+
+void animation_buffer_read_finish(animation_buffer * buf, unsigned char * addr)
+{
+    //  Integrity check
+	assert(addr == buf->r_pos);
+  //  printk(KERN_INFO "read one buffer 0x%p\n", addr);
+	buf->r_pos += buf->frame_size;	
+	if (buf->r_pos - buf->buffer == buf->frame_size * buf->frame_count) 
+		buf->r_pos = buf->buffer;
+      
+	up(&buf->sem_writable);
+}
+
diff --git a/drivers/video/wmt/bootanimation/buffer.h b/drivers/video/wmt/bootanimation/buffer.h
new file mode 100755
index 00000000..3ac79aa5
--- /dev/null
+++ b/drivers/video/wmt/bootanimation/buffer.h
@@ -0,0 +1,34 @@
+#ifndef ANIMATION_BUFFER_H_INCLUDED
+#define ANIMATION_BUFFER_H_INCLUDED
+
+#include "LzmaDec.h"
+#include <linux/semaphore.h>
+
+typedef struct 
+{
+    unsigned char *buffer;
+    unsigned char *w_pos;
+    unsigned char *r_pos;
+    int frame_count;
+    int frame_size;
+    struct semaphore sem_writable;
+    struct semaphore sem_readable;
+    int     eof;
+}animation_buffer;
+    
+                              
+int animation_buffer_init(animation_buffer * buf, int size, int count, ISzAlloc *alloc);
+
+int animation_buffer_stop(animation_buffer * buf);
+int animation_buffer_release(animation_buffer * buf, ISzAlloc *alloc);
+
+
+unsigned char * animation_buffer_get_writable(animation_buffer * buf, unsigned int * pSize);
+void            animation_buffer_write_finish(animation_buffer * buf, unsigned char * addr);
+
+unsigned char * animation_buffer_get_readable(animation_buffer * buf);
+void            animation_buffer_read_finish(animation_buffer * buf, unsigned char * addr);
+
+
+#endif /* ANIMATION_BUFFER_H_INCLUDED */
+
diff --git a/drivers/video/wmt/cec.c b/drivers/video/wmt/cec.c
new file mode 100755
index 00000000..5f80c334
--- /dev/null
+++ b/drivers/video/wmt/cec.c
@@ -0,0 +1,333 @@
+/*++
+ * linux/drivers/video/wmt/cec.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define CEC_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "cec.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define CEC_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx cec_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in cec.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  cec_xxx;        *//*Example*/
+int cec_logical_addr;
+int cec_physical_addr;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void cec_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+/*---------------------------- CEC COMMON API -------------------------------*/
+
+#ifdef WMT_FTBLK_CEC
+
+struct cec_base_regs *cec_regs = (void *) CEC_BASE_ADDR;
+/*---------------------------- CEC HAL --------------------------------------*/
+void wmt_cec_tx_data(char *buf, int size)
+{
+	int i;
+	unsigned int reg;
+	int wait_idle;
+
+#ifdef DEBUG
+	DPRINT("[CEC] tx data(%d):", size);
+	for (i = 0; i < size; i++)
+		DPRINT(" 0x%x", buf[i]);
+	DPRINT("\n");
+#endif
+
+	if (size > 16) {
+		DPRINT("[CEC] *W* size max 16\n");
+		return;
+	}
+
+	wait_idle = 0;
+	while (cec_regs->enable.b.wr_start) {
+		if (wait_idle >= 10) {
+			DPRINT("[CEC] wait idle timeout\n");
+			return;
+		}
+		wait_idle++;
+		mdelay(10);
+		return;
+	}
+
+	for (i = 0; i < size; i++) {
+		reg = (buf[i] << 4) + 0x1;
+		if (i == (size - 1))
+			reg |= BIT1;
+		cec_regs->encode_data[i].val = reg;
+	}
+	cec_regs->encode_number.b.wr_num = (size * 10) + 0x1;
+	cec_regs->enable.b.wr_start = 1;
+}
+
+int wmt_cec_rx_data(char *buf)
+{
+	int i, size;
+	unsigned int reg;
+
+	for (i = 0; i < 16; i++) {
+		reg = cec_regs->decode_data[i].val;
+		buf[i] = (reg & 0xFF0) >> 4;
+		if (reg & BIT1) /* EOM */
+			break;
+	}
+	cec_regs->decode_reset.b.finish_reset = 1;
+	mdelay(1);
+	cec_regs->decode_reset.b.finish_reset = 0;
+	size = i + 1;
+#ifdef DEBUG
+	DPRINT("[CEC] rx data(%d):\n", size);
+	for (i = 0; i < size; i++)
+		DPRINT(" 0x%x", buf[i]);
+	DPRINT("\n");
+#endif
+	return size;
+}
+
+void wmt_cec_set_clock(void)
+{
+	#define CEC_CLOCK (1000000 / 7984)
+
+	cec_regs->wr_start_set0 = (370 * CEC_CLOCK); /* 3.7 ms */
+	cec_regs->wr_start_set1 = (450 * CEC_CLOCK); /* 4.5 ms */
+	cec_regs->wr_logic0_set0 = (150 * CEC_CLOCK); /* 1.5 ms */
+	cec_regs->wr_logic0_set1 = (240 * CEC_CLOCK); /* 2.4 ms */
+	cec_regs->wr_logic1_set0 = (60 * CEC_CLOCK); /* 0.6 ms */
+	cec_regs->wr_logic1_set1 = (240 * CEC_CLOCK); /* 2.4 ms */
+	cec_regs->rd_start_l_set0 = (350 * CEC_CLOCK); /* 3.5 ms */
+	cec_regs->rd_start_r_set0 = (390 * CEC_CLOCK); /* 3.9 ms */
+	cec_regs->rd_start_l_set1 = (430 * CEC_CLOCK); /* 4.3 ms */
+	cec_regs->rd_start_r_set1 = (470 * CEC_CLOCK); /* 4.7 ms */
+	cec_regs->rd_logic0_l_set0 = (130 * CEC_CLOCK); /* 1.3 ms */
+	cec_regs->rd_logic0_r_set0 = (170 * CEC_CLOCK); /* 1.7 ms */
+	cec_regs->rd_logic0_l_set1 = (205 * CEC_CLOCK); /* 2.05 ms*/
+	cec_regs->rd_logic0_r_set1 = (275 * CEC_CLOCK); /* 2.75 ms*/
+	cec_regs->rd_logic1_l_set0 = (40 * CEC_CLOCK); /* 0.4 ms */
+	cec_regs->rd_logic1_r_set0 = (80 * CEC_CLOCK); /* 0.8 ms */
+	cec_regs->rd_logic1_l_set1 = (205 * CEC_CLOCK); /* 2.05 ms*/
+	cec_regs->rd_logic1_r_set1 = (275 * CEC_CLOCK); /* 2.75 ms*/
+	cec_regs->rd_l_set0_error = (182 * CEC_CLOCK); /* 1.82 ms */
+	cec_regs->rd_r_set1_error = (238 * CEC_CLOCK); /* 2.38 ms */
+	cec_regs->rd_l_error = (287 * CEC_CLOCK); /* 2.87 ms */
+	cec_regs->rx_sample_l_range = (85 * CEC_CLOCK); /* 0.85 ms*/
+	cec_regs->rx_sample_r_range = (125 * CEC_CLOCK); /*1.25 ms*/
+	cec_regs->wr_set0_error = (225 * CEC_CLOCK); /* 2.25 ms */
+	cec_regs->wr_set1_error = (225 * CEC_CLOCK); /* 2.25 ms ?*/
+}
+
+void wmt_cec_set_logical_addr(int no, char addr, int enable)
+{
+	switch (no) {
+	case 0:
+		cec_regs->logical_addr.b.addr1 = addr;
+		cec_regs->logical_addr.b.valid1 = addr;
+		break;
+	case 1:
+		cec_regs->logical_addr.b.addr2 = addr;
+		cec_regs->logical_addr.b.valid2 = addr;
+		break;
+	case 2:
+		cec_regs->logical_addr.b.addr3 = addr;
+		cec_regs->logical_addr.b.valid3 = addr;
+		break;
+	case 3:
+		cec_regs->logical_addr.b.addr4 = addr;
+		cec_regs->logical_addr.b.valid4 = addr;
+		break;
+	case 4:
+		cec_regs->logical_addr.b.addr5 = addr;
+		cec_regs->logical_addr.b.valid5 = addr;
+		break;
+	default:
+		DPRINT("[CEC] *W* invalid %d\n", no);
+		break;
+	}
+	DBGMSG("[CEC] set logical addr %d,0x%x\n", no, addr);
+}
+
+void wmt_cec_rx_enable(int enable)
+{
+	cec_regs->reject.b.next_decode = (enable) ? 0 : 1;
+	/* GPIO4 disable GPIO function */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x40, BIT4, 4, (enable) ? 0 : 1);
+}
+
+void wmt_cec_enable_int(int no, int enable)
+{
+	if (enable)
+		cec_regs->int_enable |= (0x1 << no);
+	else
+		cec_regs->int_enable &= ~(0x1 << no);
+}
+
+void wmt_cec_clr_int(int sts)
+{
+	cec_regs->status.val = sts;
+}
+
+int wmt_cec_get_int(void)
+{
+	int reg;
+	reg = cec_regs->status.val;
+	return reg;
+}
+
+void wmt_cec_enable_loopback(int enable)
+{
+	/* 1 : read self write and all dest data */
+	cec_regs->rd_encode.b.enable = enable;
+}
+
+void wmt_cec_init_hw(void)
+{
+	wmt_cec_set_clock();
+	cec_regs->wr_retry.b.retry = 3;
+	cec_regs->rx_trig_range = 2;
+
+	cec_regs->free_3x.b.free_3x = 3;
+	cec_regs->free_3x.b.free_5x = 5;
+	cec_regs->free_3x.b.free_7x = 7;
+
+	cec_regs->comp.b.disable = 1;
+	cec_regs->handle_disable.b.err = 0;
+	cec_regs->handle_disable.b.no_ack = 0;
+	cec_regs->decode_full.b.disable = 0;
+	cec_regs->status4_disable.b.start = 1;
+	cec_regs->status4_disable.b.logic0 = 1;
+	cec_regs->status4_disable.b.logic1 = 1;
+	cec_regs->rd_encode.b.enable = 0;
+}
+
+/*---------------------------- CEC API --------------------------------------*/
+void wmt_cec_reg_dump(void)
+{
+	DPRINT("========== CEC register dump ==========\n");
+	vpp_reg_dump(REG_CEC_BEGIN, REG_CEC_END - REG_CEC_BEGIN);
+
+	DPRINT("---------- CEC Tx ----------\n");
+	DPRINT("wr start %d,wr num %d\n",
+		cec_regs->enable.b.wr_start, cec_regs->encode_number.b.wr_num);
+	DPRINT("wr header ack %d,EOM %d,data 0x%x\n",
+		cec_regs->encode_data[0].b.wr_data_ack,
+		cec_regs->encode_data[0].b.wr_data_eom,
+		cec_regs->encode_data[0].b.wr_data);
+	DPRINT("wr data ack %d,EOM %d,data 0x%x\n",
+		cec_regs->encode_data[1].b.wr_data_ack,
+		cec_regs->encode_data[1].b.wr_data_eom,
+		cec_regs->encode_data[1].b.wr_data);
+	DPRINT("finish reset %d,wr retry %d\n",
+		cec_regs->decode_reset.b.finish_reset,
+		cec_regs->wr_retry.b.retry);
+	DPRINT("---------- CEC Rx ----------\n");
+	DPRINT("rd start %d,all ack %d,finish %d\n",
+		cec_regs->decode_start.b.rd_start,
+		cec_regs->decode_start.b.rd_all_ack,
+		cec_regs->decode_start.b.rd_finish);
+	DPRINT("rd header ack %d,EOM %d,data 0x%x\n",
+		cec_regs->decode_data[0].b.rd_data_ack,
+		cec_regs->decode_data[0].b.rd_data_eom,
+		cec_regs->decode_data[0].b.rd_data);
+	DPRINT("rd data ack %d,EOM %d,data 0x%x\n",
+		cec_regs->decode_data[1].b.rd_data_ack,
+		cec_regs->decode_data[1].b.rd_data_eom,
+		cec_regs->decode_data[1].b.rd_data);
+
+	DPRINT("---------- Logical addr ----------\n");
+	DPRINT("addr1 0x%x,valid %d\n",
+		cec_regs->logical_addr.b.addr1,
+		cec_regs->logical_addr.b.valid1);
+	DPRINT("addr2 0x%x,valid %d\n",
+		cec_regs->logical_addr.b.addr2,
+		cec_regs->logical_addr.b.valid2);
+	DPRINT("addr3 0x%x,valid %d\n",
+		cec_regs->logical_addr.b.addr3,
+		cec_regs->logical_addr.b.valid3);
+	DPRINT("addr4 0x%x,valid %d\n",
+		cec_regs->logical_addr.b.addr4,
+		cec_regs->logical_addr.b.valid4);
+	DPRINT("addr5 0x%x,valid %d\n",
+		cec_regs->logical_addr.b.addr5,
+		cec_regs->logical_addr.b.valid5);
+
+	DPRINT("---------- Misc ----------\n");
+	DPRINT("free 3x %d,5x %d,7x %d\n",
+		cec_regs->free_3x.b.free_3x, cec_regs->free_3x.b.free_5x,
+		cec_regs->free_3x.b.free_7x);
+	DPRINT("reject next decode %d,comp disable %d\n",
+		cec_regs->reject.b.next_decode, cec_regs->comp.b.disable);
+	DPRINT("err handle disable %d,no ack disable %d\n",
+		cec_regs->handle_disable.b.err,
+		cec_regs->handle_disable.b.no_ack);
+	DPRINT("r1 enc ok %d,r1 dec ok %d,r1 err %d\n",
+		cec_regs->status.b.r1_encode_ok,
+		cec_regs->status.b.r1_decode_ok,
+		cec_regs->status.b.r1_error);
+	DPRINT("r1 arb fail %d,r1 no ack %d\n",
+		cec_regs->status.b.r1_arb_fail,
+		cec_regs->status.b.r1_no_ack);
+	DPRINT("dec full disable %d,self rd enable %d\n",
+		cec_regs->decode_full.b.disable,
+		cec_regs->rd_encode.b.enable);
+}
+
+#ifdef CONFIG_PM
+static unsigned int *wmt_cec_pm_bk;
+void wmt_cec_do_suspend(void)
+{
+	/* Suspend GPIO output high */
+	vppif_reg32_write(GPIO_BASE_ADDR+0xC0, BIT23, 23, 0);
+	wmt_cec_pm_bk = vpp_backup_reg(REG_CEC_BEGIN,
+		(REG_CEC_END - REG_CEC_BEGIN));
+}
+
+void wmt_cec_do_resume(void)
+{
+	vppm_regs->sw_reset2.val = 0x1011111;
+	/* disable GPIO function */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x40, BIT4, 4, 0);
+	/* GPIO4 disable GPIO out */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x80, BIT4, 4, 0);
+	/* GPIO4 disable pull ctrl */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x480, BIT4, 4, 0);
+	/* Suspend GPIO output enable */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x80, BIT23, 23, 1);
+	/* Suspend GPIO output high */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0xC0, BIT23, 23, 1);
+	/* Wake3 disable pull ctrl */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x480, BIT19, 19, 0);
+	vpp_restore_reg(REG_CEC_BEGIN,
+		(REG_CEC_END - REG_CEC_BEGIN), wmt_cec_pm_bk);
+	wmt_cec_pm_bk = 0;
+}
+#endif
+#endif /* WMT_FTBLK_CEC */
+
diff --git a/drivers/video/wmt/cec.h b/drivers/video/wmt/cec.h
new file mode 100755
index 00000000..887be767
--- /dev/null
+++ b/drivers/video/wmt/cec.h
@@ -0,0 +1,64 @@
+/*++
+ * linux/drivers/video/wmt/cec.h
+ * WonderMedia HDMI CEC driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp-osif.h"
+#include "./hw/wmt-vpp-hw.h"
+#include "hw/wmt-cec-reg.h"
+
+#ifdef WMT_FTBLK_CEC
+
+#ifndef CEC_H
+#define CEC_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CEC_C
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+EXTERN void wmt_cec_tx_data(char *buf, int size);
+EXTERN void wmt_cec_clr_int(int sts);
+EXTERN int wmt_cec_get_int(void);
+
+EXTERN void wmt_cec_enable_loopback(int enable);
+EXTERN void wmt_cec_tx_data(char *buf, int size);
+EXTERN int wmt_cec_rx_data(char *buf);
+EXTERN void wmt_cec_hotplug_notify(int plug_status);
+EXTERN void wmt_cec_do_hotplug_notify(int no, int plug_status);
+
+EXTERN void wmt_cec_init_hw(void);
+EXTERN void wmt_cec_set_logical_addr(int no, char addr, int enable);
+EXTERN void wmt_cec_rx_enable(int enable);
+EXTERN void wmt_cec_do_suspend(void);
+EXTERN void wmt_cec_do_resume(void);
+
+#undef EXTERN
+#ifdef __cplusplus
+}
+#endif
+#endif /* CEC_H */
+#endif /* WMT_FTBLK_CEC */
diff --git a/drivers/video/wmt/com-cec.h b/drivers/video/wmt/com-cec.h
new file mode 100755
index 00000000..8020aec5
--- /dev/null
+++ b/drivers/video/wmt/com-cec.h
@@ -0,0 +1,65 @@
+/*++
+ * linux/drivers/video/wmt/com-cec.h
+ * WonderMedia HDMI CEC driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef COM_CEC_H
+#define COM_CEC_H
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* define for notify AP */
+#define USER_PID 1
+#define WP_PID	 2
+#define USER_PIX_MAX 2
+#define NETLINK_CEC_TEST (MAX_LINKS - 2)
+
+#define DEVICE_RX_DATA	0
+#define DEVICE_PLUG_IN	2
+#define DEVICE_PLUG_OUT 3
+#define DEVICE_STREAM	4
+
+#define MAX_MSG_BYTE 16
+#define MSG_ABORT 0xff
+
+struct wmt_cec_msg {
+	char msglen;
+	char msgdata[MAX_MSG_BYTE];
+};
+#define wmt_cec_msg_t struct wmt_cec_msg
+
+struct wmt_phy_addr {
+	unsigned int phy_addr;
+};
+#define wmt_phy_addr_t struct wmt_phy_addr
+
+#define WMT_CEC_IOC_MAGIC	'c'
+#define WMT_CEC_IOC_MAXNR	3
+#define CECIO_TX_DATA		_IOW(WMT_CEC_IOC_MAGIC, 0, wmt_cec_msg_t)
+#define CECIO_TX_LOGADDR	_IO(WMT_CEC_IOC_MAGIC, 1)
+#define CECIO_RX_PHYADDR	_IOR(WMT_CEC_IOC_MAGIC, 2, wmt_phy_addr_t)
+
+#if defined(__cplusplus)
+}
+#endif
+#endif
diff --git a/drivers/video/wmt/com-mb.h b/drivers/video/wmt/com-mb.h
new file mode 100755
index 00000000..1b1380b5
--- /dev/null
+++ b/drivers/video/wmt/com-mb.h
@@ -0,0 +1,92 @@
+/*++
+ * WonderMedia Memory Block driver
+ *
+ * Copyright c 2010  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef COM_MB_H
+/* To assert that only one occurrence is included */
+#define COM_MB_H
+
+/*-------------------- MODULE DEPENDENCY -------------------------------------*/
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+
+/*------------------------------------------------------------------------------
+   Macros below are used for driver in IOCTL
+------------------------------------------------------------------------------*/
+#define MB_IOC_MAGIC 'M'
+
+/* O: physical address I: size */
+#define MBIO_MALLOC _IOWR(MB_IOC_MAGIC, 0, unsigned long)
+/* O: ummap size I: user address if map, physical address if not map */
+#define MBIO_FREE _IOWR(MB_IOC_MAGIC, 1, unsigned long)
+/* O: ummap size I: user address */
+#define MBIO_UNMAP _IOWR(MB_IOC_MAGIC, 2, unsigned long)
+/* O: mb size I: phys address */
+#define MBIO_MBSIZE _IOWR(MB_IOC_MAGIC, 3, unsigned long)
+/* O: max free mba size */
+#define MBIO_MAX_AVAILABLE_SIZE _IOR(MB_IOC_MAGIC, 4, unsigned long)
+/* advance use only */
+/* I: user address */
+#define MBIO_GET _IOW(MB_IOC_MAGIC, 5, unsigned long)
+/* I: user address */
+#define MBIO_PUT _IOW(MB_IOC_MAGIC, 6, unsigned long)
+/* O: virt address I: user address */
+#define MBIO_USER_TO_VIRT _IOWR(MB_IOC_MAGIC, 7, unsigned long)
+/* O: phys address I: user address */
+#define MBIO_USER_TO_PHYS _IOWR(MB_IOC_MAGIC, 8, unsigned long)
+/* I: size */
+#define MBIO_PREFETCH _IOW(MB_IOC_MAGIC, 9, unsigned long)
+/* O: static mba size */
+#define MBIO_STATIC_SIZE _IOR(MB_IOC_MAGIC, 10, unsigned long)
+/* O: use counter I: physical address */
+#define MBIO_MB_USER_COUNT _IOWR(MB_IOC_MAGIC, 11, unsigned long)
+#define MBIO_FORCE_RESET _IO(MB_IOC_MAGIC, 12)
+/* I: phys address */
+#define MBIO_GET_BY_PHYS _IOW(MB_IOC_MAGIC, 13, unsigned long)
+/* I: phys address */
+#define MBIO_PUT_BY_PHYS _IOW(MB_IOC_MAGIC, 14, unsigned long)
+/* I: user address */
+#define MBIO_SYNC_CACHE _IOW(MB_IOC_MAGIC, 15, unsigned long)
+/* O: mb driver version */
+#define MBIO_GET_VERSION _IOR(MB_IOC_MAGIC, 16, unsigned long)
+/* O: property of MB */
+#define MBIO_SET_CACHABLE _IOW(MB_IOC_MAGIC, 17, unsigned long)
+/* O: property of MB */
+#define MBIO_CLR_CACHABLE _IOW(MB_IOC_MAGIC, 18, unsigned long)
+/* I: phys address */
+#define MBIO_STATIC_GET _IOW(MB_IOC_MAGIC, 19, unsigned long)
+/* I: phys address */
+#define MBIO_STATIC_PUT _IOW(MB_IOC_MAGIC, 20, unsigned long)
+/* I: user address O: physical address */
+#define MBIO_TEST_USER2PHYS _IOWR(MB_IOC_MAGIC, 100, unsigned long)
+/* I: user address, size, prdt addr, and prdt size */
+#define MBIO_TEST_USER2PRDT _IOWR(MB_IOC_MAGIC, 101, unsigned long)
+/* I: user address, size, mmu addr, and mmu size O: mmu physical addr */
+#define MBIO_TEST_USER2MMUT _IOWR(MB_IOC_MAGIC, 102, unsigned long)
+/* I: user address, size, prdt addr, and prdt size */
+#define MBIO_TEST_MB2PRDT _IOWR(MB_IOC_MAGIC, 103, unsigned long)
+/* I: user address, size, mmu addr, and mmu size O: mmu physical addr */
+#define MBIO_TEST_MB2MMUT _IOWR(MB_IOC_MAGIC, 104, unsigned long)
+
+#endif /* ifndef COM_MB_H */
+
+/*=== END com-mb.h ==========================================================*/
+
diff --git a/drivers/video/wmt/com-vpp.h b/drivers/video/wmt/com-vpp.h
new file mode 100755
index 00000000..4076c4ae
--- /dev/null
+++ b/drivers/video/wmt/com-vpp.h
@@ -0,0 +1,455 @@
+/*++
+ * linux/drivers/video/wmt/com-vpp.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef COM_VPP_H
+#define COM_VPP_H
+
+#ifdef __KERNEL__
+#include <linux/types.h>
+#include <linux/fb.h>
+#include <asm/io.h>
+#include <mach/common_def.h>
+#include <mach/com-video.h>
+#else
+#include "com-video.h"
+#ifdef CFG_LOADER 
+#include "com-fb.h"
+#endif
+#endif
+
+#define VPP_NEW_FBUF_MANAGER
+
+#define VPP_AHB_CLK			250000000
+
+#ifdef CONFIG_MAX_RESX
+	#define VPP_HD_MAX_RESX		CONFIG_MAX_RESX
+#else
+	#define VPP_HD_MAX_RESX		1920
+#endif
+
+#ifdef CONFIG_MAX_RESY
+	#define VPP_HD_MAX_RESY		CONFIG_MAX_RESY
+#else
+	#define VPP_HD_MAX_RESY		1200
+#endif
+
+#ifdef CONFIG_DEFAULT_RESX
+	#define VPP_HD_DISP_RESX	CONFIG_DEFAULT_RESX
+#else
+	#define VPP_HD_DISP_RESX	1024
+#endif
+
+#ifdef CONFIG_DEFAULT_RESY
+	#define VPP_HD_DISP_RESY	CONFIG_DEFAULT_RESY
+#else
+	#define VPP_HD_DISP_RESY	768
+#endif
+
+#ifdef CONFIG_DEFAULT_FPS
+	#define VPP_HD_DISP_FPS		CONFIG_DEFAULT_FPS
+#else
+	#define VPP_HD_DISP_FPS		60
+#endif
+
+#define VPP_HD_DISP_PIXCLK	65000000
+
+#define BIT0	0x00000001
+#define BIT1	0x00000002
+#define BIT2	0x00000004
+#define BIT3	0x00000008
+#define BIT4	0x00000010
+#define BIT5	0x00000020
+#define BIT6	0x00000040
+#define BIT7	0x00000080
+#define BIT8	0x00000100
+#define BIT9	0x00000200
+#define BIT10	0x00000400
+#define BIT11	0x00000800
+#define BIT12	0x00001000
+#define BIT13	0x00002000
+#define BIT14	0x00004000
+#define BIT15	0x00008000
+#define BIT16	0x00010000
+#define BIT17	0x00020000
+#define BIT18	0x00040000
+#define BIT19	0x00080000
+#define BIT20	0x00100000
+#define BIT21	0x00200000
+#define BIT22	0x00400000
+#define BIT23	0x00800000
+#define BIT24	0x01000000
+#define BIT25	0x02000000
+#define BIT26	0x04000000
+#define BIT27	0x08000000
+#define BIT28	0x10000000
+#define BIT29	0x20000000
+#define BIT30	0x40000000
+#define BIT31	0x80000000
+
+#define VPP_YUV_BLACK		0x008080	/* Y, Cr, Cb */
+#define VPP_YUV_WHITE		0xff8080
+#define VPP_YUV_RED		0x51f05a
+#define VPP_YUV_GREEN		0x902235
+#define VPP_YUV_BLUE		0x286df0
+#define VPP_RGB32_BLACK		0x00000000
+
+#define VPP_COL_RGB32_BLACK	0x000000
+#define VPP_COL_RGB32_WHITE	0xFFFFFF
+#define VPP_COL_RGB32_RED	0xFF0000
+#define VPP_COL_RGB32_GREEN	0x00FF00
+#define VPP_COL_RGB32_BLUE	0x0000FF
+
+#define VPP_COL_BLACK		0x008080	/* Y, Cr, Cb */
+#define VPP_COL_WHITE		0xff8080
+#define VPP_COL_RED		0x41d464
+#define VPP_COL_GREEN		0x902235
+#define VPP_COL_BLUE		0x2372d4
+
+#define VPP_MAGNUM(s, e)	((2^((s)-(e)+1))-1)
+
+#define WMT_FB_COLFMT(a)	(a & 0xFF)
+
+enum vpp_fbuf_s {
+	VPP_FBUF_GOVR_1,
+	VPP_FBUF_GOVR_2,
+	VPP_FBUF_SCLR_1,
+	VPP_FBUF_SCLR_2,
+	VPP_FBUF_MAX
+};
+#define vpp_fbuf_t enum vpp_fbuf_s
+
+enum vpp_flag_s {
+	VPP_FLAG_NULL = 0,
+	VPP_FLAG_ENABLE = 1,
+	VPP_FLAG_DISABLE = 0,
+	VPP_FLAG_TRUE = 1,
+	VPP_FLAG_FALSE = 0,
+	VPP_FLAG_ZERO = 0,
+	VPP_FLAG_ONE = 1,
+	VPP_FLAG_SUCCESS = 1,
+	VPP_FLAG_ERROR = 0,
+	VPP_FLAG_RD = 1,
+	VPP_FLAG_WR = 0,
+};
+#define vpp_flag_t enum vpp_flag_s
+
+enum vpp_mod_s {
+	VPP_MOD_GOVRH2,
+	VPP_MOD_GOVRH,
+	VPP_MOD_DISP,
+	VPP_MOD_GOVW,
+	VPP_MOD_GOVM,
+	VPP_MOD_SCL,
+	VPP_MOD_SCLW,
+	VPP_MOD_VPU,
+	VPP_MOD_VPUW,
+	VPP_MOD_PIP,
+	VPP_MOD_VPPM,
+	VPP_MOD_LCDC,
+	VPP_MOD_CURSOR,
+	VPP_MOD_MAX
+};
+#define vpp_mod_t enum vpp_mod_s
+
+enum vpp_vout_s {
+	VPP_VOUT_NONE = 0,
+	VPP_VOUT_SDA = 1,
+	VPP_VOUT_LCD = 2,
+	VPP_VOUT_DVI = 3,
+	VPP_VOUT_HDMI = 4,
+	VPP_VOUT_DVO2HDMI = 5,
+	VPP_VOUT_LVDS = 6,
+	VPP_VOUT_VGA = 7,
+	VPP_VOUT_FBDEV = 8,
+	VPP_VOUT_VIRDISP = 9,
+	VPP_VOUT_MAX
+};
+#define vpp_vout_t enum vpp_vout_s
+
+enum vpp_display_format_s {
+	VPP_DISP_FMT_FRAME,	/* Progressive */
+	VPP_DISP_FMT_FIELD,	/* Interlace */
+	VPP_DISP_FMT_MAX,
+};
+#define vpp_display_format_t enum vpp_display_format_s
+
+enum vpp_media_format_s {
+	VPP_MEDIA_FMT_MPEG,
+	VPP_MEDIA_FMT_H264,
+	VPP_MEDIA_FMT_MAX,
+};
+#define vpp_media_format_t enum vpp_media_format_s
+
+enum vpp_csc_s { /* don't change this order */
+	VPP_CSC_YUV2RGB2_MIN,
+	VPP_CSC_YUV2RGB_SDTV_0_255 = VPP_CSC_YUV2RGB2_MIN,
+	VPP_CSC_YUV2RGB_SDTV_16_235,
+	VPP_CSC_YUV2RGB_HDTV_0_255,
+	VPP_CSC_YUV2RGB_HDTV_16_235,
+	VPP_CSC_YUV2RGB_JFIF_0_255,
+	VPP_CSC_YUV2RGB_SMPTE170M,
+	VPP_CSC_YUV2RGB_SMPTE240M,
+	VPP_CSC_RGB2YUV_MIN,
+	VPP_CSC_RGB2YUV_SDTV_0_255 = VPP_CSC_RGB2YUV_MIN,
+	VPP_CSC_RGB2YUV_SDTV_16_235,
+	VPP_CSC_RGB2YUV_HDTV_0_255,
+	VPP_CSC_RGB2YUV_HDTV_16_235,
+	VPP_CSC_RGB2YUV_JFIF_0_255,
+	VPP_CSC_RGB2YUV_SMPTE170M,
+	VPP_CSC_RGB2YUV_SMPTE240M,
+	VPP_CSC_RGB2YUV_JFIF_VT1625,
+	VPP_CSC_MAX,
+	VPP_CSC_BYPASS
+};
+#define vpp_csc_t enum vpp_csc_s
+
+enum vpp_reglevel_s {
+	VPP_REG_LEVEL_1,
+	VPP_REG_LEVEL_2,
+	VPP_REG_LEVEL_MAX,
+};
+#define vpp_reglevel_t enum vpp_reglevel_s
+
+enum vpp_datawidht_s {
+	VPP_DATAWIDHT_12,
+	VPP_DATAWIDHT_24,
+	VPP_DATAWIDHT_MAX,
+};
+#define vpp_datawidht_t enum vpp_datawidht_s
+
+enum vpp_tvsys_s {
+	VPP_TVSYS_NTSC,
+	VPP_TVSYS_NTSCJ,
+	VPP_TVSYS_NTSC443,
+	VPP_TVSYS_PAL,
+	VPP_TVSYS_PALM,
+	VPP_TVSYS_PAL60,
+	VPP_TVSYS_PALN,
+	VPP_TVSYS_PALNC,
+	VPP_TVSYS_720P,
+	VPP_TVSYS_1080I,
+	VPP_TVSYS_1080P,
+	VPP_TVSYS_MAX
+};
+#define vpp_tvsys_t enum vpp_tvsys_s
+
+enum vpp_tvconn_s {
+	VPP_TVCONN_YCBCR,
+	VPP_TVCONN_SCART,
+	VPP_TVCONN_YPBPR,
+	VPP_TVCONN_VGA,
+	VPP_TVCONN_SVIDEO,
+	VPP_TVCONN_CVBS,
+	VPP_TVCONN_MAX
+};
+#define vpp_tvconn_t enum vpp_tvconn_s
+
+#define VPP_OPT_INTERLACE		0x01
+#define VPP_DVO_SYNC_POLAR_HI		0x08
+#define VPP_DVO_VSYNC_POLAR_HI		0x10
+
+struct vpp_clock_s {
+	int read_cycle;
+
+	unsigned int total_pixel_of_line;
+	unsigned int begin_pixel_of_active;
+	unsigned int end_pixel_of_active;
+
+	unsigned int total_line_of_frame;
+	unsigned int begin_line_of_active;
+	unsigned int end_line_of_active;
+
+	unsigned int hsync;
+	unsigned int vsync;
+	unsigned int line_number_between_VBIS_VBIE;
+	unsigned int line_number_between_PVBI_VBIS;
+};
+#define vpp_clock_t struct vpp_clock_s
+
+struct vpp_scale_s {
+	vdo_framebuf_t src_fb;
+	vdo_framebuf_t dst_fb;
+};
+#define vpp_scale_t struct vpp_scale_s
+
+struct vpp_scale_overlap_s {
+	int mode;
+	vdo_framebuf_t src_fb;
+	vdo_framebuf_t src2_fb;
+	vdo_framebuf_t dst_fb;
+};
+#define vpp_scale_overlap_t struct vpp_scale_overlap_s
+
+struct vpp_overlap_s {
+	unsigned int alpha_src_type:2; /* 0-mif1,1-mif2,2-fix */
+	unsigned int alpha_src:8;
+	unsigned int alpha_dst_type:2; /* 0-mif1,1-mif2,2-fix */
+	unsigned int alpha_dst:8;
+	unsigned int alpha_swap:1; /* 0-(alpha,1-alpha),1:(1-alpha,alpha) */
+	unsigned int color_key_from:2; /* 0-RMIF1,1-RMIF2 */
+	unsigned int color_key_comp:2; /* 0-888,1-777,2-666,3-555 */
+	unsigned int color_key_mode:3; /* (Non-Hit,Hit):0/1-(alpha,alpha),
+				2-(alpha,pix1), 3-(pix1,alpha),4-(alpha,pix2),
+				5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */
+	unsigned int reserved:4;
+	unsigned int color_key; /* ARGB */
+};
+#define vpp_overlap_t struct vpp_overlap_s
+
+#define VPP_VOUT_STS_REGISTER	0x01
+#define VPP_VOUT_STS_ACTIVE	0x02
+#define VPP_VOUT_STS_PLUGIN	0x04
+#define VPP_VOUT_STS_EDID	0x08
+#define VPP_VOUT_STS_BLANK	0x10
+#define VPP_VOUT_STS_POWERDN	0x20
+#define VPP_VOUT_STS_CONTENT_PROTECT 0x40
+#define VPP_VOUT_STS_FB		0xF00
+#define VPP_VOUT_ARG_NUM 5
+struct vpp_vout_info_s {
+	enum vpp_vout_s mode[VPP_VOUT_ARG_NUM]; 
+	unsigned int status[VPP_VOUT_ARG_NUM];
+};
+#define vpp_vout_info_t struct vpp_vout_info_s
+
+struct vpp_vout_parm_s {
+	int num;
+	int arg;
+};
+#define vpp_vout_parm_t struct vpp_vout_parm_s
+
+#define VOUT_OPT_BLANK		BIT(8)
+
+#define VPP_CAP_DUAL_DISPLAY	BIT(0)
+struct vpp_cap_s {
+	unsigned int chip_id;
+	unsigned int version;
+	unsigned int resx_max;
+	unsigned int resy_max;
+	unsigned int pixel_clk;
+	unsigned int module;
+	unsigned int option;
+};
+#define vpp_cap_t struct vpp_cap_s
+
+struct vpp_i2c_s {
+	unsigned int addr;
+	unsigned int index;
+	unsigned int val;
+};
+#define vpp_i2c_t struct vpp_i2c_s
+
+struct vpp_mod_fbinfo_s {
+	vpp_mod_t mod;
+	int read;
+	vdo_framebuf_t fb;
+};
+#define vpp_mod_fbinfo_t struct vpp_mod_fbinfo_s
+
+struct vpp_vmode_parm_s {
+	unsigned int resx;
+	unsigned int resy;
+	unsigned int fps;
+	unsigned int option;
+};
+#define vpp_vmode_parm_t struct vpp_vmode_parm_s
+
+#define VPP_VOUT_VMODE_NUM	20
+struct vpp_vout_vmode_s {
+	vpp_vout_t mode;
+	int num;
+	vpp_vmode_parm_t parm[VPP_VOUT_VMODE_NUM];
+};
+#define vpp_vout_vmode_t struct vpp_vout_vmode_s
+
+struct vpp_vout_edid_s {
+	vpp_vout_t mode;
+	int size;
+	char *buf;
+};
+#define vpp_vout_edid_t struct vpp_vout_edid_s
+
+struct vpp_vout_cp_info_s {
+	int num;
+	unsigned int bksv[2];
+};
+#define vpp_vout_cp_info_t struct vpp_vout_cp_info_s
+
+#define VPP_VOUT_CP_NUM		336
+struct vpp_vout_cp_key_s {
+	char key[VPP_VOUT_CP_NUM];
+};
+#define vpp_vout_cp_key_t struct vpp_vout_cp_key_s
+
+struct vpp_mod_parm_t {
+	vpp_mod_t mod;
+	int read;
+	unsigned int parm;
+};
+
+#define VPPIO_MAGIC		'f'
+
+/* VPP common ioctl command */
+#define VPPIO_VPP_BASE		0x0
+#define VPPIO_VPPGET_INFO _IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 0, vpp_cap_t)
+#define VPPIO_VPPSET_INFO _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 0, vpp_cap_t)
+#define VPPIO_I2CSET_BYTE _IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 1, vpp_i2c_t)
+#define VPPIO_I2CGET_BYTE _IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 1, vpp_i2c_t)
+#define VPPIO_MODSET_CSC \
+	_IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 2, struct vpp_mod_parm_t)
+#define VPPIO_MODULE_FBINFO \
+	_IOWR(VPPIO_MAGIC, VPPIO_VPP_BASE + 6, vpp_mod_fbinfo_t)
+#define VPPIO_STREAM_ENABLE	_IO(VPPIO_MAGIC, VPPIO_VPP_BASE + 12)
+#define VPPIO_STREAM_GETFB \
+	_IOR(VPPIO_MAGIC, VPPIO_VPP_BASE + 13, vdo_framebuf_t)
+#define VPPIO_STREAM_PUTFB \
+	_IOW(VPPIO_MAGIC, VPPIO_VPP_BASE + 13, vdo_framebuf_t)
+#define VPPIO_MULTIVD_ENABLE _IO(VPPIO_MAGIC, VPPIO_VPP_BASE + 15)
+
+/* VOUT ioctl command */
+#define VPPIO_VOUT_BASE		0x10
+#define VPPIO_VOGET_INFO _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 0, vpp_vout_info_t)
+#define VPPIO_VOGET_HDMI_3D \
+	_IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 1, struct vpp_vout_parm_s)
+#define VPPIO_VOUT_VMODE \
+	_IOWR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 7, vpp_vout_vmode_t)
+#define VPPIO_VOGET_EDID _IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 8, vpp_vout_edid_t)
+#define VPPIO_VOGET_CP_INFO \
+	_IOR(VPPIO_MAGIC, VPPIO_VOUT_BASE + 9, vpp_vout_cp_info_t)
+#define VPPIO_VOSET_CP_KEY \
+	_IOW(VPPIO_MAGIC, VPPIO_VOUT_BASE + 10, vpp_vout_cp_key_t)
+#define VPPIO_VOSET_AUDIO_PASSTHRU	_IO(VPPIO_MAGIC, VPPIO_VOUT_BASE + 11)
+#define VPPIO_VOSET_VIRTUAL_FBDEV	_IO(VPPIO_MAGIC, VPPIO_VOUT_BASE + 13)
+
+/* SCL ioctl command */
+#define VPPIO_SCL_BASE		0x60
+#define VPPIO_SCL_SCALE	_IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 0, vpp_scale_t)
+#define VPPIO_SCL_SCALE_ASYNC \
+	_IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 2, vpp_scale_t)
+#define VPPIO_SCL_SCALE_FINISH	_IO(VPPIO_MAGIC, VPPIO_SCL_BASE + 3)
+#define VPPIO_SCLSET_OVERLAP \
+	_IOW(VPPIO_MAGIC, VPPIO_SCL_BASE + 4, vpp_overlap_t)
+#define VPPIO_SCL_SCALE_OVERLAP	\
+	_IOWR(VPPIO_MAGIC, VPPIO_SCL_BASE + 5, vpp_scale_overlap_t)
+
+#define VPPIO_MAX		0x70
+#endif /* COM_VPP_H */
diff --git a/drivers/video/wmt/dev-cec.c b/drivers/video/wmt/dev-cec.c
new file mode 100755
index 00000000..84105bd0
--- /dev/null
+++ b/drivers/video/wmt/dev-cec.c
@@ -0,0 +1,488 @@
+/*++
+ * linux/drivers/video/wmt/dev-cec.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define DEV_CEC_C
+
+/* #define DEBUG */
+#include <linux/platform_device.h>
+#include <linux/major.h>
+#include <linux/cdev.h>
+#include <linux/netlink.h>
+#include <net/sock.h>
+#include "cec.h"
+#include "vpp.h"
+
+#define DRIVER_NAME "wmt-cec"
+
+#define TXNORSP	0x8000 /* Tx no response interrupt */
+#define TXLSARB	0x2000 /* Tx lose arbitration */
+#define TXDONE	0x0100 /* Tx done */
+#define RXFAIL	0x0002 /* Rx fail, details in Rx10 */
+#define RXDONE	0x0001 /* Rx done */
+
+#define MAX_RETRY 3
+#define MAX_TIMEOUT 5000
+
+static int tx_state;
+
+static struct cdev *wmt_cec_cdev;
+static DEFINE_SEMAPHORE(wmt_cec_sem);
+
+struct wmt_cec_msg recv_msg;
+static void wmt_cec_do_rx_notify(struct work_struct *ptr)
+{
+	vpp_netlink_notify(USER_PID, DEVICE_RX_DATA, (int)&recv_msg);
+}
+DECLARE_DELAYED_WORK(wmt_cec_rx_work, wmt_cec_do_rx_notify);
+
+
+/* receive message interrupt handling */
+static void wmt_cec_do_recv(void)
+{
+	memset(&recv_msg, 0, sizeof(recv_msg));
+	/* get received data */
+	recv_msg.msglen = wmt_cec_rx_data(recv_msg.msgdata);
+	if (recv_msg.msglen > MAX_MSG_BYTE)
+		recv_msg.msglen = MAX_MSG_BYTE;
+
+	DBGMSG("read a received byte! msglen: %d\n", recv_msg.msglen);
+
+	/* clear receive blockage */
+
+	/* notify AP the received message, let AP decide what to response */
+	schedule_delayed_work(&wmt_cec_rx_work, HZ / 10);
+}
+
+/* check if logic address is valid */
+static int bvalidaddr(char addr)
+{
+	if (addr > 15)
+		return 0;
+	return 1;
+}
+
+/* make sure cec line is not busy */
+static int tx_get_cecline(void)
+{
+	int timeout = 400;
+
+	while (timeout-- > 0) {
+		/* if not busy */
+		if (1)
+			return 0;
+		msleep(1);
+	}
+	return -ETIMEDOUT;
+}
+
+/* transfer a time*/
+DECLARE_COMPLETION(txcomp);
+static int wmt_cec_do_xfer_one(char *msgdata, int msglen)
+{
+	int ret;
+	unsigned long  jiffies;
+
+	ret = tx_get_cecline();
+	if (ret != 0)
+		ret = -EAGAIN;
+
+	wmt_cec_tx_data(msgdata, msglen);
+
+	jiffies = msecs_to_jiffies((unsigned int)MAX_TIMEOUT);
+	jiffies = wait_for_completion_timeout(&txcomp, jiffies);
+	if (jiffies == 0)
+		return -EAGAIN;
+
+	if (tx_state == TXLSARB)
+		return -EAGAIN;
+
+	return tx_state;
+}
+
+/* transfer a message, including retransmission if needed*/
+static int wmt_cec_do_xfer(char *msgdata, int msglen)
+{
+	int retry;
+	int ret;
+	char srcaddr, tgtaddr;
+
+	if (msglen < 1) {
+		DPRINT("[CEC] xfer: invalid message, msglen is less than 1.\n");
+		return -1;
+	}
+
+	srcaddr = (msgdata[0] & 0xf0) >> 4;
+	tgtaddr = (msgdata[0] & 0x0f);
+	if (!bvalidaddr(srcaddr) || !bvalidaddr(tgtaddr)) {
+		DPRINT("[CEC] xfer: invalid logic address in msg data.\n");
+		return -1;
+	}
+
+	for (retry = 0; retry < MAX_RETRY; retry++) {
+		ret = wmt_cec_do_xfer_one(msgdata, msglen);
+		if (ret != -EAGAIN)
+			goto out;
+		DPRINT("[CEC] Retrying transmission (%d)\n", retry);
+		udelay(100);
+	}
+	return -EAGAIN;
+out:
+	/* if polling message ret is no-response, set logical address register,
+		and enable slave mode */
+	if (srcaddr == tgtaddr && msglen == 1) {
+		if (ret == TXNORSP) {
+			DBGMSG("[CEC] logic addr register is 0x%x\n", tgtaddr);
+			return 0;
+		} else
+			return -1;
+	} else if (ret == TXDONE)
+		return 0;
+	else
+		return -1;
+}
+
+/* irq handling function */
+irqreturn_t wmt_cec_do_irq(int irq, void *dev_id)
+{
+	int sts;
+
+	sts = wmt_cec_get_int();
+	wmt_cec_clr_int(sts);
+	if (sts & BIT0) { /* tx done */
+		DBGMSG("[CEC] write ok int\n");
+		complete(&txcomp);
+		tx_state = TXDONE;
+	}
+	if (sts & BIT1) { /* rx done */
+		DBGMSG("[CEC] read ok int\n");
+		wmt_cec_do_recv();
+	}
+	if (sts & BIT2) { /* rx error */
+		DBGMSG("[CEC] read error int\n");
+	}
+	if (sts & BIT3) { /* tx arb fail */
+		DBGMSG("[CEC] wr arb fail int\n");
+		complete(&txcomp);
+		tx_state = TXLSARB;
+	}
+	if (sts & BIT4) { /* tx no ack */
+/*		DBGMSG("[CEC] write no ack int(addr not match)\n"); */
+		complete(&txcomp);
+		tx_state = TXNORSP;
+	}
+	return IRQ_HANDLED;
+}
+
+static int wmt_cec_open(
+	struct inode *inode,
+	struct file *filp
+)
+{
+	int ret = 0;
+
+	DBGMSG("[CEC] wmt_cec_open\n");
+
+	down(&wmt_cec_sem);
+	wmt_cec_rx_enable(1);
+	up(&wmt_cec_sem);
+	return ret;
+} /* End of videodecoder_open() */
+
+static int wmt_cec_release(
+	struct inode *inode,
+	struct file *filp
+)
+{
+	int ret = 0;
+
+	DBGMSG("[CEC] wmt_cec_release\n");
+
+	down(&wmt_cec_sem);
+	wmt_cec_rx_enable(0);
+	up(&wmt_cec_sem);
+	return ret;
+} /* End of videodecoder_release() */
+
+static long wmt_cec_ioctl(
+	struct file *filp,
+	unsigned int cmd,
+	unsigned long arg
+)
+{
+	int ret = -EINVAL;
+
+	DBGMSG("[CEC] wmt_cec_ioctl 0x%x,0x%x\n", cmd, arg);
+
+	/* check type and number, if fail return ENOTTY */
+	if (_IOC_TYPE(cmd) != WMT_CEC_IOC_MAGIC)
+		return -ENOTTY;
+	if (_IOC_NR(cmd) > WMT_CEC_IOC_MAXNR)
+		return -ENOTTY;
+
+	/* check argument area */
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ret = !access_ok(VERIFY_WRITE,
+			(void __user *) arg, _IOC_SIZE(cmd));
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		ret = !access_ok(VERIFY_READ,
+			(void __user *) arg, _IOC_SIZE(cmd));
+	else
+		ret = 0;
+
+	if (ret)
+		return -EFAULT;
+
+	down(&wmt_cec_sem);
+	switch (cmd) {
+	case CECIO_TX_DATA:
+		{
+		struct wmt_cec_msg msg;
+
+		ret = copy_from_user((void *) &msg, (const void *)arg,
+					sizeof(struct wmt_cec_msg));
+		wmt_cec_do_xfer(msg.msgdata, msg.msglen);
+		}
+		break;
+	case CECIO_TX_LOGADDR:
+		wmt_cec_set_logical_addr((arg & 0xFF00) >> 8, arg & 0xFF, 1);
+		break;
+	case CECIO_RX_PHYADDR:
+		{
+		wmt_phy_addr_t parm;
+
+		parm.phy_addr = edid_get_hdmi_phy_addr();
+		ret = copy_to_user((void *)arg, (void *)&parm,
+					sizeof(wmt_phy_addr_t));
+		}
+		break;
+	default:
+		DBGMSG("[CEC] *W* wmt_cec_ioctl cmd 0x%x\n", cmd);
+		break;
+	}
+	up(&wmt_cec_sem);
+	return ret;
+} /* End of videodecoder_ioctl() */
+
+static int wmt_cec_mmap(
+	struct file *filp,
+	struct vm_area_struct *vma
+)
+{
+	int ret = -EINVAL;
+	down(&wmt_cec_sem);
+	up(&wmt_cec_sem);
+	return ret;
+}
+
+static ssize_t wmt_cec_read(
+	struct file *filp,
+	char __user *buf,
+	size_t count,
+	loff_t *f_pos
+)
+{
+	ssize_t ret = 0;
+	down(&wmt_cec_sem);
+	up(&wmt_cec_sem);
+	return ret;
+} /* videodecoder_read */
+
+static ssize_t wmt_cec_write(
+	struct file *filp,
+	const char __user *buf,
+	size_t count,
+	loff_t *f_pos
+)
+{
+	ssize_t ret = 0;
+	down(&wmt_cec_sem);
+	up(&wmt_cec_sem);
+	return ret;
+} /* End of videodecoder_write() */
+
+const struct file_operations wmt_cec_fops = {
+	.owner          = THIS_MODULE,
+	.open           = wmt_cec_open,
+	.release        = wmt_cec_release,
+	.read           = wmt_cec_read,
+	.write          = wmt_cec_write,
+	.unlocked_ioctl = wmt_cec_ioctl,
+	.mmap           = wmt_cec_mmap,
+};
+
+static int __init wmt_cec_probe
+(
+	struct platform_device *dev /*!<; // a pointer to struct device */
+)
+{
+	dev_t dev_no;
+	int ret;
+
+	DBGMSG("[CEC] Enter wmt_cec_probe\n");
+
+	wmt_cec_init_hw();
+	wmt_cec_set_logical_addr(4, 0xf, 1); /* default set boardcast address */
+	wmt_cec_rx_enable(0);
+	/* wmt_cec_enable_loopback(1); */
+
+	dev_no = MKDEV(CEC_MAJOR, 0);
+	ret = register_chrdev_region(dev_no, 1, "wmtcec");
+	if (ret < 0) {
+		DPRINT("can't get %s dev major %d\n", DRIVER_NAME, CEC_MAJOR);
+		return ret;
+	}
+
+	/* register char device */
+	wmt_cec_cdev = cdev_alloc();
+	if (!wmt_cec_cdev) {
+		DPRINT("alloc dev error.\n");
+		return -ENOMEM;
+	}
+
+	cdev_init(wmt_cec_cdev, &wmt_cec_fops);
+	ret = cdev_add(wmt_cec_cdev, dev_no, 1);
+	if (ret) {
+		DPRINT("reg char dev error(%d).\n", ret);
+		cdev_del(wmt_cec_cdev);
+		return ret;
+	}
+
+	if (vpp_request_irq(IRQ_VPP_IRQ20, wmt_cec_do_irq,
+		SA_INTERRUPT, "cec", (void *) 0))
+		DPRINT("*E* request CEC ISR fail\n");
+	cec_regs->int_enable = 0x1f;
+	DBGMSG("[CEC] Exit wmt_cec_probe(0x%x)\n", dev_no);
+	return 0;
+} /* End of wmt_cec_probe */
+
+static int wmt_cec_remove
+(
+	struct platform_device *dev /*!<; // a pointer point to struct device */
+)
+{
+	return 0;
+} /* End of wmt_cec_remove */
+
+#ifdef CONFIG_PM
+static int wmt_cec_suspend
+(
+	struct platform_device *pDev,	/*!<; // a pointer to struct device */
+	pm_message_t state		/*!<; // suspend state */
+)
+{
+	DPRINT("Enter wmt_cec_suspend\n");
+	wmt_cec_do_suspend();
+	return 0;
+} /* End of wmt_cec_suspend */
+
+static int wmt_cec_resume
+(
+	struct platform_device *pDev	/*!<; // a pointer to struct device */
+)
+{
+	DPRINT("Enter wmt_cec_resume\n");
+	wmt_cec_do_resume();
+	return 0;
+} /* End of wmt_cec_resume */
+#else
+#define wmt_cec_suspend NULL
+#define wmt_cec_resume NULL
+#endif
+
+/***************************************************************************
+	device driver struct define
+****************************************************************************/
+static struct platform_driver wmt_cec_driver = {
+	.driver.name    = "wmtcec", /* equal to platform device name. */
+	.driver.bus     = &platform_bus_type,
+	.probe          = wmt_cec_probe,
+	.remove         = wmt_cec_remove,
+	.suspend        = wmt_cec_suspend,
+	.resume         = wmt_cec_resume,
+};
+
+/***************************************************************************
+	platform device struct define
+****************************************************************************/
+static u64 wmt_cec_dma_mask = 0xffffffffUL;
+static struct platform_device wmt_cec_device = {
+	.name   = "wmtcec",
+	.dev    = {
+		.dma_mask = &wmt_cec_dma_mask,
+		.coherent_dma_mask = ~0,
+	},
+#if 0
+	.id     = 0,
+	.dev    = {
+		.release = wmt_cec_platform_release,
+	},
+	.num_resources  = 0,    /* ARRAY_SIZE(wmt_cec_resources), */
+	.resource       = NULL, /* wmt_cec_resources, */
+#endif
+};
+
+static int __init wmt_cec_init(void)
+{
+	int ret;
+	char buf[100];
+	int varlen = 100;
+	unsigned int cec_enable = 0;
+
+	if (wmt_getsyspara("wmt.display.cec", buf, &varlen) == 0)
+		vpp_parse_param(buf, &cec_enable, 1, 0);
+
+	if (cec_enable == 0)
+		return 0;
+
+	DBGMSG(KERN_ALERT "Enter wmt_cec_init\n");
+
+	ret = platform_driver_register(&wmt_cec_driver);
+	if (!ret) {
+		ret = platform_device_register(&wmt_cec_device);
+		if (ret)
+			platform_driver_unregister(&wmt_cec_driver);
+	}
+	return ret;
+}
+
+static void __exit wmt_cec_exit(void)
+{
+	dev_t dev_no;
+
+	DBGMSG(KERN_ALERT "Enter wmt_cec_exit\n");
+
+	platform_driver_unregister(&wmt_cec_driver);
+	platform_device_unregister(&wmt_cec_device);
+	dev_no = MKDEV(CEC_MAJOR, 0);
+	unregister_chrdev_region(dev_no, 1);
+	return;
+}
+
+module_init(wmt_cec_init);
+module_exit(wmt_cec_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("WMT CEC driver");
+MODULE_AUTHOR("WMT TECH");
+MODULE_VERSION("1.0.0");
+
diff --git a/drivers/video/wmt/devices/Makefile b/drivers/video/wmt/devices/Makefile
new file mode 100755
index 00000000..da55ae48
--- /dev/null
+++ b/drivers/video/wmt/devices/Makefile
@@ -0,0 +1,26 @@
+#
+# Makefile for the Wonder Media framebuffer driver
+#
+
+# wmt external video device
+obj-$(CONFIG_LCD_WMT) += lcd-oem.o
+obj-$(CONFIG_LCD_CHILIN_LW0700AT9003) += lcd-CHILIN-LW700at9003.o
+obj-$(CONFIG_LCD_INNOLUX_AT070TN83) += lcd-INNOLUX-AT070TN83.o
+obj-$(CONFIG_LCD_AUO_A080SN01) += lcd-AUO-A080SN01.o
+obj-$(CONFIG_LCD_EKING_EK08009) += lcd-EKING-EK08009-70135.o
+obj-$(CONFIG_LCD_HANNSTAR_HSD101PFW2) += lcd-HANNSTAR-HSD101PFW2.o
+obj-y += lcd-lvds-1024x600.o
+obj-y += lcd-gl5001w.o
+#obj-y += cs8556.o
+#obj-y += lcd-b079xan01.o
+obj-y += lcd-spi.o
+obj-y += lcd-setup.o
+
+obj-$(CONFIG_LCD_WMT) += lcd.o
+#obj-$(CONFIG_HDMI_SIL902X_WMT) += sil902x.o
+#obj-$(CONFIG_HDCP_SIL902X_WMT) += sil9024/
+obj-$(CONFIG_DVI_VT1632_WMT) += vt1632.o
+obj-$(CONFIG_TV_VT1625_WMT) += vt1625.o
+#obj-$(CONFIG_HDMI_CAT6610_WMT) += cat6612.o cat6610/
+#obj-$(CONFIG_HDMI_AD9389_WMT) += ad9389.o
+#obj-$(CONFIG_EXTTV_ADV7393_WMT) += ad7393.o
diff --git a/drivers/video/wmt/devices/cs8556.c b/drivers/video/wmt/devices/cs8556.c
new file mode 100755
index 00000000..72097685
--- /dev/null
+++ b/drivers/video/wmt/devices/cs8556.c
@@ -0,0 +1,627 @@
+/*++
+ * linux/drivers/video/wmt/cs8556.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+/*********************************************************************
+* REVISON HISTORY
+*
+* VERSION	| DATE		| AUTHORS	  | DESCRIPTION
+* 1.0		| 2013/08/24	| Howay Huo	      | First Release
+**********************************************************************/
+
+#define CS8556_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include <linux/i2c.h>
+#include <mach/hardware.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include "../vout.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  VT1632_XXXX  xxxx    *//*Example*/
+
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VT1632_XXXX    1     *//*Example*/
+#define CS8556_ADDR 0x3d
+#define CS8556_NAME          "CS8556"
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx vt1632_xxx_t; *//*Example*/
+struct avdetect_gpio_t {
+	unsigned int flag;
+	unsigned int gpiono;
+	unsigned int act;
+};
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  vt1632_xxx;        *//*Example*/
+static int s_cs8556_ready;
+static int s_cs8556_init;
+static struct i2c_client *s_cs8556_client;
+static enum vout_tvformat_t s_tvformat = TV_MAX;
+static int s_irq_init;
+static struct avdetect_gpio_t s_avdetect_gpio = {0, WMT_PIN_GP0_GPIO5, 1};
+
+static unsigned char s_CS8556_Original_Offset0[] = {
+	0xF0, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
+	0x80, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x01,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static unsigned char s_RGB888_To_PAL_Offset0[] = {
+	0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x5F, 0x03, 0x3F, 0x00, 0x7D, 0x00, 0x53, 0x03,
+	0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x70, 0x02, 0x04, 0x00, 0x2E, 0x00, 0x62, 0x02,
+	0x00, 0x00, 0x84, 0x00, 0x2B, 0x00, 0x36, 0x00,
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xBF, 0x06, 0x7F, 0x00, 0xFE, 0x00, 0xA4, 0x06,
+	0x00, 0x00, 0x2D, 0x11, 0x3C, 0x01, 0x3A, 0x01,
+	0x70, 0x02, 0x04, 0x00, 0x12, 0x00, 0x34, 0x01,
+	0x00, 0x00, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00,
+	0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x41, 0x18, 0x09, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+	0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+	0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+	0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
+	0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x24, 0x1A, 0x00, 0x01, 0x03, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x01, 0xA4, 0x06, 0x0B, 0x00, 0x07, 0x01,
+	0xF0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x40, 0x01
+};
+
+static unsigned char s_RGB888_To_NTSC_Offset0[] = {
+	0x01, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00,
+	0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x59, 0x03, 0x3D, 0x00, 0x7E, 0x00, 0x49, 0x03,
+	0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+	0x0C, 0x02, 0x05, 0x00, 0x21, 0x00, 0x03, 0x02,
+	0x00, 0x00, 0x7A, 0x00, 0x23, 0x00, 0x16, 0x00,
+	0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xB3, 0x06, 0x7F, 0x00, 0x00, 0x01, 0xA4, 0x06,
+	0x00, 0x00, 0x05, 0x50, 0x00, 0x01, 0x07, 0x01,
+	0x0C, 0x02, 0x02, 0x00, 0x12, 0x00, 0x07, 0x01,
+	0x00, 0x00, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00,
+	0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x41, 0x18, 0x09, 0x00, 0x00, 0x00, 0x02,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00,
+	0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00,
+	0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+	0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
+	0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
+	0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x01, 0x24, 0x1A, 0x00, 0x01, 0x03, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x04, 0x01, 0xA4, 0x06, 0x0B, 0x00, 0x07, 0x01,
+	0xF0, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vt1632_xxx(void); *//*Example*/
+static int I2CMultiPageRead(unsigned char maddr, unsigned char page,
+	unsigned char saddr, int number, unsigned char *value)
+{
+	int ret;
+	unsigned char wbuf[2];
+	struct i2c_msg rd[2];
+
+	wbuf[0] = page;
+	wbuf[1] = saddr;
+
+	rd[0].addr  = maddr;
+	rd[0].flags = 0;
+	rd[0].len   = 2;
+	rd[0].buf   = wbuf;
+
+	rd[1].addr  = maddr;
+	rd[1].flags = I2C_M_RD;
+	rd[1].len   = number;
+	rd[1].buf   = value;
+
+	ret = i2c_transfer(s_cs8556_client->adapter, rd, ARRAY_SIZE(rd));
+
+	if (ret != ARRAY_SIZE(rd)) {
+		DBG_ERR("fail\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int I2CMultiPageWrite(unsigned char maddr, unsigned char page,
+	unsigned char saddr, int number, unsigned char *value)
+{
+	int ret;
+	unsigned char *pbuf;
+	struct i2c_msg wr[1];
+
+	pbuf = kmalloc(number + 2, GFP_KERNEL);
+	if (!pbuf) {
+		DBG_ERR("alloc memory fail\n");
+		return -1;
+	}
+
+	*pbuf = page;
+	*(pbuf + 1) = saddr;
+
+	memcpy(pbuf + 2, value, number);
+
+	wr[0].addr  = maddr;
+	wr[0].flags = 0;
+	wr[0].len   = number + 2;
+	wr[0].buf   = pbuf;
+
+	ret = i2c_transfer(s_cs8556_client->adapter, wr, ARRAY_SIZE(wr));
+
+	if (ret != ARRAY_SIZE(wr)) {
+		DBG_ERR("fail\n");
+		kfree(pbuf);
+		return -1;
+	}
+
+	kfree(pbuf);
+	return 0 ;
+}
+
+/************************ i2c device struct definition ************************/
+static int __devinit cs8556_i2c_probe(struct i2c_client *i2c,
+	const struct i2c_device_id *id)
+{
+	DBGMSG("cs8556_i2c_probe\n");
+
+	return 0;
+}
+
+static int __devexit cs8556_i2c_remove(struct i2c_client *client)
+{
+	DBGMSG("cs8556_i2c_remove\n");
+
+	return 0;
+}
+
+
+static const struct i2c_device_id cs8556_i2c_id[] = {
+	{CS8556_NAME, 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, cs8556_i2c_id);
+
+static struct i2c_board_info __initdata cs8556_i2c_board_info[] = {
+	{
+		I2C_BOARD_INFO(CS8556_NAME, CS8556_ADDR),
+	},
+};
+
+static struct i2c_driver cs8556_i2c_driver = {
+	.driver = {
+		.name = CS8556_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = cs8556_i2c_probe,
+	.remove = __devexit_p(cs8556_i2c_remove),
+	.id_table = cs8556_i2c_id,
+};
+
+/*----------------------- Function Body --------------------------------------*/
+static void avdetect_irq_enable(void)
+{
+	wmt_gpio_unmask_irq(s_avdetect_gpio.gpiono);
+}
+
+static void avdetect_irq_disable(void)
+{
+	wmt_gpio_mask_irq(s_avdetect_gpio.gpiono);
+}
+
+int avdetect_irq_hw_init(int resume)
+{
+	int ret;
+
+	if (!resume) {
+		ret = gpio_request(s_avdetect_gpio.gpiono,
+			"avdetect irq"); /* enable gpio */
+		if (ret < 0) {
+			DBG_ERR("gpio(%d) request fail for avdetect irq\n",
+				s_avdetect_gpio.gpiono);
+			return ret;
+		}
+	} else
+		gpio_re_enabled(s_avdetect_gpio.gpiono); /* re-enable gpio */
+
+	gpio_direction_input(s_avdetect_gpio.gpiono); /* gpio input */
+
+	/* enable pull and pull-up */
+	wmt_gpio_setpull(s_avdetect_gpio.gpiono, WMT_GPIO_PULL_UP);
+
+	/* disable interrupt */
+	wmt_gpio_mask_irq(s_avdetect_gpio.gpiono);
+
+	/* rise edge and clear interrupt */
+	wmt_gpio_set_irq_type(s_avdetect_gpio.gpiono, IRQ_TYPE_EDGE_BOTH);
+
+	return 0;
+}
+
+/*
+static void avdetect_irq_hw_free(void)
+{
+	gpio_free(AVDETECT_IRQ_PIN);
+
+}
+*/
+
+static irqreturn_t avdetect_irq_handler(int irq, void *dev_id)
+{
+	/* DPRINT("avdetect_irq_handler\n"); */
+
+	if (!gpio_irqstatus(s_avdetect_gpio.gpiono))
+		return IRQ_NONE;
+
+	wmt_gpio_ack_irq(s_avdetect_gpio.gpiono);  /* clear interrupt */
+
+	/* DPRINT("cvbs hotplug interrupt\n"); */
+	if (!is_gpio_irqenable(s_avdetect_gpio.gpiono)) {
+		/* pr_err("avdetect irq is disabled\n"); */
+		return IRQ_HANDLED;
+	} else
+		return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t avdetect_irq_thread(int irq, void *dev)
+{
+	/* DPRINT(cvbs_hotplug_irq_thread\n"); */
+
+	if (s_avdetect_gpio.act == 1) {
+		if (gpio_get_value(s_avdetect_gpio.gpiono))
+			DPRINT("av plug in\n");
+		else
+			DPRINT("av plug out\n");
+	} else {
+		if (gpio_get_value(s_avdetect_gpio.gpiono))
+			DPRINT("av plug out\n");
+		else
+			DPRINT("av plug in\n");
+	}
+
+	return IRQ_HANDLED;
+}
+
+int cs8556_check_plugin(int hotplug)
+{
+	return 1;
+}
+
+int cs8556_init(struct vout_t *vo)
+{
+	int ret;
+	char buf[40] = {0};
+	int varlen = 40;
+	int no = 1; /* default i2c1 */
+	int num;
+	unsigned char rbuf[256] = {0};
+	struct i2c_adapter *adapter = NULL;
+
+	DPRINT("cs8556_init\n");
+
+	if (s_tvformat == TV_MAX) {
+		if (wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) {
+			if (!strnicmp(buf, "PAL", 3))
+				s_tvformat = TV_PAL;
+			else if (!strnicmp(buf, "NTSC", 4))
+				s_tvformat = TV_NTSC;
+			else
+				s_tvformat = TV_UNDEFINED;
+		} else
+			s_tvformat = TV_UNDEFINED;
+	}
+
+	if (s_tvformat == TV_UNDEFINED)
+		goto err0;
+
+	if (!s_cs8556_init) {
+		if (wmt_getsyspara("wmt.cs8556.i2c", buf, &varlen) == 0) {
+			if (strlen(buf) > 0)
+				no = buf[0] - '0';
+		}
+
+		adapter = i2c_get_adapter(no);
+		if (adapter == NULL) {
+			DBG_ERR("Can't get i2c adapter,client address error\n");
+			goto err0;
+		}
+
+		s_cs8556_client =
+			i2c_new_device(adapter, cs8556_i2c_board_info);
+		if (s_cs8556_client == NULL) {
+			DBG_ERR("allocate i2c client failed\n");
+			goto err0;
+		}
+
+		i2c_put_adapter(adapter);
+
+		ret = i2c_add_driver(&cs8556_i2c_driver);
+		if (ret != 0) {
+			DBG_ERR("Failed register CS8556 I2C driver: %d\n", ret);
+			goto err1;
+		}
+
+		if (wmt_getsyspara("wmt.io.avdetect", buf, &varlen) == 0) {
+			num = sscanf(buf, "%d:%d:%d", &s_avdetect_gpio.flag,
+				&s_avdetect_gpio.gpiono, &s_avdetect_gpio.act);
+
+			if (num != 3)
+				DBG_ERR("wmt.io.avdetect err. num = %d\n", num);
+			else {
+				if (s_avdetect_gpio.gpiono > 19)
+					DBG_ERR("invalid avdetect gpio : %d\n",
+					s_avdetect_gpio.gpiono);
+				else {
+					ret = avdetect_irq_hw_init(0);
+					if (!ret) {
+						ret = request_threaded_irq(
+							IRQ_GPIO,
+							avdetect_irq_handler,
+							avdetect_irq_thread,
+							IRQF_SHARED,
+							CS8556_NAME,
+							s_cs8556_client);
+
+						if (ret)
+							DBG_ERR("irq req %d\n",
+							ret);
+						else {
+							s_irq_init = 1;
+							DPRINT("avdetect irq");
+							DPRINT("req success\n");
+						}
+					}
+				}
+			}
+		}
+
+		s_cs8556_init = 1;
+	} else {
+		if (s_irq_init)
+			avdetect_irq_hw_init(1);
+	}
+
+	ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+	if (ret) {
+		DBG_ERR("I2C address 0x%02X is not found\n", CS8556_ADDR);
+		goto err0;
+	}
+
+	switch (s_tvformat) {
+	case TV_PAL:
+		ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256,
+			s_RGB888_To_PAL_Offset0);
+		if (ret) {
+			DBG_ERR("PAL init fail\n");
+			goto err0;
+		}
+		break;
+	case TV_NTSC:
+		ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 256,
+			s_RGB888_To_NTSC_Offset0);
+		if (ret) {
+			DBG_ERR("NTSC init fail\n");
+			goto err0;
+		}
+		break;
+	default:
+		goto err0;
+		break;
+	}
+
+	if (s_irq_init)
+		avdetect_irq_enable();
+
+	s_cs8556_ready = 1;
+
+	return 0;
+#if 0
+err3:
+	cvbs_hotplug_irq_disable();
+	free_irq(IRQ_GPIO, s_cs8556_client);
+	cvbs_hotplug_irq_hw_free();
+err2:
+	i2c_del_driver(&cs8556_i2c_driver);
+#endif
+err1:
+	i2c_unregister_device(s_cs8556_client);
+err0:
+	s_cs8556_ready = 0;
+	return -1;
+}
+
+static int cs8556_set_mode(unsigned int *option)
+{
+	if (!s_cs8556_ready)
+		return -1;
+
+	return 0;
+}
+
+static void cs8556_set_power_down(int enable)
+{
+	int ret;
+	unsigned char rbuf[256] = {0};
+
+	if (!s_cs8556_ready)
+		return;
+
+	DBGMSG("cs8556_set_power_down(%d)\n", enable);
+
+	if (enable) {
+		ret = I2CMultiPageWrite(CS8556_ADDR, 0x00, 0x00, 5,
+			s_CS8556_Original_Offset0);
+		if (ret)
+			DBG_ERR("I2C write Original_Offset0 fail\n");
+		else {
+			if (s_irq_init)
+				avdetect_irq_disable();
+		}
+	} else {
+		ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+		if (ret) {
+			DBG_ERR("I2C read Offset0 fail\n");
+			return;
+		}
+
+		switch (s_tvformat) {
+		case TV_PAL:
+			if (memcmp(rbuf, s_RGB888_To_PAL_Offset0, 0x50) != 0) {
+				ret = I2CMultiPageWrite(CS8556_ADDR, 0x00,
+					0x00, 256, s_RGB888_To_PAL_Offset0);
+				if (ret)
+					DBG_ERR("I2C write PAL_Offset0 fail\n");
+			}
+			break;
+		case TV_NTSC:
+			if (memcmp(rbuf, s_RGB888_To_NTSC_Offset0, 0x50) != 0) {
+				ret = I2CMultiPageWrite(CS8556_ADDR, 0x00,
+					0x00, 256, s_RGB888_To_NTSC_Offset0);
+				if (ret)
+					DBG_ERR("I2C wr NTSC_Offset0 fail\n");
+			}
+			break;
+		default:
+			break;
+		}
+	}
+}
+
+static int cs8556_config(struct vout_info_t *info)
+{
+	return 0;
+}
+
+static int cs8556_get_edid(char *buf)
+{
+	return -1;
+}
+
+/*
+static int cs8556_interrupt(void)
+{
+	return cs8556_check_plugin(1);
+}
+*/
+
+void cs8556_read(void)
+{
+	int i, ret;
+	unsigned char rbuf[256] = {0};
+
+	ret = I2CMultiPageRead(CS8556_ADDR, 0x00, 0x00, 256, rbuf);
+	if (!ret) {
+		DPRINT("CS8556 Read offset0 data as follows:\n");
+		for (i = 0; i < 256;) {
+			DPRINT("0x%02X,", rbuf[i]);
+			if ((++i) % 16 == 0)
+				DPRINT("\n");
+		}
+	}
+}
+
+int cvbs_is_ready(void)
+{
+	return s_cs8556_ready;
+}
+
+/*----------------------- vout device plugin ---------------------------------*/
+struct vout_dev_t cs8556_vout_dev_ops = {
+	.name = CS8556_NAME,
+	.mode = VOUT_INF_DVI,
+
+	.init = cs8556_init,
+	.set_power_down = cs8556_set_power_down,
+	.set_mode = cs8556_set_mode,
+	.config = cs8556_config,
+	.check_plugin = cs8556_check_plugin,
+	.get_edid = cs8556_get_edid,
+/*	.interrupt = cs8556_interrupt, */
+};
+
+int cs8556_module_init(void)
+{
+	vout_device_register(&cs8556_vout_dev_ops);
+	return 0;
+} /* End of cs8556_module_init */
+module_init(cs8556_module_init);
+/*--------------------End of Function Body -----------------------------------*/
+#undef CS8556_C
diff --git a/drivers/video/wmt/devices/lcd-AUO-A080SN01.c b/drivers/video/wmt/devices/lcd-AUO-A080SN01.c
new file mode 100755
index 00000000..f4602a16
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-AUO-A080SN01.c
@@ -0,0 +1,95 @@
+/*++
+ * linux/drivers/video/wmt/lcd-AUO-A080SN01.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_AUO_A080SN01_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_A080SN01_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_A080SN01_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_a080sn01_initial(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_a080sn01_parm = {
+	.bits_per_pixel = 24,
+	.capability = 0,
+	.vmode = {
+	.name = "AUO A080SN01",
+	.refresh = 60,
+	.xres = 800,
+	.yres = 600,
+	.pixclock = KHZ2PICOS(40000),
+	.left_margin = 88,
+	.right_margin = 40,
+	.upper_margin = 24,
+	.lower_margin = 1,
+	.hsync_len = 128,
+	.vsync_len = 3,
+	.sync = 0,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 162,
+	.height = 121,
+	.initial = lcd_a080sn01_initial,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_a080sn01_initial(void)
+{
+	DPRINT("lcd_a080sn01_initial\n");
+
+	/* TODO */
+}
+
+struct lcd_parm_t *lcd_a080sn01_get_parm(int arg)
+{
+	return &lcd_a080sn01_parm;
+}
+
+int lcd_a080sn01_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_AUO_A080SN01,
+		(void *) lcd_a080sn01_get_parm);
+	return ret;
+} /* End of lcd_a080sn01_init */
+module_init(lcd_a080sn01_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_AUO_A080SN01_C
+
diff --git a/drivers/video/wmt/devices/lcd-CHILIN-LW700at9003.c b/drivers/video/wmt/devices/lcd-CHILIN-LW700at9003.c
new file mode 100755
index 00000000..af9752b3
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-CHILIN-LW700at9003.c
@@ -0,0 +1,104 @@
+/*++
+ * linux/drivers/video/wmt/lcd-CHILIN-LW700at9003.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_CHILIN_LW700AT9003_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_LW700AT9003_XXXX  xxxx    *//*Example*/
+
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_LW700AT9003_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_lw700at9003_power_on(void);
+static void lcd_lw700at9003_power_off(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES ------------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_lw700at9003_parm = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+	.name = "CHILIN LW700AT9003",
+	.refresh = 48,
+	.xres = 800,
+	.yres = 480,
+	.pixclock = KHZ2PICOS(33260),
+	.left_margin = 105,
+	.right_margin = 105,
+	.upper_margin = 23,
+	.lower_margin = 22,
+	.hsync_len = 40,
+	.vsync_len = 5,
+	.sync = 0,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 152,
+	.height = 91,
+	.initial = lcd_lw700at9003_power_on,
+	.uninitial = lcd_lw700at9003_power_off,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_lw700at9003_power_on(void)
+{
+	DPRINT("lcd_lw700at9003_power_on\n");
+	/* TODO */
+}
+
+static void lcd_lw700at9003_power_off(void)
+{
+	DPRINT("lcd_lw700at9003_power_off\n");
+
+	/* TODO */
+}
+
+struct lcd_parm_t *lcd_lw700at9003_get_parm(int arg)
+{
+	lcd_lw700at9003_parm.bits_per_pixel = arg;
+	return &lcd_lw700at9003_parm;
+}
+
+int lcd_lw700at9003_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_CHILIN_LW0700AT9003,
+		(void *) lcd_lw700at9003_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_lw700at9003_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_CHILIN_LW700AT9003_C
diff --git a/drivers/video/wmt/devices/lcd-EKING-EK08009-70135.c b/drivers/video/wmt/devices/lcd-EKING-EK08009-70135.c
new file mode 100755
index 00000000..1d401886
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-EKING-EK08009-70135.c
@@ -0,0 +1,103 @@
+/*++
+ * linux/drivers/video/wmt/lcd-EKING_EK08009-70135.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_EKING_EK08009_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_EK08009_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_EK08009_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_ek08009_power_on(void);
+static void lcd_ek08009_power_off(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_ek08009_parm = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+	.name = "EKING EK08009",
+	.refresh = 60,
+	.xres = 800,
+	.yres = 600,
+	.pixclock = KHZ2PICOS(40000),
+	.left_margin = 46,
+	.right_margin = 210,
+	.upper_margin = 24,
+	.lower_margin = 12,
+	.hsync_len = 1,
+	.vsync_len = 1,
+	.sync = 0,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 162,
+	.height = 162,
+	.initial = lcd_ek08009_power_on,
+	.uninitial = lcd_ek08009_power_off,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_ek08009_power_on(void)
+{
+	DPRINT("lcd_ek08009_power_on\n");
+
+	/* TODO */
+}
+
+static void lcd_ek08009_power_off(void)
+{
+	DPRINT("lcd_ek08009_power_off\n");
+
+	/* TODO */
+}
+
+struct lcd_parm_t *lcd_ek08009_get_parm(int arg)
+{
+	return &lcd_ek08009_parm;
+}
+
+int lcd_ek08009_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_EKING_EK08009,
+		(void *) lcd_ek08009_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_ek08009_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_EKING_EK08009_C
diff --git a/drivers/video/wmt/devices/lcd-HANNSTAR-HSD101PFW2.c b/drivers/video/wmt/devices/lcd-HANNSTAR-HSD101PFW2.c
new file mode 100755
index 00000000..438e3fee
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-HANNSTAR-HSD101PFW2.c
@@ -0,0 +1,103 @@
+/*++
+ * linux/drivers/video/wmt/lcd-HANNSTAR-HSD101PFW2.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_EKING_HSD101PFW2_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_HSD101PFW2_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_HSD101PFW2_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_HSD101PFW2_power_on(void);
+static void lcd_HSD101PFW2_power_off(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_HSD101PFW2_parm = {
+	.bits_per_pixel = 18,
+	.capability = 0,
+	.vmode = {
+	.name = "HANNSTAR HSD101PFW2",
+	.refresh = 60,
+	.xres = 1024,
+	.yres = 600,
+	.pixclock = KHZ2PICOS(45000),
+	.left_margin = 44,
+	.right_margin = 88,
+	.upper_margin = 10,
+	.lower_margin = 5,
+	.hsync_len = 44,
+	.vsync_len = 10,
+	.sync = FB_SYNC_VERT_HIGH_ACT,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 222,
+	.height = 125,
+	.initial = lcd_HSD101PFW2_power_on,
+	.uninitial = lcd_HSD101PFW2_power_off,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_HSD101PFW2_power_on(void)
+{
+	DPRINT("lcd_HSD101PFW2_power_on\n");
+
+	/* TODO */
+}
+
+static void lcd_HSD101PFW2_power_off(void)
+{
+	DPRINT("lcd_HSD101PFW2_power_off\n");
+
+	/* TODO */
+}
+
+struct lcd_parm_t *lcd_HSD101PFW2_get_parm(int arg)
+{
+	return &lcd_HSD101PFW2_parm;
+}
+
+int lcd_HSD101PFW2_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_HANNSTAR_HSD101PFW2,
+		(void *) lcd_HSD101PFW2_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_HSD101PFW2_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_EKING_HSD101PFW2_C
diff --git a/drivers/video/wmt/devices/lcd-INNOLUX-AT070TN83.c b/drivers/video/wmt/devices/lcd-INNOLUX-AT070TN83.c
new file mode 100755
index 00000000..7c1da494
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-INNOLUX-AT070TN83.c
@@ -0,0 +1,118 @@
+/*++
+ * linux/drivers/video/wmt/lcd-INNOLUX-AT070TN83.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_INNOLUX_AT070TN83_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_AT070TN83_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_AT070TN83_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_at070tn83_initial(void);
+static void lcd_at070tn83_uninitial(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_at070tn83_parm = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+	.name = "INNOLUX AT707TN83",
+	.refresh = 60,
+	.xres = 800,
+	.yres = 480,
+	.pixclock = KHZ2PICOS(33333),
+	.left_margin = 45,
+	.right_margin = 210,
+	.upper_margin = 22,
+	.lower_margin = 22,
+	.hsync_len = 1,
+	.vsync_len = 1,
+	.sync = 0,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 154,
+	.height = 85,
+	.initial = lcd_at070tn83_initial,
+	.uninitial = lcd_at070tn83_uninitial,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_at070tn83_initial(void)
+{
+#if 0
+	outl(inl(GPIO_BASE_ADDR + 0x80) | BIT0, GPIO_BASE_ADDR + 0x80);
+	outl(inl(GPIO_BASE_ADDR + 0x4C) | BIT28, GPIO_BASE_ADDR + 0x4C);
+	outl(inl(GPIO_BASE_ADDR + 0x8C) | BIT28, GPIO_BASE_ADDR + 0x8C);
+	/* DVDD */
+	/* T2 > 0ms */ /* AVDD/VCOM(NANDQS) */
+	outl(inl(GPIO_BASE_ADDR + 0xCC) | BIT28, GPIO_BASE_ADDR + 0xCC);
+	/* T4 > 0ms */
+	/* VGH */
+	/* 0 < T6 <= 10ms */
+	lcd_enable_signal(1); /* signal, DVO enable */
+	lcd_oem_enable_backlight(200); /* T12 > 200ms, BL(bit0) */
+#endif
+}
+
+static void lcd_at070tn83_uninitial(void)
+{
+#if 0
+	/* BL(bit0) */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~BIT0, GPIO_BASE_ADDR + 0xC0);
+	mdelay(200); /* T12 > 200ms */
+	lcd_enable_signal(0); /* singal, DVO enable */
+	/* AVDD/VCOM(NANDQS) */
+	outl(inl(GPIO_BASE_ADDR + 0xCC) & ~BIT28, GPIO_BASE_ADDR + 0xCC);
+#endif
+}
+
+struct lcd_parm_t *lcd_at070tn83_get_parm(int arg)
+{
+	return &lcd_at070tn83_parm;
+}
+
+int lcd_at070tn83_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_INNOLUX_AT070TN83,
+		(void *) lcd_at070tn83_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_at070tn83_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_INNOLUX_AT070TN83_C
diff --git a/drivers/video/wmt/devices/lcd-b079xan01.c b/drivers/video/wmt/devices/lcd-b079xan01.c
new file mode 100755
index 00000000..05a6e957
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-b079xan01.c
@@ -0,0 +1,363 @@
+/*++
+ * linux/drivers/video/wmt/lcd-b079xan01.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <linux/spi/spi.h>
+#include <mach/wmt-spi.h>
+
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+
+#include "../lcd.h"
+
+#define DRIVERNAME	"ssd2828"
+
+static struct lcd_parm_t lcd_b079xan01_parm = {
+	.bits_per_pixel = 24,
+	.capability = 0,
+	.vmode = {
+		.name = "B079XAN01",
+		.refresh = 60,
+		.xres = 768,
+		.yres = 1024,
+		.pixclock = KHZ2PICOS(64800),
+		.left_margin = 56,
+		.right_margin = 60,
+		.upper_margin = 30,
+		.lower_margin = 36,
+		.hsync_len = 64,
+		.vsync_len = 50,
+		.sync = 0, /* FB_SYNC_VERT_HIGH_ACT | FB_SYNC_HOR_HIGH_ACT, */
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 120,
+	.height = 160,
+#if 0
+	.initial = lcd_power_on,
+	.uninitial = lcd_power_off,
+#endif
+};
+
+static struct lcd_parm_t *lcd_b079xan01_get_parm(int arg)
+{
+	return &lcd_b079xan01_parm;
+}
+
+static int lcd_b079xan01_init(void)
+{
+	return lcd_panel_register(LCD_B079XAN01,
+		(void *) lcd_b079xan01_get_parm);
+}
+
+struct ssd2828_chip {
+	struct spi_device *spi;
+	int gpio_reset;
+};
+
+static int ssd2828_read(struct spi_device *spi, uint8_t reg)
+{
+	int ret;
+	uint8_t buf1[3] = { 0x70, 0x00, 0x00 };
+	uint8_t buf2[3] = { 0x73, 0x00, 0x00 };
+
+	buf1[2] = reg;
+
+	ret = spi_write(spi, buf1, 3);
+	if (ret) {
+		pr_err("spi_write ret=%d\n", ret);
+		return -EIO;
+	}
+
+	ret = spi_w8r16(spi, buf2[0]);
+	if (ret < 0) {
+		pr_err("spi_write ret=%d\n", ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+#if 0
+static int ssd2828_write(struct spi_device *spi, uint8_t reg, uint16_t data)
+{
+	int ret;
+	uint8_t buf_reg[3] = { 0x70, 0x00, 0x00 };
+	uint8_t buf_data[3] = { 0x72, 0x00, 0x00 };
+
+	buf_reg[2] = reg;
+
+	buf_data[1] = (data >> 8) & 0xff;
+	buf_data[2] = data & 0xff;
+
+	ret = spi_write(spi, buf_reg, 3);
+	if (ret) {
+		pr_err("spi_write ret=%d,w cmd=0x%06x\n", ret, data);
+		return ret;
+	}
+
+	ret = spi_write(spi, buf_data, 3);
+	if (ret)
+		pr_err("spi_write ret=%d,w cmd=0x%06x\n", ret, data);
+
+	return ret;
+}
+#endif
+
+static inline int spi_write_24bit(struct spi_device *spi, uint32_t data)
+{
+	int ret;
+	uint8_t buf[3];
+
+	buf[0] = (data >> 16) & 0xff;
+	buf[1] = (data >> 8) & 0xff;
+	buf[2] = data & 0xff;
+
+	ret = spi_write(spi, buf, 3);
+	if (ret)
+		pr_err("spi_write ret=%d,w cmd=0x%06x\n", ret, data);
+
+	return ret;
+}
+
+static const uint32_t ssd2828_init_sequence[] = {
+	0x7000B1, 0x723240, /* VSA=50, HAS=64 */
+	0x7000B2, 0x725078, /* VBP=30+50, HBP=56+64 */
+	0x7000B3, 0x72243C, /* VFP=36, HFP=60 */
+	0x7000B4, 0x720300, /* HACT=768 */
+	0x7000B5, 0x720400, /* VACT=1024 */
+	0x7000B6, 0x72000b, /* burst mode, 24bpp loosely packed */
+	0x7000DE, 0x720003, /* no of lane=4 */
+	0x7000D6, 0x720005, /* RGB order and packet number in blanking period */
+	0x7000B9, 0x720000, /* disable PLL */
+
+	/* lane speed=576 (24MHz * 24 = 576) */
+	/* may modify according to requirement, 500Mbps to 560Mbps */
+	/* LP clock : 576 / 9 / 8 = 8 MHz */
+	0x7000BA, 0x728018,
+	0x7000BB, 0x720008,
+
+	0x7000B9, 0x720001, /* enable PPL */
+	0x7000C4, 0x720001, /* enable BTA */
+	0x7000B7, 0x720342, /* enter LP mode */
+	0x7000B8, 0x720000, /* VC */
+	0x7000BC, 0x720000, /* set packet size */
+
+	0x700011, 0xff0000 + 200, /* sleep out cmd */
+	0x700029, 0xff0000 + 200, /* display on */
+	0x7000B7, 0x72030b, /* video mode on */
+};
+
+static int ssd2828_hw_reset(struct ssd2828_chip *chip)
+{
+	lcd_power_on(1);
+	msleep(10);
+
+	gpio_direction_output(chip->gpio_reset, 1);
+	msleep(10);
+	gpio_direction_output(chip->gpio_reset, 0);
+	msleep(20);
+	gpio_direction_output(chip->gpio_reset, 1);
+	msleep(20);
+	return 0;
+}
+
+static int ssd2828_hw_init(struct ssd2828_chip *chip)
+{
+	int ret = 0;
+	int i;
+
+	ssd2828_hw_reset(chip);
+
+	ret = ssd2828_read(chip->spi, 0xB0);
+	if (ret < 0 || ret != 0x2828) {
+		pr_err("Error: SSD2828 not found!\n");
+		return -ENODEV;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ssd2828_init_sequence); i++) {
+		if (ssd2828_init_sequence[i] & 0xff000000) {
+			msleep(ssd2828_init_sequence[i] & 0xff);
+			continue;
+		}
+		ret = spi_write_24bit(chip->spi, ssd2828_init_sequence[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static ssize_t option_port_testmode_show(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	char *s = buf;
+	int ret;
+	int reg;
+
+	struct spi_device *spi = container_of(dev, struct spi_device, dev);
+
+	s += sprintf(s, "register  value\n");
+
+	for (reg = 0xb0; reg <= 0xff; reg++) {
+		ret = ssd2828_read(spi, (uint8_t)reg);
+		if (ret < 0)
+			goto out;
+		s += sprintf(s, "reg 0x%02X : 0x%04x\n", reg, ret);
+	}
+
+	s += sprintf(s, "=========\n");
+
+out:
+	return s - buf;
+}
+
+static ssize_t option_port_testmode_store(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	return 0;
+}
+
+static DEVICE_ATTR(testmode, S_IRUGO,
+		   option_port_testmode_show,
+		   option_port_testmode_store);
+
+static int __devinit ssd2828_probe(struct spi_device *spi)
+{
+	struct ssd2828_chip *chip;
+	int gpio = WMT_PIN_GP0_GPIO0;
+	int ret;
+
+	ret = gpio_request(gpio, "SSD2828 Reset");
+	if (ret) {
+		dev_err(&spi->dev, "can not open GPIO %d\n", gpio);
+		return ret;
+	}
+
+	ret = ssd2828_read(spi, 0xB0);
+	if (ret < 0 || ret != 0x2828) {
+		pr_err("Error: SSD2828 not found!\n");
+		return -ENODEV;
+	}
+
+	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+	if (!chip)
+		return -ENOMEM;
+
+	chip->spi = spi;
+	chip->gpio_reset = gpio;
+	spi_set_drvdata(spi, chip);
+
+	ret = sysfs_create_file(&spi->dev.kobj, &dev_attr_testmode.attr);
+	if (unlikely(ret))
+		pr_err("ssd2828 sysfs_create_file failed\n");
+
+	return ret;
+}
+
+static int ssd2828_spi_resume(struct spi_device *spi)
+{
+	struct ssd2828_chip *chip = dev_get_drvdata(&spi->dev);
+	return ssd2828_hw_init(chip);
+}
+
+static struct spi_driver ssd2828_driver = {
+	.driver = {
+		.name	= DRIVERNAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= ssd2828_probe,
+	.resume		= ssd2828_spi_resume,
+#if 0
+	.remove		= __devexit_p(ssd2828_remove),
+	.shutdown	= ssd2828_shutdown,
+#endif
+};
+
+static struct spi_board_info ssd2828_spi_info[] __initdata = {
+	{
+		.modalias	= DRIVERNAME,
+		.bus_num	= 1,
+		.chip_select	= 0,
+		.max_speed_hz	= 12000000,
+		.irq		= -1,
+		.mode		= SPI_CLK_MODE3,
+	},
+};
+
+static int wmt_lcd_panel(void)
+{
+	char buf[96];
+	int len = sizeof(buf);
+	int type, id = 0;
+
+	if (wmt_getsyspara("wmt.display.param", buf, &len))
+		return -ENODEV;
+
+	sscanf(buf, "%d:%d", &type, &id);
+	return id;
+}
+
+static int __init b079xan01_init(void)
+{
+	int ret;
+
+	if (wmt_lcd_panel() != LCD_B079XAN01) {
+		pr_err("LCD B079XAN01 not found\n");
+		return -EINVAL;
+	}
+
+	ret = spi_register_board_info(ssd2828_spi_info,
+				      ARRAY_SIZE(ssd2828_spi_info));
+	if (ret) {
+		pr_err("spi_register_board_info failed\n");
+		return ret;
+	}
+
+	ret = spi_register_driver(&ssd2828_driver);
+	if (ret) {
+		pr_err("spi_register_driver failed\n");
+		return -EIO;
+	}
+
+	if (lcd_b079xan01_init()) {
+		spi_unregister_driver(&ssd2828_driver);
+		return -ENODEV;
+	}
+
+	pr_info("spi %s register success\n", DRIVERNAME);
+
+	return 0;
+}
+
+static void b079xan01_exit(void)
+{
+	spi_unregister_driver(&ssd2828_driver);
+}
+
+module_init(b079xan01_init);
+module_exit(b079xan01_exit);
diff --git a/drivers/video/wmt/devices/lcd-gl5001w.c b/drivers/video/wmt/devices/lcd-gl5001w.c
new file mode 100755
index 00000000..03e3de29
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-gl5001w.c
@@ -0,0 +1,1412 @@
+/*++
+ * linux/drivers/video/wmt/devices/lcd-gl5001w.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2012  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/power_supply.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/proc_fs.h>
+#include <linux/gpio.h>//wangaq+
+#include "../lcd.h"
+
+//#include <mach/gpio-cs.h>
+//#include <mach/wmt_env.h>
+#include <mach/wmt_iomux.h>//wangaq+
+
+
+#include "../lcd.h"//yangchen add
+
+#define DRIVER_NAME "tc358768"
+#define I2C_ADDR    0x0E
+#define I2C_ADAPTER 0
+
+#define DTYPE_DCS_SWRITE_0P     0X05
+#define DTYPE_DCS_SWRITE_1P     0X15
+#define DTYPE_DCS_LWRITE        0X39
+#define DTYPE_GEN_LWRITE        0X29
+#define DTYPE_GEN_SWRITE_2P     0X23
+#define DTYPE_GEN_SWRITE_1P     0X13
+#define DTYPE_GEN_SWRITE_0P     0X03
+
+
+#define Gl5001w_Reset_Port      WMT_PIN_GP62_SUSGPIO0
+#define Tc358768_Reset_Port     WMT_PIN_GP1_GPIO8
+//#define BackLight_Power_PORT  WMT_PIN_GP0_GPIO0
+
+static void lcd_set_power(int status);
+static int save=1;
+//static struct work_struct cw500_resume_work;
+struct cw500_data {
+    struct work_struct cw500_resume_work;
+};
+struct cw500_data *data;
+
+#if 0
+#define lcd_debug   printk
+#else
+#define lcd_debug(fmt...)   do { } while (0)
+#endif
+
+#define __unused __attribute__ ((unused))
+
+static bool lcd_init_gl500 = false;
+
+
+typedef enum {
+    //LCD_BTL504880,
+    LCD_YT50F62C6,
+    LCD_BT050TN,
+    LCD_ILI9806,
+    LCD_OTM8019A,
+    LCD_MAX
+} lcd_panel_enum;
+
+struct lcd_deviceid_struct{
+    unsigned short id;
+    unsigned char addr;
+    unsigned char read_start;
+    unsigned char len;
+};
+
+static struct lcd_deviceid_struct lcd_deviceid[LCD_MAX]={
+    //{0x8009,0xa1,6,2},
+    {0x9805,0xd3,5,2},
+    {0x8009,0xa1,6,2},
+    {0x9816,0xd3,5,2},
+    {0x8019,0xa1,6,2}
+};
+
+//LCD_YT50F62C6
+static unsigned char LCD_YT50F62C6_CMD_FF_3DATA[] = {0xFF,0xFF,0x98,0x05};        //EXTC Command Set enable register
+static unsigned char LCD_YT50F62C6_CMD_FD_4DATA[] = {0xFD,0x03,0x13,0x44,0x00};
+static unsigned char LCD_YT50F62C6_CMD_F8_15DATA[] = {0xF8,0x15,0x02,0x02,0x15,0x02,0x02,0x30,0x01,0x01,0x30,0x01,0x01,0x30,0x01,0x01};
+static unsigned char LCD_YT50F62C6_CMD_B8_1DATA[] = {0xB8,0x73};        //DBI Type B Interface Setting
+static unsigned char LCD_YT50F62C6_CMD_F1_1DATA[] = {0xF1,0x00};            //Gate Modulation
+static unsigned char LCD_YT50F62C6_CMD_F2_3DATA[] = {0xF2,0x00,0x58,0x41};      //CR/EQ/PC
+static unsigned char LCD_YT50F62C6_CMD_FC_3DATA[] = {0xFC,0x04,0x0F,0x01};
+static unsigned char LCD_YT50F62C6_CMD_FE_1DATA[] = {0xFE,0x19};        //SRAM Repair
+static unsigned char LCD_YT50F62C6_CMD_EB_2DATA[] = {0xEB,0x08,0x0F};       // 3 Gamma & Dithering
+static unsigned char LCD_YT50F62C6_CMD_E0_16DATA[] = {0xE0,0x00,0x02,0x07,0x10,0x10,0x1D,0x0F,0x0B,0x00,0x03,0x02,0x0B,0x0C,0x33,0x2F,0x00};        //P-Gamma
+static unsigned char LCD_YT50F62C6_CMD_E1_16DATA[] = {0xE1,0x00,0x02,0x07,0x10,0x10,0x17,0x0B,0x0B,0x00,0x03,0x02,0x0B,0x0C,0x33,0x2F,0x00};        //N-Gamma
+static unsigned char LCD_YT50F62C6_CMD_C1_4DATA[] = {0xC1,0x13,0x26,0x06,0x26};     //Power Control 1
+static unsigned char LCD_YT50F62C6_CMD_C7_1DATA[] = {0xC7,0xC4};
+static unsigned char LCD_YT50F62C6_CMD_B1_3DATA[] = {0xB1,0x00,0x12,0x14};          //Frame Rate Control
+static unsigned char LCD_YT50F62C6_CMD_B4_1DATA[] = {0xB4,0x02};            // 2 Dot Inversion
+static unsigned char LCD_YT50F62C6_CMD_36_1DATA[] = {0x36,0x0A};          //Memory Access
+static unsigned char LCD_YT50F62C6_CMD_3A_1DATA[] = {0x3A,0x77};            //16 & 18 & 24 bits
+static unsigned char LCD_YT50F62C6_CMD_21_0DATA[] = {0x21};             //Display Inv-On
+static unsigned char LCD_YT50F62C6_CMD_B0_1DATA[] = {0xB0,0x00};            //RGB I/F Polarity
+static unsigned char LCD_YT50F62C6_CMD_B6_1DATA[] = {0xB6,0x01};            //CPU/RGB I/F Select
+static unsigned char LCD_YT50F62C6_CMD_C2_1DATA[] = {0xC2,0x11};
+static unsigned char LCD_YT50F62C6_CMD_11_0DATA[] = {0x11};                //Sleep out
+static unsigned char LCD_YT50F62C6_CMD_29_0DATA[] = {0x29};                //Display on
+static unsigned char LCD_YT50F62C6_CMD_2C_0DATA[] = {0x2C};                //Memory write
+
+//LCD_BT050TN
+static unsigned char LCD_BT050TN_CMD_FF00_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_FF00_3DATA[] = {0xFF,0x80,0x09,0x01};
+static unsigned char LCD_BT050TN_CMD_FF80_0DATA[] = {0x00,0x80};
+static unsigned char LCD_BT050TN_CMD_FF80_2DATA[] = {0xFF,0x80,0x09};
+static unsigned char LCD_BT050TN_CMD_FF03_0DATA[] = {0x00,0x03};
+static unsigned char LCD_BT050TN_CMD_FF03_1DATA[] = {0xFF,0x01};
+static unsigned char LCD_BT050TN_CMD_2100_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_2100_1DATA[] = {0x21,0x00};
+static unsigned char LCD_BT050TN_CMD_D800_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_D800_2DATA[] = {0xD8,0x6F,0x6F};
+static unsigned char LCD_BT050TN_CMD_C582_0DATA[] = {0x00,0x82};
+static unsigned char LCD_BT050TN_CMD_C582_1DATA[] = {0xC5,0xA3};
+static unsigned char LCD_BT050TN_CMD_C181_0DATA[] = {0x00,0x81};
+static unsigned char LCD_BT050TN_CMD_C181_1DATA[] = {0xC1,0x66};
+static unsigned char LCD_BT050TN_CMD_C1A1_0DATA[] = {0x00,0xA1};
+static unsigned char LCD_BT050TN_CMD_C1A1_1DATA[] = {0xC1,0x08};
+static unsigned char LCD_BT050TN_CMD_B4C0_0DATA[] = {0x00,0xB4};
+static unsigned char LCD_BT050TN_CMD_B4C0_1DATA[] = {0xC0,0x50};
+static unsigned char LCD_BT050TN_CMD_C0A3_0DATA[] = {0x00,0xA3};
+static unsigned char LCD_BT050TN_CMD_C0A3_1DATA[] = {0xC0,0x00};
+static unsigned char LCD_BT050TN_CMD_C489_0DATA[] = {0x00,0x89};
+static unsigned char LCD_BT050TN_CMD_C489_1DATA[] = {0xC4,0x08};
+static unsigned char LCD_BT050TN_CMD_C481_0DATA[] = {0x00,0x81};
+static unsigned char LCD_BT050TN_CMD_C481_1DATA[] = {0xC4,0x83};
+static unsigned char LCD_BT050TN_CMD_C590_0DATA[] = {0x00,0x90};
+static unsigned char LCD_BT050TN_CMD_C590_3DATA[] = {0xC5,0x96,0xA7,0x01};
+static unsigned char LCD_BT050TN_CMD_C5B1_0DATA[] = {0x00,0xB1};
+static unsigned char LCD_BT050TN_CMD_C5B1_1DATA[] = {0xC5,0xA9};
+static unsigned char LCD_BT050TN_CMD_D900_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_D900_1DATA[] = {0xD9,0x15};
+static unsigned char LCD_BT050TN_CMD_E100_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_E100_16DATA[] = {0xE1,0x02,0x08,0x0E,0x10,0x09,0x1D,0x0E,0x0E,0x00,0x05,0x02,0x07,0x0E,0x24,0x23,0x1D};
+static unsigned char LCD_BT050TN_CMD_E200_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_E200_16DATA[] = {0xE2,0x02,0x08,0x0E,0x0F,0x09,0x1D,0x0E,0x0D,0x00,0x04,0x02,0x07,0x0E,0x25,0x23,0x1D};
+static unsigned char LCD_BT050TN_CMD_0000_0DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_0000_1DATA[] = {0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_B3A1_0DATA[] = {0x00,0xA1};
+static unsigned char LCD_BT050TN_CMD_B3A1_1DATA[] = {0xB3,0x10};
+static unsigned char LCD_BT050TN_CMD_B3A7_0DATA[] = {0x00,0xA7};
+static unsigned char LCD_BT050TN_CMD_B3A7_1DATA[] = {0xB3,0x10};
+static unsigned char LCD_BT050TN_CMD_C090_0DATA[] = {0x00,0x90};
+static unsigned char LCD_BT050TN_CMD_C090_6DATA[] = {0xC0,0x00,0x44,0x00,0x00,0x00,0x03};
+static unsigned char LCD_BT050TN_CMD_C1A6_0DATA[] = {0x00,0xA6};
+static unsigned char LCD_BT050TN_CMD_C1A6_3DATA[] = {0xC1,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CE80_0DATA[] = {0x00,0x80};
+static unsigned char LCD_BT050TN_CMD_CE80_6DATA[] = {0xCE,0x87,0x03,0x00,0x86,0x03,0x00};
+static unsigned char LCD_BT050TN_CMD_CE90_0DATA[] = {0x00,0x90};
+static unsigned char LCD_BT050TN_CMD_CE90_6DATA[] = {0xCE,0x33,0x1E,0x00,0x33,0x1F,0x00};
+static unsigned char LCD_BT050TN_CMD_CEA0_0DATA[] = {0x00,0xA0};
+static unsigned char LCD_BT050TN_CMD_CEA0_14DATA[] = {0xCE,0x38,0x03,0x03,0x20,0x00,0x00,0x00,0x38,0x02,0x03,0x21,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CEB0_0DATA[] = {0x00,0xb0};
+static unsigned char LCD_BT050TN_CMD_CEB0_14DATA[] = {0xCE,0x38,0x01,0x03,0x22,0x00,0x00,0x00,0x38,0x00,0x03,0x23,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CEC0_0DATA[] = {0x00,0xC0};
+static unsigned char LCD_BT050TN_CMD_CEC0_14DATA[] = {0xCE,0x30,0x00,0x03,0x24,0x00,0x00,0x00,0x30,0x01,0x03,0x25,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CED0_0DATA[] = {0x00,0xD0};
+static unsigned char LCD_BT050TN_CMD_CED0_14DATA[] = {0xCE,0x30,0x02,0x03,0x26,0x00,0x00,0x00,0x30,0x03,0x03,0x27,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CFC6_0DATA[] = {0x00,0xC6};
+static unsigned char LCD_BT050TN_CMD_CFC6_2DATA[] = {0xCF,0x01,0x80};
+static unsigned char LCD_BT050TN_CMD_CFC9_0DATA[] = {0x00,0xC9};
+static unsigned char LCD_BT050TN_CMD_CFC9_1DATA[] = {0xCF,0x00};
+static unsigned char LCD_BT050TN_CMD_CBC0_0DATA[] = {0x00,0xC0};
+static unsigned char LCD_BT050TN_CMD_CBC0_15DATA[] = {0xCB,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CBD0_0DATA[] = {0x00,0xD0};
+static unsigned char LCD_BT050TN_CMD_CBD0_15DATA[] = {0xCB,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x04,0x04,0x04,0x00,0x00,0x04,0x04,0x04};
+static unsigned char LCD_BT050TN_CMD_CBE0_0DATA[] = {0x00,0xE0};
+static unsigned char LCD_BT050TN_CMD_CBE0_10DATA[] = {0xCB,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CC80_0DATA[] = {0x00,0x80};
+static unsigned char LCD_BT050TN_CMD_CC80_10DATA[] = {0xCC,0x00,0x26,0x25,0x02,0x06,0x00,0x00,0x0A,0x0E,0x0C};
+static unsigned char LCD_BT050TN_CMD_CC90_0DATA[] = {0x00,0x90};
+static unsigned char LCD_BT050TN_CMD_CC90_15DATA[] = {0xCC,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x26,0x25,0x01,0x05};
+static unsigned char LCD_BT050TN_CMD_CCA0_0DATA[] = {0x00,0xA0};
+static unsigned char LCD_BT050TN_CMD_CCA0_15DATA[] = {0xCC,0x00,0x00,0x09,0x0d,0x0b,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_CCB0_0DATA[] = {0x00,0xB0};
+static unsigned char LCD_BT050TN_CMD_CCB0_10DATA[] = {0xCC,0x00,0x25,0x26,0x05,0x01,0x00,0x00,0x0F,0x0B,0x0D};
+static unsigned char LCD_BT050TN_CMD_CCC0_0DATA[] = {0x00,0xC0};
+static unsigned char LCD_BT050TN_CMD_CCC0_15DATA[] = {0xCC,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x26,0x06,0x02};
+static unsigned char LCD_BT050TN_CMD_CCD0_0DATA[] = {0x00,0xD0};
+static unsigned char LCD_BT050TN_CMD_CCD0_15DATA[] = {0xCC,0x00,0x00,0x10,0x0c,0x0e,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+static unsigned char LCD_BT050TN_CMD_21_0DATA[] = {0x21};
+static unsigned char LCD_BT050TN_CMD_36_0DATA[] = {0x36};
+static unsigned char LCD_BT050TN_CMD_00_0DATA[] = {0x00};
+static unsigned char LCD_BT050TN_CMD_11_0DATA[] = {0x11};
+static unsigned char LCD_BT050TN_CMD_29_0DATA[] = {0x29};
+static unsigned char LCD_BT050TN_CMD_2C_0DATA[] = {0x2C};
+
+
+//LCD_ILI9806
+static unsigned char LCD_ILI9806_CMD_FF_3DATA[] = {0xFF,0xFF,0x98,0x16};
+static unsigned char LCD_ILI9806_CMD_BA_1DATA[] = {0xBA,0x60};
+static unsigned char LCD_ILI9806_CMD_F3_1DATA[] = {0xF3,0x70};
+static unsigned char LCD_ILI9806_CMD_F9_3DATA[] = {0xF9,0x04,0xFB,0x84};
+static unsigned char LCD_ILI9806_CMD_B0_1DATA[] = {0xB0,0x01};
+static unsigned char LCD_ILI9806_CMD_BC_23DATA[] = {0xBC,0x01,0x0F,0x61,0xFE,0x01,0x01,0x0B,0x11,0x6C,0x63,0xFF,0xFF,0x01,0x01,0x00,0x00,0x55,0x53,0x01,0x00,0x00,0x43,0x0B};
+static unsigned char LCD_ILI9806_CMD_BD_8DATA[] = {0xBD,0x01,0x23,0x45,0x67,0x01,0x23,0x45,0x67};
+static unsigned char LCD_ILI9806_CMD_BE_17DATA[] = {0xBE,0x13,0x11,0x00,0x22,0x22,0xBA,0xAB,0x22,0x22,0x22,0x66,0x22,0x22,0x22,0x22,0x22,0x22};
+static unsigned char LCD_ILI9806_CMD_ED_2DATA[] = {0xED,0x7F,0x0F};
+static unsigned char LCD_ILI9806_CMD_B4_3DATA[] = {0xB4,0x02,0x02,0x02};
+static unsigned char LCD_ILI9806_CMD_B5_4DATA[] = {0xB5,0x14,0x14,0x04,0x00};
+static unsigned char LCD_ILI9806_CMD_C0_3DATA[] = {0xC0,0x7F,0x0B,0x04};
+static unsigned char LCD_ILI9806_CMD_C1_4DATA[] = {0xC1,0x17,0x78,0x78,0x20};
+static unsigned char LCD_ILI9806_CMD_D7_1DATA[] = {0xD7,0x2A};
+static unsigned char LCD_ILI9806_CMD_D8_1DATA[] = {0xD8,0x28};
+static unsigned char LCD_ILI9806_CMD_FC_1DATA[] = {0xFC,0x05};
+static unsigned char LCD_ILI9806_CMD_E0_16DATA[] = {0xE0,0x00,0x03,0x0A,0x0E,0x11,0x15,0x0A,0x08,0x04,0x09,0x07,0x0D,0x0D,0x2E,0x28,0x00};
+static unsigned char LCD_ILI9806_CMD_E1_16DATA[] = {0xE1,0x00,0x02,0x09,0x0E,0x11,0x15,0x0A,0x09,0x04,0x09,0x08,0x0C,0x0D,0x2F,0x28,0x00};
+static unsigned char LCD_ILI9806_CMD_D5_8DATA[] = {0xD5,0x09,0x0A,0x0D,0x0B,0xCB,0xA5,0x01,0x04};
+static unsigned char LCD_ILI9806_CMD_F7_1DATA[] = {0xF7,0x89};
+static unsigned char LCD_ILI9806_CMD_C7_1DATA[] = {0xC7,0x43};
+static unsigned char LCD_ILI9806_CMD_36_1DATA[] = {0x36,0x00};
+static unsigned char LCD_ILI9806_CMD_51_1DATA[] = {0x51,0xFF};
+static unsigned char LCD_ILI9806_CMD_53_1DATA[] = {0x53,0x24};
+static unsigned char LCD_ILI9806_CMD_55_1DATA[] = {0x55,0x03};
+static unsigned char LCD_ILI9806_CMD_11_0DATA[] = {0x11};
+static unsigned char LCD_ILI9806_CMD_29_0DATA[] = {0x29};
+static unsigned char LCD_ILI9806_CMD_2C_0DATA[] = {0x2C};                //Memory write
+
+//OTM8019A
+static unsigned char LCD_OTM8019A_CMD_1[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_2[]= {0xFF,0x80,0x19,0x01};
+static unsigned char LCD_OTM8019A_CMD_3[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_4[]= {0xFF,0x80,0x19};
+static unsigned char LCD_OTM8019A_CMD_5[]= {0x00,0x90};
+static unsigned char LCD_OTM8019A_CMD_6[]= {0xB3,0x02};
+static unsigned char LCD_OTM8019A_CMD_7[]= {0x00,0x92};
+static unsigned char LCD_OTM8019A_CMD_8[]= {0xB3,0x45};
+static unsigned char LCD_OTM8019A_CMD_9[]= {0x00,0xA2};
+static unsigned char LCD_OTM8019A_CMD_10[]= {0xC0,0x04,0x00,0x02};
+static unsigned char LCD_OTM8019A_CMD_11[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_12[]= {0xC0,0x00,0x58,0x00,0x14,0x16};
+static unsigned char LCD_OTM8019A_CMD_13[]= {0x00,0x90};
+static unsigned char LCD_OTM8019A_CMD_14[]= {0xC0,0x00,0x15,0x00,0x00,0x00,0x03};
+static unsigned char LCD_OTM8019A_CMD_15[]= {0x00,0xB4};
+static unsigned char LCD_OTM8019A_CMD_16[]= {0xC0,0x70};//1+2 dot inversion
+static unsigned char LCD_OTM8019A_CMD_17[]= {0x00,0x81};
+static unsigned char LCD_OTM8019A_CMD_18[]= {0xC1,0x33};
+static unsigned char LCD_OTM8019A_CMD_19[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_20[]= {0xC4,0x30,0x83};
+static unsigned char LCD_OTM8019A_CMD_21[]= {0x00,0x89};
+static unsigned char LCD_OTM8019A_CMD_22[]= {0xC4,0x08};
+static unsigned char LCD_OTM8019A_CMD_23[]= {0x00,0x82};
+static unsigned char LCD_OTM8019A_CMD_24[]= {0xC5,0xB0};
+static unsigned char LCD_OTM8019A_CMD_25[]= {0x00,0x90};
+static unsigned char LCD_OTM8019A_CMD_26[]= {0xC5,0x4E,0x79,0x01,0x03};
+static unsigned char LCD_OTM8019A_CMD_27[]= {0x00,0xB1};
+static unsigned char LCD_OTM8019A_CMD_28[]= {0xC5,0xA9};
+static unsigned char LCD_OTM8019A_CMD_29[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_30[]= {0xCE,0x87,0x03,0x00,0x85,0x03,0x00,0x86,0x03,0x00,0x84,0x03,0x00};
+static unsigned char LCD_OTM8019A_CMD_31[]= {0x00,0xA0};
+static unsigned char LCD_OTM8019A_CMD_32[]= {0xCE,0x38,0x03,0x03,0x58,0x00,0x00,0x00,0x38,0x02,0x03,0x59,0x00,0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_33[]= {0x00,0xB0};
+static unsigned char LCD_OTM8019A_CMD_34[]= {0xCE,0x38,0x01,0x03,0x5A,0x00,0x00,0x00,0x38,0x00,0x03,0x5B,0x00,0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_35[]= {0x00,0xC0};
+static unsigned char LCD_OTM8019A_CMD_36[]= {0xCE,0x30,0x00,0x03,0x5C,0x00,0x00,0x00,0x30,0x01,0x03,0x5D,0x00,0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_37[]= {0x00,0xD0};
+static unsigned char LCD_OTM8019A_CMD_38[]= {0xCE,0x30,0x02,0x03,0x5E,0x00,0x00,0x00,0x30,0x03,0x03,0x5F,0x00,0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_39[]= {0x00,0xC7};
+static unsigned char LCD_OTM8019A_CMD_40[]= {0xCF,0x00};
+static unsigned char LCD_OTM8019A_CMD_41[]= {0x00,0xC9};
+static unsigned char LCD_OTM8019A_CMD_42[]= {0xCF,0x00};
+static unsigned char LCD_OTM8019A_CMD_43[]= {0x00,0xC4};
+static unsigned char LCD_OTM8019A_CMD_44[]= {0xCB,0x01,0x01,0x01,0x01,0x01,0x01};
+static unsigned char LCD_OTM8019A_CMD_45[]= {0x00,0xD9};
+static unsigned char LCD_OTM8019A_CMD_46[]= {0xCB,0x00,0x00,0x01,0x01,0x01,0x01};
+static unsigned char LCD_OTM8019A_CMD_47[]= {0x00,0xE0};
+static unsigned char LCD_OTM8019A_CMD_48[]= {0xCB,0x01,0x01};
+static unsigned char LCD_OTM8019A_CMD_49[]= {0x00,0x84};
+static unsigned char LCD_OTM8019A_CMD_50[]= {0xCC,0x0C,0x0A,0x10,0x0E,0x03,0x04};
+static unsigned char LCD_OTM8019A_CMD_51[]= {0x00,0x9E};
+static unsigned char LCD_OTM8019A_CMD_52[]= {0xCC,0x00};
+static unsigned char LCD_OTM8019A_CMD_53[]= {0x00,0xA0};
+static unsigned char LCD_OTM8019A_CMD_54[]= {0xCC,0x00,0x02,0x01,0x0d,0x0f,0x09,0x0b};
+static unsigned char LCD_OTM8019A_CMD_55[]= {0x00,0xB4};
+static unsigned char LCD_OTM8019A_CMD_56[]= {0xCC,0x0D,0x0F,0x09,0x0B,0x02,0x01};
+static unsigned char LCD_OTM8019A_CMD_57[]= {0x00,0xCE};
+static unsigned char LCD_OTM8019A_CMD_58[]= {0xCC,0x85};
+static unsigned char LCD_OTM8019A_CMD_59[]= {0x00,0xD0};
+static unsigned char LCD_OTM8019A_CMD_60[]= {0xCC,0x05,0x03,0x04,0x0c,0x0a,0x10,0x0e};
+static unsigned char LCD_OTM8019A_CMD_61[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_62[]= {0xD8,0x85,0x85};
+static unsigned char LCD_OTM8019A_CMD_63[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_64[]= {0xD9,0x61};
+static unsigned char LCD_OTM8019A_CMD_65[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_66[]= {0xE1,0x00,0x03,0x0a,0x1d,0x33,0x49,0x54,0x89,0x7a,0x8e,0x79,0x69,0x81,0x6d,0x73,0x6d,0x66,0x5d,0x52,0x00};
+static unsigned char LCD_OTM8019A_CMD_67[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_68[]= {0xE2,0x00,0x04,0x0a,0x1d,0x33,0x49,0x54,0x89,0x7a,0x8e,0x79,0x69,0x81,0x6d,0x73,0x6d,0x66,0x5d,0x52,0x00};
+static unsigned char LCD_OTM8019A_CMD_69[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_70[]= {0xC4,0x30};
+static unsigned char LCD_OTM8019A_CMD_71[]= {0x00,0x98};
+static unsigned char LCD_OTM8019A_CMD_72[]= {0xC0,0x00};
+static unsigned char LCD_OTM8019A_CMD_73[]= {0x00,0xa9};
+static unsigned char LCD_OTM8019A_CMD_74[]= {0xC0,0x06};
+static unsigned char LCD_OTM8019A_CMD_75[]= {0x00,0xb0};
+static unsigned char LCD_OTM8019A_CMD_76[]= {0xC1,0x20,0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_77[]= {0x00,0xe1};
+static unsigned char LCD_OTM8019A_CMD_78[]= {0xC0,0x40,0x18};
+static unsigned char LCD_OTM8019A_CMD_79[]= {0x00,0x80};
+static unsigned char LCD_OTM8019A_CMD_80[]= {0xC1,0x03,0x33};
+static unsigned char LCD_OTM8019A_CMD_81[]= {0x00,0xA0};
+static unsigned char LCD_OTM8019A_CMD_82[]= {0xC1,0xe8};
+static unsigned char LCD_OTM8019A_CMD_83[]= {0x00,0x90};
+static unsigned char LCD_OTM8019A_CMD_84[]= {0xb6,0xb4};
+static unsigned char LCD_OTM8019A_CMD_85[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_86[]= {0xfb,0x01};
+static unsigned char LCD_OTM8019A_CMD_87[]= {0x00,0x00};
+static unsigned char LCD_OTM8019A_CMD_88[]= {0xFF,0xFF,0xFF,0xFF};
+static unsigned char LCD_OTM8019A_CMD_89[]= {0x11,0x00};
+static unsigned char LCD_OTM8019A_CMD_90[]= {0x29,0x00};
+//End   of
+static struct i2c_client *tc358768_client;
+
+static inline int tc358768_rd_reg_32bits(uint32_t reg_addr)
+{
+    int ret;
+    struct i2c_msg msgs[2];
+    uint8_t buf[4];
+    struct i2c_client *client = tc358768_client;
+
+    buf[0] = (reg_addr >> 8) & 0xff;
+    buf[1] = reg_addr & 0xff;
+
+    msgs[0].addr  = client->addr;
+    msgs[0].flags = 0;
+    msgs[0].len   = 2;
+    msgs[0].buf   = buf;
+
+    msgs[1].addr  = client->addr;
+    msgs[1].flags = I2C_M_RD;
+    msgs[1].len   = 2;
+    msgs[1].buf   = buf;
+
+    ret = i2c_transfer(client->adapter, msgs, 2);
+    if (ret < 0) {
+        printk("%s:i2c_transfer fail =%d\n", __func__, ret);
+        return -1;
+    }
+
+    ret = (buf[0] << 8) | buf[1];
+
+    return ret;
+}
+
+static inline int tc358768_wr_reg_32bits(uint32_t value)
+{
+    struct i2c_msg msgs;
+    int ret = -1;
+    uint8_t buf[4];
+    struct i2c_client *client = tc358768_client;
+
+    buf[0] = value>>24;
+    buf[1] = value>>16;
+    buf[2] = value>>8;
+    buf[3] = value;
+
+    msgs.addr  = client->addr;
+    msgs.flags = 0;
+    msgs.len   = 4;
+    msgs.buf   = buf;
+
+    ret = i2c_transfer(client->adapter, &msgs, 1);
+    if(ret < 0)
+        printk("%d:i2c_transfer fail = %d\n",__LINE__, ret);
+
+    return ret;
+}
+
+static int _tc358768_wr_regs_32bits(unsigned int reg_array[], int n)
+{
+
+    int i = 0;
+    lcd_debug("%s:%d\n", __func__, n);
+    for(i = 0; i < n; i++) {
+        if(reg_array[i] < 0x00020000) {
+            if(reg_array[i] < 20000)
+                udelay(reg_array[i]);
+            else {
+                mdelay(reg_array[i]/1000);
+            }
+        } else {
+            tc358768_wr_reg_32bits(reg_array[i]);
+        }
+    }
+    return 0;
+}
+
+#define tc358768_wr_regs_32bits(reg_array) \
+    _tc358768_wr_regs_32bits(reg_array, ARRAY_SIZE(reg_array))
+
+static uint32_t initialize[] = {
+    // **************************************************
+    // Initizlize  -> Display On after power-on
+    // **************************************************
+    // **************************************************
+    // Power on TC358768XBG according to recommended power-on sequence
+    // Relase reset (RESX="H")
+    // Start input REFCK and PCLK
+    // **************************************************
+    // **************************************************
+    // TC358768XBG Software Reset
+    // **************************************************
+    0x00020001, //SYSctl, S/W Reset
+    10,
+    0x00020000, //SYSctl, S/W Reset release
+
+    // **************************************************
+    // TC358768XBG PLL,Clock Setting
+    // **************************************************
+    0x00160063, //PLL Control Register 0 (PLL_PRD,PLL_FBD)
+    0x00180603, //PLL_FRS,PLL_LBWS, PLL oscillation enable
+    1000,
+    0x00180613, //PLL_FRS,PLL_LBWS, PLL clock out enable
+
+    // **************************************************
+    // TC358768XBG DPI Input Control
+    // **************************************************
+    0x00060064, //FIFO Control Register
+
+    // **************************************************
+    // TC358768XBG D-PHY Setting
+    // **************************************************
+    0x01400000, //D-PHY Clock lane enable
+    0x01420000, //
+    0x01440000, //D-PHY Data lane0 enable
+    0x01460000, //
+    0x01480000, //D-PHY Data lane1 enable
+    0x014A0000, //
+    0x014C0001, //
+    0x014E0001, //
+    0x01500001, //
+    0x01520001, //
+
+    0x01000002, //
+    0x01020000, //
+    0x01040000, //
+    0x01060002, //
+    0x01080002, //
+    0x010A0000, //
+    0x010C0002, //
+    0x010E0000, //
+    0x01100002, //
+    0x01120000, //
+    // **************************************************
+    // TC358768XBG DSI-TX PPI Control
+    // **************************************************
+    0x02100A5A, //LINEINITCNT
+    0x02120000, //
+    0x02140002, //LPTXTIMECNT
+    0x02160000, //
+    0x02180E02, //TCLK_HEADERCNT
+    0x021A0000, //
+    0x021C0000, //TCLK_TRAILCNT
+    0x021E0000, //
+    0x02200002, //THS_HEADERCNT
+    0x02220000, //
+    0x02244650, //TWAKEUPCNT
+    0x02260000, //
+    0x02280000, //TCLK_POSTCNT
+    0x022A0000, //
+    0x022C0001, //THS_TRAILCNT
+    0x022E0000, //
+    0x02300005, //HSTXVREGCNT
+    0x02320000, //
+    0x02340007, //HSTXVREGEN enable
+    0x02360000, //
+    0x02380001, //DSI clock Enable/Disable during LP
+    0x023A0000, //
+    0x023C0002, //BTACNTRL1
+    0x023E0002, //
+    0x02040001, //STARTCNTRL
+    0x02060000, //
+
+    // **************************************************
+    // TC358768XBG DSI-TX Timing Control
+    // **************************************************
+    0x06200001, //Sync Event mode setting   Event mode
+    0x06220014, //V Control Register1   VBP
+    0x0624000C, //V Control Register2   not used
+    0x06260356, //V Control Register3   800
+    0x0628005E, //H Control Register1
+    0x062A003F, //H Control Register2
+    //0x062C0438, //H Control Register3   (480*18)/8=1080
+    0x062C05A0, //H Control Register3   (480*24)/8=1440
+
+    0x05180001, //DSI Start
+    0x051A0000, //
+};
+
+static uint32_t start_dsi_hs_mode[] = {
+
+    // **************************************************
+    // Set to HS mode
+    // **************************************************
+    0x05000083, //DSI lane setting, DSI mode=HS
+    0x0502A300, //bit set
+    0x05008000, //Switch to DSI mode
+    0x0502C300, //
+
+    // **************************************************
+    // Host: RGB(DPI) input start
+    // **************************************************
+
+    //0x00080047, //DSI-TX Format setting: RGB666
+    0x00080037, //DSI-TX Format setting//3 RGB888;4 RGB666
+    //0x0050001E, //DSI-TX Pixel stream packet Data Type setting
+    0x0050003E, //Packed Pixel Stream, 24-bit RGB, 8-8-8 Format
+    0x00320000, //HSYNC Polarity
+
+    0x00040040, //Configuration Control Register
+
+};
+
+static inline void mipi_dsi_init(void)
+{
+    tc358768_wr_regs_32bits(initialize);
+}
+
+static inline void mipi_dsi_hs_start(void)
+{
+    tc358768_wr_regs_32bits(start_dsi_hs_mode);
+}
+
+static void tc_print(u32 addr)
+{
+    lcd_debug("+++addr->%04x: %04x\n", addr, tc358768_rd_reg_32bits(addr));
+}
+
+static int tc358768_command_tx_less8bytes(unsigned char type,
+                      unsigned char *regs, int n)
+{
+    int i = 0;
+    unsigned int command[] = {
+        0x06020000,
+        0x06040000,
+        0x06100000,
+        0x06120000,
+        0x06140000,
+        0x06160000,
+    };
+
+    if(n <= 2)
+        command[0] |= 0x1000;   //short packet
+    else {
+        command[0] |= 0x4000;   //long packet
+        command[1] |= n;        //word count byte
+    }
+    command[0] |= type;        //data type
+
+    lcd_debug("*cmd:\n");
+    lcd_debug("0x%08x\n", command[0]);
+    lcd_debug("0x%08x\n", command[1]);
+
+    for(i = 0; i < (n + 1)/2; i++) {
+        command[i+2] |= regs[i*2];
+        if((i*2 + 1) < n)
+            command[i+2] |= regs[i*2 + 1] << 8;
+        lcd_debug("0x%08x\n", command[i+2]);
+    }
+
+    _tc358768_wr_regs_32bits(command, (n + 1)/2 + 2);
+    tc358768_wr_reg_32bits(0x06000001);   //Packet Transfer
+    if(regs[0] == 0x29){
+        //tc358768_wr_reg_32bits(0x06000001);
+    }
+    //wait until packet is out
+    i = 100;
+    while(tc358768_rd_reg_32bits(0x0600) & 0x01) {
+        if(i-- == 0)
+            break;
+        tc_print(0x0600);
+    }
+
+    //udelay(50);
+    return 0;
+}
+
+static int __unused tc358768_command_tx_more8bytes_hs(unsigned char type,
+                              unsigned char regs[], int n)
+{
+
+    int i = 0;
+    unsigned int dbg_data = 0x00E80000, temp = 0;
+    unsigned int command[] = {
+        0x05000080,     // HS data 4 lane, EOT is added
+        0x0502A300,
+        0x00080001,
+        0x00500000,     // Data ID setting
+        0x00220000,     // Transmission byte count= byte
+        0x00E08000, // Enable I2C/SPI write to VB
+        0x00E20048, // Total word count = 0x48 (max 0xFFF).
+                // This value should be adjusted considering
+                // trade off between transmission time and
+                // transmission start/stop time delay
+        0x00E4007F,     // Vertical blank line = 0x7F
+    };
+
+
+    command[3] |= type;        //data type
+    command[4] |= n & 0xffff;           //Transmission byte count
+
+    tc358768_wr_regs_32bits(command);
+
+    for(i = 0; i < (n + 1)/2; i++) {
+        temp = dbg_data | regs[i*2];
+        if((i*2 + 1) < n)
+            temp |= (regs[i*2 + 1] << 8);
+        lcd_debug("0x%08x\n", temp);
+        tc358768_wr_reg_32bits(temp);
+    }
+    if((n % 4 == 1) ||  (n % 4 == 2))     //4 bytes align
+        tc358768_wr_reg_32bits(dbg_data);
+
+    tc358768_wr_reg_32bits(0x00E0C000);     //Start command transmisison
+    tc358768_wr_reg_32bits(0x00E00000);  //Stop command transmission. This setting should be done just after above setting to prevent multiple output
+    udelay(200);
+    //Re-Initialize
+    //tc358768_wr_regs_32bits(re_initialize);
+    return 0;
+}
+
+static int tc358768_command_tx_more8bytes_lp(unsigned char type,
+                         unsigned char regs[], int n)
+{
+
+    int i = 0;
+    unsigned int dbg_data = 0x00E80000, temp = 0;
+    unsigned int command[] = {
+        0x00080001,
+        0x00500000,    //Data ID setting
+        0x00220000,    //Transmission byte count= byte
+        0x00E08000,    //Enable I2C/SPI write to VB
+    };
+
+    command[1] |= type;        //data type
+    command[2] |= n & 0xffff;           //Transmission byte count
+
+    tc358768_wr_regs_32bits(command);
+
+    for(i = 0; i < (n + 1)/2; i++) {
+        temp = dbg_data | regs[i*2];
+        if((i*2 + 1) < n)
+            temp |= (regs[i*2 + 1] << 8);
+        lcd_debug("0x%08x\n", temp);
+        tc358768_wr_reg_32bits(temp);
+
+    }
+    if((n % 4 == 1) ||  (n % 4 == 2))     //4 bytes align
+        tc358768_wr_reg_32bits(dbg_data);
+
+    tc358768_wr_reg_32bits(0x00E0E000);     //Start command transmisison
+    udelay(1000);
+    tc358768_wr_reg_32bits(0x00E02000);  //Keep Mask High to prevent short packets send out
+    tc358768_wr_reg_32bits(0x00E00000);  //Stop command transmission. This setting should be done just after above setting to prevent multiple output
+    udelay(10);
+    return 0;
+}
+
+int _tc358768_send_packet(unsigned char type, unsigned char regs[], int n) {
+
+    if(n <= 8) {
+        tc358768_command_tx_less8bytes(type, regs, n);
+    } else {
+        //tc358768_command_tx_more8bytes_hs(type, regs, n);
+        tc358768_command_tx_more8bytes_lp(type, regs, n);
+    }
+    return 0;
+}
+
+/*
+ * The DCS is separated into two functional areas:
+ *  the User Command Set and the Manufacturer Command Set.
+ *  Each command is an eight-bit code with 00h to AFh assigned to
+ *  the User Command Set and all other codes assigned to
+ *  the Manufacturer Command Set.
+ */
+int _mipi_dsi_send_dcs_packet(unsigned char regs[], int n) {
+
+    unsigned char type = 0;
+    if(n == 1) {
+        type = DTYPE_DCS_SWRITE_0P;
+    } else if (n == 2) {
+        type = DTYPE_DCS_SWRITE_1P;
+    } else if (n > 2) {
+        type = DTYPE_DCS_LWRITE;
+    }
+    _tc358768_send_packet(type, regs, n);
+    return 0;
+}
+
+static int tc358768_command_read_bytes(unsigned char addr,unsigned char *regs, int n)
+{
+    unsigned short *data = (unsigned short *)regs,i;
+    unsigned int command[] = {
+        0x06021037,
+        0x06040000,
+        0x06100000,
+        0x06000001,
+        0x06021000,
+        0x06040000,
+        0x06100000,
+        0x06000001,
+    };
+
+    lcd_debug("%s start addr=0x%x\n",__FUNCTION__,addr);
+
+    command[2] |= 32;
+    command[4] |= 0x14;
+    command[6] |= addr;
+
+    _tc358768_wr_regs_32bits(command,4);
+    udelay(100);
+    tc358768_wr_reg_32bits(0x05040010);
+    tc358768_wr_reg_32bits(0x05060000);
+    udelay(100);
+    _tc358768_wr_regs_32bits(&command[4],4);
+
+    while(n-- > 0){
+        *data = (unsigned short)tc358768_rd_reg_32bits(0x0430);
+        //printf("%s *data=0x%x\n",__FUNCTION__,*data);
+        data++;
+        *data = (unsigned short)tc358768_rd_reg_32bits(0x0432);
+        //printf("%s *data=0x%x\n",__FUNCTION__,*data);
+        data++;
+        udelay(100);
+    }
+
+    return 0;
+}
+
+static lcd_panel_enum tc358768_check_lcd_type(void)
+{
+    unsigned char data[50]={0},i=0;
+    int lcd_id;
+    for(i=0;i<LCD_MAX;i++)
+    {
+        tc358768_command_read_bytes(lcd_deviceid[i].addr,data,9);
+        lcd_id = (data[lcd_deviceid[i].read_start]<<8) + data[lcd_deviceid[i].read_start+1];
+        printk("%s lcd_id=0x%x,0x%x\n",__FUNCTION__,lcd_id,lcd_deviceid[i].id);
+        if(lcd_id == lcd_deviceid[i].id)
+            break;
+    }
+    return i;
+}
+
+#define mipi_dsi_send_packet(type, regs) \
+    _tc358768_send_packet(type, regs, ARRAY_SIZE(regs))
+
+#define mipi_dsi_send_dcs_packet(regs) \
+    _mipi_dsi_send_dcs_packet(regs, ARRAY_SIZE(regs))
+
+static int gl5001w_reset(void)
+{
+    printk("wangaq:gl5001w_reset\n");
+
+    gpio_direction_output(Gl5001w_Reset_Port,1);
+    mdelay(2);
+    gpio_direction_output(Gl5001w_Reset_Port,0);
+    mdelay(15);
+    gpio_direction_output(Gl5001w_Reset_Port,1);
+    mdelay(5);
+
+    return 0;
+}
+
+static int tc358768_reset(void)
+{
+    printk("wangaq:tc358768_reset\n");
+
+
+
+    gpio_direction_output(Tc358768_Reset_Port,0);
+    mdelay(20);
+    gpio_direction_output(Tc358768_Reset_Port,1);
+    mdelay(20);
+
+
+    return 0;
+}
+
+static void set_backlight_power(int on)
+{
+    printk("set_backlight_power value=%d\n",on);
+    //gpio_direction_output(BackLight_Power_PORT,on ? 1 : 0);
+
+        printk("set_backlight_power oniff=%d\n",on ? 1 : 0);
+}
+
+static void inline backlight_on(void)
+{
+    set_backlight_power(1);
+}
+
+static void inline backlight_off(void)
+{
+    set_backlight_power(0);
+}
+
+static int gl5001w_hw_init(void)
+{
+    lcd_panel_enum lcd_id;
+
+    mipi_dsi_init();
+    lcd_id = tc358768_check_lcd_type();
+    //lcd init
+    //Start of xiaogang.zhang modified on 2013-4-22 14:22 1.0
+    if(lcd_id==LCD_YT50F62C6)
+    {
+        printk("gl5001w_hw_init LCD_YT50F62C6\n");
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_FF_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_FD_4DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_F8_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_B8_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_F1_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_F2_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_FC_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_FE_1DATA);
+        msleep(360);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_EB_2DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_E0_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_E1_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_C1_4DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_C7_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_B1_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_B4_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_36_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_3A_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_21_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_B0_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_B6_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_C2_1DATA);
+
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_11_0DATA);
+        msleep(120);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_29_0DATA);
+
+        msleep(20);
+        mipi_dsi_send_dcs_packet(LCD_YT50F62C6_CMD_2C_0DATA);
+    }
+    else if(lcd_id==LCD_BT050TN)
+    {
+        printk("gl5001w_hw_init LCD_BT050TN\n");
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF00_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF00_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF80_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF80_2DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF03_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_FF03_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_2100_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_2100_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_D800_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_D800_2DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C582_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C582_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C181_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C181_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C1A1_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C1A1_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B4C0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B4C0_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C0A3_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C0A3_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C489_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C489_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C481_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C481_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C590_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C590_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C5B1_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C5B1_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_D900_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_D900_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_E100_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_E100_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_E200_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_E200_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_0000_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_0000_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B3A1_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B3A1_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B3A7_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_B3A7_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C090_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C090_6DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C1A6_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_C1A6_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CE80_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CE80_6DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CE90_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CE90_6DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEA0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEA0_14DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEB0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEB0_14DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEC0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CEC0_14DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CED0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CED0_14DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CFC6_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CFC6_2DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CFC9_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CFC9_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBC0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBC0_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBD0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBD0_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBE0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CBE0_10DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CC80_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CC80_10DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CC90_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CC90_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCA0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCA0_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCB0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCB0_10DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCC0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCC0_15DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCD0_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_CCD0_15DATA);
+
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_21_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_36_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_00_0DATA);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_11_0DATA);
+        msleep(120);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_29_0DATA);
+        msleep(20);
+        mipi_dsi_send_dcs_packet(LCD_BT050TN_CMD_2C_0DATA);
+    }
+    else if(lcd_id==LCD_ILI9806)
+    {
+        printk("gl5001w_hw_init LCD_ILI9806\n");
+
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_FF_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_BA_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_F3_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_F9_3DATA);
+        msleep(10);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_B0_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_BC_23DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_BD_8DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_BE_17DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_ED_2DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_B4_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_B5_4DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_C0_3DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_C1_4DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_D7_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_D8_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_FC_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_E0_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_E1_16DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_D5_8DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_F7_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_C7_1DATA);
+        msleep(10);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_36_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_51_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_53_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_55_1DATA);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_11_0DATA);
+        msleep(120);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_29_0DATA);
+        msleep(20);
+        mipi_dsi_send_dcs_packet(LCD_ILI9806_CMD_2C_0DATA);
+    }
+    else if(lcd_id==LCD_OTM8019A)
+    {
+        printk("gl5001w_hw_init LCD_OTM8019A\n");
+
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_1);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_2);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_3);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_4);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_5);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_6);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_7);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_8);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_9);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_10);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_11);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_12);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_13);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_14);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_15);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_16);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_17);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_18);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_19);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_20);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_21);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_22);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_23);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_24);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_25);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_26);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_27);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_28);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_29);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_30);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_31);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_32);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_33);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_34);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_35);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_36);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_37);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_38);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_39);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_40);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_41);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_42);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_43);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_44);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_45);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_46);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_47);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_48);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_49);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_50);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_51);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_52);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_53);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_54);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_55);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_56);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_57);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_58);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_59);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_60);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_61);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_62);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_63);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_64);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_65);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_66);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_67);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_68);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_69);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_70);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_71);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_72);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_73);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_74);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_76);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_77);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_78);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_79);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_80);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_81);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_82);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_83);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_84);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_85);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_86);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_87);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_88);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_89);
+        msleep(120);
+        mipi_dsi_send_dcs_packet(LCD_OTM8019A_CMD_90);
+        msleep(120);
+
+    }
+    else
+    {
+        printk("gl5001w_hw_init can't find lcd-\n");
+        return 0;
+    }
+    msleep(1);
+    mipi_dsi_hs_start();
+    msleep(10);
+
+    return 0;
+}
+
+
+static void lcd_gl5001w_power_on(void)
+{
+    int ret;
+
+    printk("lcd_gl5001w_power_on\n");
+    gl5001w_reset();
+    tc358768_reset();
+
+    ret = tc358768_rd_reg_32bits(0);
+    if(ret == 0x4401) {
+        printk("+TC358768AXBG works ok\n");
+    } else {
+        printk("+TC358768AXBG error , read:0x%0x\n", ret);
+        return;
+    }
+
+    gl5001w_hw_init();
+}
+
+static void lcd_gl5001w_power_off(void)
+{
+    printk("lcd_gl5001w_power_off\n");
+
+    gpio_direction_output(Gl5001w_Reset_Port,0);
+
+    lcd_init_gl500 = true;
+}
+
+static int tc358768_probe(struct i2c_client *client,
+              const struct i2c_device_id *did)
+{
+    struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
+    int ret = 0;
+
+    if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
+        dev_warn(&adapter->dev,
+             "I2C-Adapter doesn't support I2C_FUNC_I2C\n");
+        return -EIO;
+    }
+
+    tc358768_client = client;
+    return ret;
+}
+
+static int tc358768_remove(struct i2c_client *client)
+{
+    return 0;
+}
+
+static const struct i2c_device_id tc358768_id[] = {
+    { DRIVER_NAME, 0 },
+    {},
+};
+MODULE_DEVICE_TABLE(i2c, tc358768_id);
+
+
+
+
+
+
+static void cw500_resume_work_func(struct work_struct *work)
+{
+    save=0;
+    //printk("-cw500_resume_work_func-\n");
+    lcd_set_enable(1);
+    lcd_gl5001w_power_on();
+    return NULL;
+}
+
+
+static int  get_gpio_lcd_gl5001w(void)
+{
+    int ret = 0;
+    ret = gpio_request(Gl5001w_Reset_Port,"Gl5001w_Reset_Port");
+    if (ret){
+        printk("gpio_request Gl5001w_Reset_Port for GL5001W failed\n");
+        goto err_get;
+    }
+
+    ret = gpio_request(Tc358768_Reset_Port,"Tc358768_Reset_Port");
+    if (ret){
+        printk("gpio_request Tc358768_Reset_Port for Tc358768 failed\n");
+        goto err_get;
+    }
+    //ret = gpio_request(BackLight_Power_PORT,"BackLight_Power_PORT");
+    //if (ret){
+    //  printk("gpio_request BackLight_Power_PORT for backlight failed\n");
+    //  goto err_get;
+    //}
+    return 0;
+err_get:
+    return -1;
+}
+static void  put_gpio_lcd_gl5001w(void)
+{
+    gpio_free(Gl5001w_Reset_Port);
+    gpio_free(Tc358768_Reset_Port);
+    //gpio_free(BackLight_Power_PORT);
+    return;
+}
+
+
+static int cw500_gl5001_suspend(struct i2c_client *c, pm_message_t state)
+{
+        save=1;
+    printk("-cw500_gl5001_suspend-\n");
+    put_gpio_lcd_gl5001w();
+    return 0;
+}
+
+
+static int cw500_gl5001_resume(struct i2c_client *c)
+{
+
+    printk("-cw500_gl5001_resume\n");
+    get_gpio_lcd_gl5001w();
+    schedule_work(&data->cw500_resume_work);
+    return 0;
+}
+
+static struct i2c_driver tc358768_driver = {
+    .driver = {
+        .name = DRIVER_NAME,
+    },
+    .probe = tc358768_probe,
+    .remove = __devexit_p(tc358768_remove),
+    .id_table = tc358768_id,
+    .resume= cw500_gl5001_resume,
+    .suspend= cw500_gl5001_suspend,
+};
+
+static void lcd_set_power(int status)
+{
+
+
+    if (!lcd_init_gl500) {
+        return;
+    }
+
+    if (save==0) {
+        return;
+    }
+
+    if (status == LCD_POWER_ON)
+        {
+        lcd_gl5001w_power_on();
+        lcd_init_gl500 = false;
+        }
+}
+
+static struct lcd_parm_t lcd_gl5001w_parm = {
+    //.name = "GL5001W",
+    //.fps = 60,                /* frame per second */
+    .bits_per_pixel = 24,
+    .capability = 0,
+    .width = 480,
+    .height = 854,
+    .vmode = {
+        .name = "GL5001W",          // mipi_480x800
+        .refresh = 60,
+        .xres = 480,
+        .yres = 854,
+        .pixclock = KHZ2PICOS(26000),             //pixel_clock
+        .left_margin = 20,                        //hbp
+        .right_margin = 30,                       //hfp
+        .upper_margin = 12,                        //vbp
+        .lower_margin = 8,                        //vfp
+        .hsync_len = 10,                          //hsync
+        .vsync_len = 8,                           //vsync
+        .sync = 0,                                //?
+        .vmode = 0,
+        .flag = 0,
+    },
+    //.initial = dummy_call_path,
+    //.uninitial = lcd_gl5001w_power_off,
+    //.set_power = lcd_set_power,
+};
+
+static struct lcd_parm_t *lcd_gl5001w_get_parm(int arg)
+{
+    return &lcd_gl5001w_parm;
+}
+
+static int wmt_check_devices(void)
+{
+    int ret = 0;
+    int param[7];
+        char buf[96] = {0};
+    int len = sizeof(buf);
+
+    ret = wmt_getsyspara("wmt.display.fb0", buf, &len);
+    if (ret) {
+        pr_err("Read wmt.display.param Failed.\n");
+        return -ENODEV;
+    }
+
+    ret = vpp_parse_param(buf, param, 6, 0);
+    if (ret < 2)
+        return -ENODEV;
+
+    if (param[3] != LCD_GL5001W)
+        return -ENODEV;
+
+    return 0;
+}
+
+static struct i2c_board_info i2c_board_info = {
+    I2C_BOARD_INFO(DRIVER_NAME, I2C_ADDR),
+};
+
+#if 0
+static int tc358768_proc(char *page, char **start, off_t off,
+        int count, int *eof, void *data)
+{
+    lcd_gl5001w_power_on();
+    return 0;
+}
+#endif
+
+static int __init gl5001w_init(void)
+{
+    int ret;
+    struct i2c_client *client;
+    struct i2c_adapter *adap;
+    unsigned char buf[40];
+    int buflen = 40;
+    unsigned int value;
+    char *endp;
+
+    if(wmt_getsyspara("wmt.support.lcd.gl5001w", buf, &buflen) == 0) {
+        value = simple_strtoul(buf, &endp, 0);
+        if(value == 0)
+            return -1;
+    } else
+        return -1;
+
+    ret = gpio_request(Gl5001w_Reset_Port,"Gl5001w_Reset_Port");
+    if (ret){
+        printk("gpio_request Gl5001w_Reset_Port for GL5001W failed\n");
+        goto err_get;
+    }
+
+    ret = gpio_request(Tc358768_Reset_Port,"Tc358768_Reset_Port");
+    if (ret){
+        printk("gpio_request Tc358768_Reset_Port for Tc358768 failed\n");
+        goto err_get;
+    }
+    //ret = gpio_request(BackLight_Power_PORT,"BackLight_Power_PORT");
+    //if (ret){
+    //  printk("gpio_request BackLight_Power_PORT for backlight failed\n");
+    //  goto err_get;
+    //}
+
+    data = kzalloc(sizeof(struct cw500_data), GFP_KERNEL);
+
+    INIT_WORK(&data->cw500_resume_work, cw500_resume_work_func);
+
+    ret = wmt_check_devices();
+    if (ret) {
+        pr_info("LCD GL5001W not found\n");
+        return -ENODEV;
+    }
+
+    adap = i2c_get_adapter(I2C_ADAPTER);
+    if (!adap)
+        return -ENODEV;
+    client = i2c_new_device(adap, &i2c_board_info);
+    i2c_put_adapter(adap);
+    if (!client) {
+        printk("i2c_new_device error\n");
+        return -ENODEV;
+    }
+
+    ret = i2c_add_driver(&tc358768_driver);
+    if (ret) {
+        return -EIO;
+    }
+
+    ret = lcd_panel_register(LCD_GL5001W,(void *) lcd_gl5001w_get_parm);
+    if (ret) {
+        i2c_del_driver(&tc358768_driver);
+        return -ENODEV;
+    }
+
+    /* for debug */
+    //create_proc_read_entry(DRIVER_NAME, 0666, NULL, tc358768_proc, NULL);
+    return 0;
+err_get:
+    return -1;
+}
+
+static void __exit gl5001w_exit(void)
+{
+    struct i2c_client *client = tc358768_client;
+    gpio_free(Gl5001w_Reset_Port);
+    gpio_free(Tc358768_Reset_Port);
+    //gpio_free(BackLight_Power_PORT);
+    i2c_unregister_device(client);
+    return i2c_del_driver(&tc358768_driver);
+}
+
+module_init(gl5001w_init);
+module_exit(gl5001w_exit);
+
+MODULE_DESCRIPTION("WonderMedia GL5001W LCD Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("i2c:gl5001w");
+
diff --git a/drivers/video/wmt/devices/lcd-lvds-1024x600.c b/drivers/video/wmt/devices/lcd-lvds-1024x600.c
new file mode 100755
index 00000000..952a2761
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-lvds-1024x600.c
@@ -0,0 +1,94 @@
+/*++
+ * linux/drivers/video/wmt/lcd-lvds-1024x600.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_LVDS_1024x600_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_LVDS_1024x600_XXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_LVDS_1024x600_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+static void lcd_LVDS_1024x600_initial(void);
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_parm_t lcd_LVDS_1024x600_parm = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_VSYNC_HI,
+	.vmode = {
+	.name = "ePAD 1024x600", /* LVDS_1024x600 */
+	.refresh = 60,
+	.xres = 1024,
+	.yres = 600,
+	.pixclock = KHZ2PICOS(45000),
+	.left_margin = 50,
+	.right_margin = 50,
+	.upper_margin = 10,
+	.lower_margin = 10,
+	.hsync_len = 4,
+	.vsync_len = 4,
+	.sync = FB_SYNC_VERT_HIGH_ACT,
+	.vmode = 0,
+	.flag = 0,
+	},
+	.width = 222,
+	.height = 125,
+	.initial = lcd_LVDS_1024x600_initial,
+};
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+static void lcd_LVDS_1024x600_initial(void)
+{
+	DPRINT("lcd_LVDS_1024x600_initial\n");
+
+	/* TODO */
+}
+
+struct lcd_parm_t *lcd_LVDS_1024x600_get_parm(int arg)
+{
+	return &lcd_LVDS_1024x600_parm;
+}
+
+int lcd_LVDS_1024x600_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_LVDS_1024x600,
+		(void *) lcd_LVDS_1024x600_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_LVDS_1024x600_init);
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_1024x600_C
diff --git a/drivers/video/wmt/devices/lcd-oem.c b/drivers/video/wmt/devices/lcd-oem.c
new file mode 100755
index 00000000..c079505e
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-oem.c
@@ -0,0 +1,430 @@
+/*++
+ * linux/drivers/video/wmt/lcd-oem.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_OEM_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_OEM_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_OEM_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+#ifdef CONFIG_UBOOT
+int lcd_bl_time;
+void lcd_uboot_set_backlight(void)
+{
+	int cur;
+	do {
+		wmt_read_ostc(&cur);
+	} while (cur < lcd_bl_time);
+	REG32_VAL(GPIO_BASE_ADDR + 0xC0) |= 0x800; /* BL( bit 11 ) */
+}
+
+#endif
+
+void lcd_oem_enable_backlight(int wait_ms)
+{
+#ifdef CONFIG_UBOOT
+	wmt_read_ostc(&lcd_bl_time);
+	lcd_bl_time += (wait_ms * 1000);
+#else
+	mdelay(wait_ms);
+	REG32_VAL(GPIO_BASE_ADDR + 0xC0) |= 0x800;
+#endif
+}
+
+#ifndef CONFIG_VPP_SHENZHEN
+static void lcd_oem_initial(void)
+{
+	outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80);
+	outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x801, GPIO_BASE_ADDR + 0xC0);
+	lcd_enable_signal(1);
+}
+
+static void lcd_oem_uninitial(void)
+{
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x801, GPIO_BASE_ADDR + 0xC0);
+	lcd_enable_signal(0);
+}
+#endif
+
+struct lcd_parm_t lcd_oem_parm = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_VSYNC_HI,
+	.vmode = {
+		.name = "WonderMedia OEM LCD (VGA 1024x768)",
+		.refresh = 60,
+		.xres = 1024,
+		.yres = 768,
+		.pixclock = KHZ2PICOS(63500),
+		.left_margin = 152,
+		.right_margin = 48,
+		.upper_margin = 23,
+		.lower_margin = 3,
+		.hsync_len = 104,
+		.vsync_len = 4,
+		.sync = FB_SYNC_VERT_HIGH_ACT,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 222,
+	.height = 125,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_initial,
+	.uninitial = lcd_oem_uninitial
+#endif
+};
+
+#ifndef CONFIG_VPP_SHENZHEN
+static void lcd_oem_1024x600_initial(void)
+{
+	outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80);
+
+	/* DVDD */
+	/* T2 > 0ms */ /* AVDD/VCOM( bit 0 ) */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x01, GPIO_BASE_ADDR + 0xC0);
+	/* T4 > 0ms */
+	/* VGH */
+	/* 0 < T6 <= 10ms */
+	lcd_enable_signal(1); /* singal, DVO enable */
+	mdelay(200); /* T12 > 200ms */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x800, GPIO_BASE_ADDR + 0xC0);
+}
+
+static void lcd_oem_1024x600_uninitial(void)
+{
+	/* BL( bit 11 ) */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x800, GPIO_BASE_ADDR + 0xC0);
+	mdelay(200); /* T12 > 200ms */
+	lcd_enable_signal(0); /* singal, DVO enable */
+	/* AVDD/VCOM( bit 0 ) */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x01, GPIO_BASE_ADDR + 0xC0);
+}
+#endif
+
+struct lcd_parm_t lcd_oem_parm_1024x600 = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_VSYNC_HI,
+	.vmode = {
+#if 1 /* 7" HHX070ML208CP21A */
+		.name = "HHX070ML208CP21A",
+		.refresh = 60,
+		.xres = 1024,
+		.yres = 600,
+		.pixclock = KHZ2PICOS(51200),
+		.left_margin = 140,
+		.right_margin = 160,
+		.upper_margin = 20,
+		.lower_margin = 12,
+		.hsync_len = 20,
+		.vsync_len = 3,
+		.sync = FB_SYNC_VERT_HIGH_ACT,
+		.vmode = 0,
+		.flag = 0,
+#else
+		.name = "ePAD 1024x600", /* HannStar HSD070PFW3 */
+		.refresh = 60,
+		.xres = 1024,
+		.yres = 600,
+		.pixclock = KHZ2PICOS(45000),
+		.left_margin = 50,
+		.right_margin = 50,
+		.upper_margin = 10,
+		.lower_margin = 10,
+		.hsync_len = 4,
+		.vsync_len = 4,
+		.sync = FB_SYNC_VERT_HIGH_ACT,
+		.vmode = 0,
+		.flag = 0,
+#endif
+	},
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_1024x600_initial,
+	.uninitial = lcd_oem_1024x600_uninitial,
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_1024x768 = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_VSYNC_HI,
+	.vmode = {
+		.name = "OEM 1024x768", /* VGA 1024x768 */
+		.refresh = 60,
+		.xres = 1024,
+		.yres = 768,
+		.pixclock = KHZ2PICOS(63500),
+		.left_margin = 152,
+		.right_margin = 48,
+		.upper_margin = 23,
+		.lower_margin = 3,
+		.hsync_len = 104,
+		.vsync_len = 4,
+		.sync = FB_SYNC_VERT_HIGH_ACT,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 222,
+	.height = 125,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_initial,
+	.uninitial = lcd_oem_uninitial
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_1366x768 = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "OEM 1366X768",
+		.refresh = 60,
+		.xres = 1366,
+		.yres = 768,
+		.pixclock = KHZ2PICOS(75440),
+		.left_margin = 98,
+		.right_margin = 31,
+		.upper_margin = 22,
+		.lower_margin = 4,
+		.hsync_len = 65,
+		.vsync_len = 12,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 293,
+	.height = 164,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_initial,
+	.uninitial = lcd_oem_uninitial
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_480x800 = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "OEM 480x800",
+		.refresh = 60,
+		.xres = 480,
+		.yres = 800,
+		.pixclock = KHZ2PICOS(27000),
+		.left_margin = 78,
+		.right_margin = 78,
+		.upper_margin = 60,
+		.lower_margin = 60,
+		.hsync_len = 4,
+		.vsync_len = 4,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_initial,
+	.uninitial = lcd_oem_uninitial
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_800x480 = {
+	.bits_per_pixel = 18,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "OEM 800x480",
+		.refresh = 48,
+		.xres = 800,
+		.yres = 480,
+		.pixclock = KHZ2PICOS(27000),
+		.left_margin = 50,
+		.right_margin = 50,
+		.upper_margin = 17,
+		.lower_margin = 16,
+		.hsync_len = 10,
+		.vsync_len = 5,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 154,
+	.height = 85,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_initial,
+	.uninitial = lcd_oem_uninitial
+#endif
+};
+
+#ifndef CONFIG_VPP_SHENZHEN
+static void lcd_oem_1280x800_initial(void)
+{
+	DBG_MSG("lcd 10 power sequence\n");
+	outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801, GPIO_BASE_ADDR + 0x80);
+
+	/* VDD on */
+	/* 0 < T < 50ms */
+	lcd_enable_signal(1); /* singal on */
+	/* VGH,VGL low */ /* AVDD/VCOM( bit 0 ) */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x01, GPIO_BASE_ADDR + 0xC0);
+	mdelay(150); /* T5 > 120ms */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x800, GPIO_BASE_ADDR + 0xC0);
+}
+
+static void lcd_oem_1280x800_uninitial(void)
+{
+	/* turn off backlight */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x800, GPIO_BASE_ADDR + 0xC0);
+	mdelay(150);
+	/* turn off LCD */
+	outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x01, GPIO_BASE_ADDR + 0xC0);
+	lcd_enable_signal(0); /* turn off singal */
+}
+#endif
+
+struct lcd_parm_t lcd_oem_parm_800x1280 = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "WY101ML369IN30A",
+		.refresh = 60,
+		.xres = 800,
+		.yres = 1280,
+		.pixclock = KHZ2PICOS(71100),
+		.left_margin = 70,
+		.right_margin = 80,
+		.upper_margin = 10,
+		.lower_margin = 10,
+		.hsync_len = 10,
+		.vsync_len = 3,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 135,
+	.height = 217,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_1280x800_initial,
+	.uninitial = lcd_oem_1280x800_uninitial,
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_1280x800 = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "WY101ML369IN30A",
+		.refresh = 60,
+		.xres = 1280,
+		.yres = 800,
+		.pixclock = KHZ2PICOS(71100),
+		.left_margin = 70,
+		.right_margin = 80,
+		.upper_margin = 10,
+		.lower_margin = 10,
+		.hsync_len = 10,
+		.vsync_len = 3,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+	.width = 217,
+	.height = 135,
+#ifndef CONFIG_VPP_SHENZHEN
+	.initial = lcd_oem_1280x800_initial,
+	.uninitial = lcd_oem_1280x800_uninitial,
+#endif
+};
+
+struct lcd_parm_t lcd_oem_parm_768x1024 = {
+	.bits_per_pixel = 24,
+	.capability = LCD_CAP_CLK_HI,
+	.vmode = {
+		.name = "oem_768x1024",
+		.refresh = 60,
+		.xres = 768,
+		.yres = 1024,
+		.pixclock = KHZ2PICOS(59300),
+		.left_margin = 80,
+		.right_margin = 80,
+		.upper_margin = 23,
+		.lower_margin = 18,
+		.hsync_len = 7,
+		.vsync_len = 5,
+		.sync = 0,
+		.vmode = 0,
+		.flag = 0,
+	},
+};
+
+/*----------------------- Function Body --------------------------------------*/
+struct lcd_parm_t *lcd_oem_get_parm(int arg)
+{
+	return &lcd_oem_parm;
+}
+
+int lcd_oem_init(void)
+{
+	int ret;
+
+	ret = lcd_panel_register(LCD_WMT_OEM, (void *)lcd_oem_get_parm);
+	return ret;
+} /* End of lcd_oem_init */
+module_init(lcd_oem_init);
+
+struct lcd_parm_t *lcd_get_oem_parm(int resx, int resy)
+{
+	struct lcd_parm_t *oem_parm[] = {
+		&lcd_oem_parm_480x800,
+		&lcd_oem_parm_1024x600,
+		&lcd_oem_parm_1024x768,
+		&lcd_oem_parm_1366x768,
+		&lcd_oem_parm_800x480,
+		&lcd_oem_parm_800x1280,
+		&lcd_oem_parm_1280x800,
+		&lcd_oem_parm_768x1024,
+		0
+	};
+	struct lcd_parm_t *p;
+	int i;
+
+	for (i = 0; ; i++) {
+		p = oem_parm[i];
+		if (p == 0) {
+			p = oem_parm[0];
+			break;
+		}
+		if ((resx == p->vmode.xres) && (resy == p->vmode.yres))
+			break;
+	}
+	return p;
+}
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_OEM_C
diff --git a/drivers/video/wmt/devices/lcd-setup.c b/drivers/video/wmt/devices/lcd-setup.c
new file mode 100755
index 00000000..798f020e
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-setup.c
@@ -0,0 +1,311 @@
+/*
+ * ==========================================================================
+ *
+ *       Filename:  lcd-setup.c
+ *
+ *    Description:  
+ *
+ *        Version:  0.01
+ *        Created:  2014.6.6
+ *
+ *        Author:  SamMei
+ *        Company:  
+ *
+ * ==========================================================================
+ */
+
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+#include <linux/i2c.h>
+#include <mach/hardware.h>
+#include <mach/wmt-spi.h>
+#include <linux/gpio.h>
+#include <mach/wmt_iomux.h>
+#include "../lcd.h"
+
+#define DRIVERNAME	"lcd-setup"
+
+#undef pr_err
+#undef pr_info
+#undef pr_warning
+#define pr_err(fmt, args...)		printk("[" DRIVERNAME "] " fmt, ##args)
+#define pr_info(fmt, args...)		printk("[" DRIVERNAME "] " fmt, ##args)
+#define pr_warning(fmt, args...)	printk("[" DRIVERNAME "] " fmt, ##args)
+
+enum {
+	LCD_SETUP_TS8224B,                      /* spi init */
+	LCD_SETUP_CHUNGHWA,                     /* i2c init */
+	LCD_SETUP_MAX,
+};
+
+static int lcd_setup_id = -1;
+struct spi_device *g_spi_device;
+
+static int wmt_lcd_setup_id(void)
+{
+	char buf[32];
+	int len = sizeof(buf);
+	int id;
+
+	if (wmt_getsyspara("wmt.lcd.setup", buf, &len))
+		id = -ENODEV;
+	sscanf(buf, "%d", &id);
+	return id;
+}
+
+static inline void spi_ctrl_9bit_tx(u8 val, int cmd_data)
+{
+	uint8_t buf[2];
+
+	if (cmd_data)
+		buf[0] = (val >> 1) | BIT7;
+	else
+		buf[0] = (val >> 1) & 0x7f;
+
+	buf[1] = (val << 7);
+
+	spi_write(g_spi_device, buf, sizeof(buf));
+}
+
+static inline void spi_9bit_tx(u8 val, int cmd_data)
+{
+	spi_ctrl_9bit_tx(val, cmd_data);
+}
+
+static inline int ts8224b_cmd(u8 cmd)
+{
+	spi_9bit_tx(cmd, 0);
+	return 0;
+}
+
+static inline int ts8224b_data(u8 data)
+{
+	spi_9bit_tx(data, 1);
+	return 0;
+}
+
+static int ts8224b_init(void)
+{
+	static uint16_t settings[] = {
+		#include "ts8224b.h"
+	};
+	int i;
+
+	printk(" ## %s, %d\n", __func__, __LINE__);
+
+	for (i = 0; i < ARRAY_SIZE(settings); i += 2) {
+		ts8224b_cmd(settings[i] >> 8);
+		ts8224b_data(settings[i+1]);
+	}
+
+	ts8224b_cmd(0x11);
+	msleep(120);
+
+	ts8224b_cmd(0x29);
+	msleep(50);
+	ts8224b_cmd(0x2c);
+	return 0;
+}
+
+extern void lcd_power_on(bool on);
+
+//int lcd_spi_resume(struct spi_device *spi)
+int lcd_spi_resume(void)
+{
+	//printk(" ## %s, %d\n", __func__, __LINE__);
+	switch (lcd_setup_id) {
+	case LCD_SETUP_TS8224B:
+		printk(" ## %s, %d\n", __func__, __LINE__);
+		lcd_power_on(1);
+		mdelay(5);
+		return ts8224b_init();
+	default:
+		return 0;
+	}
+}
+
+static int __devinit lcd_spi_probe(struct spi_device *spi)
+{
+	g_spi_device = spi;
+
+	//lcd_spi_resume();
+
+	return 0;
+}
+
+static struct spi_driver lcd_spi_driver = {
+	.driver = {
+		.name = DRIVERNAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = lcd_spi_probe,
+	//.resume = lcd_spi_resume,
+};
+
+static struct spi_board_info lcd_spi_info[] __initdata = {
+	{
+		.modalias	= DRIVERNAME,
+		.bus_num	= 0,
+		.chip_select	= 0,
+		.max_speed_hz	= 12000000,
+		.irq		= -1,
+		.mode		= SPI_CLK_MODE1,
+	},
+};
+
+
+// I2C
+
+static int lcd_i2c_resume(struct i2c_client *client)
+{
+	static uint8_t init_data[] = {
+		0x4b, 0x01,
+		0x0c, 0x01,
+		0x05, 0x03,
+		0x41, 0x03,
+		0x10, 0x06,
+		0x11, 0xE0,
+		0x12, 0x00,
+		0x13, 0x3C,
+		0x14, 0x06,
+		0x15, 0x40,
+		0x16, 0x03,
+		0x17, 0x9E,
+		0x18, 0x00,
+		0x19, 0x10,
+		0x1a, 0x03,
+		0x1b, 0x84,
+		0x1c, 0x80,
+		0x1d, 0x0A,
+		0x1e, 0x80,
+		0x1f, 0x06,
+		0x3c, 0x17,
+		0x3e, 0x16,
+		0x36, 0x00,
+		0x31, 0x00,
+		0x35, 0x41,
+		0x30, 0xB0,
+		0x30, 0xB1,
+		0x00, 0x0B,
+	};
+
+	int i, ret;
+
+	printk(" ## %s, %d\n", __FUNCTION__, __LINE__);
+	for (i = 0; i < ARRAY_SIZE(init_data); i += 2) {
+		ret = i2c_master_send(client, &init_data[i], 2);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int __devinit lcd_i2c_probe(struct i2c_client *client,
+				   const struct i2c_device_id *id)
+{
+	printk(" ## %s, %d\n", __FUNCTION__, __LINE__);
+	return 0;
+}
+
+static const struct i2c_device_id lcd_i2c_id[] = {
+	{ "lcd-i2c", 0 },
+	{ },
+};
+
+static struct i2c_driver lcd_i2c_driver = {
+	.driver    = {
+		.name  = "lcd-i2c",
+		.owner = THIS_MODULE,
+	},
+	.probe     = lcd_i2c_probe,
+//	.remove    = __devexit_p(lcd_i2c_remove),
+//	.suspend   = lcd_i2c_suspend,
+	.resume    = lcd_i2c_resume,
+//	.shutdown  = lcd_i2c_shutdown,
+	.id_table  = lcd_i2c_id,
+};
+
+static struct i2c_board_info lcd_i2c_board_info = {
+	.type          = "lcd-i2c",
+	.flags         = 0x00,
+	.addr          = 0xe0 >> 1,
+	.platform_data = NULL,
+	.archdata      = NULL,
+	.irq           = -1,
+};
+
+static struct i2c_client *i2c_client;
+static struct i2c_adapter *i2c_adap;
+
+static int __init lcd_setup_init(void)
+{
+	int ret;
+
+	lcd_setup_id = wmt_lcd_setup_id();
+	switch (lcd_setup_id) {
+
+	// SPI
+	case LCD_SETUP_TS8224B:
+		ret = spi_register_board_info(lcd_spi_info, ARRAY_SIZE(lcd_spi_info));
+		if (ret) {
+			pr_err("spi_register_board_info failed\n");
+			return ret;
+		}
+
+		ret = spi_register_driver(&lcd_spi_driver);
+		if (ret) {
+			pr_err("spi_register_driver failed\n");
+			return ret;
+		}
+
+		pr_info("spi %s register success\n", DRIVERNAME);
+		return 0;
+
+	// I2C
+	case LCD_SETUP_CHUNGHWA:
+		printk(" ## %s, %d\n", __FUNCTION__, __LINE__);
+		i2c_adap = i2c_get_adapter(1);
+		if (!i2c_adap) {
+			pr_err("Cannot get i2c adapter 1\n");
+			return -ENODEV;
+		}
+
+		i2c_client = i2c_new_device(i2c_adap, &lcd_i2c_board_info);
+		if (!i2c_client) {
+			pr_err("Unable to add I2C device for 0x%x\n",
+			       lcd_i2c_board_info.addr);
+			return -ENODEV;
+		}
+
+		return i2c_add_driver(&lcd_i2c_driver);
+
+	// INVALID
+	default:
+		return -EINVAL;
+	}
+}
+
+static void lcd_setup_exit(void)
+{
+	switch (lcd_setup_id) {
+
+	// SPI
+	case LCD_SETUP_TS8224B:
+		spi_unregister_driver(&lcd_spi_driver);
+		break;
+
+	// I2C
+	case LCD_SETUP_CHUNGHWA:
+		i2c_put_adapter(i2c_adap);
+		i2c_del_driver(&lcd_i2c_driver);
+		i2c_unregister_device(i2c_client);
+		break;
+
+	// INVALID
+	default:
+		return;
+	}
+}
+
+module_init(lcd_setup_init);
+module_exit(lcd_setup_exit);
diff --git a/drivers/video/wmt/devices/lcd-spi.c b/drivers/video/wmt/devices/lcd-spi.c
new file mode 100755
index 00000000..2782806a
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd-spi.c
@@ -0,0 +1,786 @@
+#include <linux/wait.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/list.h>
+#include <linux/irq.h>
+#include <linux/jiffies.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+#include <linux/miscdevice.h>
+#include <linux/spinlock.h>
+
+#include <mach/hardware.h>
+
+#include <linux/spi/spi.h>
+#include <mach/wmt_iomux.h>
+
+#define wmt_spi_lcd_err(fmt, args...)           printk("[%s-%d] %s: " fmt, __FILE__,__LINE__,__FUNCTION__, ## args)
+#define wmt_spi_lcd_printk(fmt, ...)            wmt_spi_lcd_err(fmt, ##__VA_ARGS__)
+
+#define WMT_SPI_READ_BUF_MAX_LEN                200
+#define WMT_SPI_LCD_SPI_MODE                    SPI_MODE_0
+
+#define WMT_SPI_LCD_A0_PIN                      WMT_PIN_GP1_GPIO10
+
+#define WMT_LCD_POWER_PIN                       WMT_PIN_GP0_GPIO0
+#define WMT_WIFI_POWER_PIN                      WMT_PIN_GP1_GPIO14
+#define WMT_AIT_POWER_PIN                       WMT_PIN_GP1_GPIO12
+#define WMT_PRINT_POWER_PIN                     WMT_PIN_GP62_WAKEUP4
+#define WMT_OTG_PRINT_SWITCH_PIN                WMT_PIN_GP21_HDMIDCSDA
+
+#if 0
+typedef enum{
+    WMT_SPI_LCD_STATE_NULL,
+    WMT_SPI_LCD_STATE_HAPPY,
+    WMT_SPI_LCD_STATE_SUN,
+    WMT_SPI_LCD_STATE_CLOUDY,
+    WMT_SPI_LCD_STATE_SAD,
+    WMT_SPI_LCD_STATE_PRINT,
+    WMT_SPI_LCD_STATE_MESSAGE,
+    WMT_SPI_LCD_STATE_MAX
+}wmt_sub_lcd_state;
+#endif
+#define WMT_SPI_LCD_IOCTL_MAGIC         0x11
+#define WMT_SPI_LCD_STATE_HAPPY         _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 0, int)
+#define WMT_SPI_LCD_STATE_SUN           _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 1, int)
+#define WMT_SPI_LCD_STATE_CLOUDY        _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 2, int)
+#define WMT_SPI_LCD_STATE_SAD           _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 3, int)
+#define WMT_SPI_LCD_STATE_PRINT         _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 4, int)
+#define WMT_SPI_LCD_STATE_MESSAGE       _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 5, int)
+
+#define WMT_WIFI_POWER                  _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 20, int)
+#define WMT_AIT_POWER                   _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 21, int)
+#define WMT_PRINT_POWER                 _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 22, int)
+#define WMT_SWITCH_OTG_PRINT            _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 23, int)
+
+#define WMT_GET_LCD_POWER               _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 30, int)
+#define WMT_GET_WIFI_POWER              _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 31, int)
+#define WMT_GET_AIT_POWER               _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 32, int)
+#define WMT_GET_PRINT_POWER             _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 33, int)
+#define WMT_GET_OTG_PRINT_STATE         _IOW(WMT_SPI_LCD_IOCTL_MAGIC, 34, int)
+
+static int wmt_sub_lcd_display_state=WMT_SPI_LCD_STATE_HAPPY;
+
+struct wmt_spi_lcd_dev  {
+    wait_queue_head_t   read_wq;
+    struct mutex        read_mutex;
+    struct spi_device   *spi;
+    struct miscdevice   sub_lcd_misc_device;
+    struct              kobject *kobj;
+    bool            irq_enabled;
+    spinlock_t      irq_enabled_lock;
+    int lcd_val;
+    int wifi_val;
+    int ait_val;
+    int print_val;
+    int otg_print_state;
+};
+
+struct wmt_spi_lcd_dev *wmt_spi_lcd_pContext;
+
+const char wmt_spi_lcd_display_happy[][64]={
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,
+    0xF0,0xF0,0xF8,0xF8,0xF8,0x7C,0x7C,0x7C,0x3E,0x3E,0x3E,0x3E,0x1E,0x1F,0x1F,0x1F,
+    0x1F,0x1F,0x1F,0x1E,0x3E,0x3E,0x3E,0x3E,0x7E,0x7C,0x7C,0xFC,0xF8,0xF8,0xF0,0xF0,
+    0xE0,0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x0F,0x07,
+    0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,
+    0x07,0x0F,0x0F,0x1F,0x3F,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x80,0xF0,0xFC,0xFF,0xFF,0xFF,0x1F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+    0xC0,0xF0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0xC0,0xF0,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0xF0,0xE0,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x1F,0x7F,0xFF,0xFF,0xFC,0xF0,0x80,0x00,
+    0xF0,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x07,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x0F,0x01,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x0F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x0F,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xF8,
+    0x0F,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0x3F,
+    0x00,0x01,0x0F,0x3F,0xFF,0xFF,0xFE,0xF8,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x07,0x0F,0x3F,0x7F,0x7F,0xFC,0xF8,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,
+    0xE0,0xE0,0xE0,0xF0,0xF0,0xF8,0xFC,0x7F,0x7F,0x3F,0x0F,0x07,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF0,0xFE,0xFF,0xFF,0x7F,0x1F,0x03,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x3F,0x7F,0xFF,0xFC,0xF8,0xF0,0xE0,0xC0,
+    0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x03,0x03,0x03,0x03,
+    0x03,0x03,0x03,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,
+    0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x07,0x07,
+    0x0F,0x1F,0x1F,0x3F,0x3E,0x3E,0x7E,0x7C,0x7C,0x7C,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,
+    0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x7C,0x7C,0x7C,0x7C,0x3E,0x3E,0x3F,0x1F,0x1F,0x0F,
+    0x0F,0x07,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
+};
+
+char wmt_spi_lcd_display_sad[][64]={
+    /* ͼ�� C:\Users\admin\Desktop\androd camera\yuhao\sad.bmp   64x64   */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xE0,0xE0,
+    0xF0,0xF0,0xF8,0xF8,0x7C,0x7C,0x7E,0x3E,0x3E,0x3E,0x1E,0x1F,0x1F,0x1F,0x1F,0x1F,
+    0x1F,0x1F,0x1F,0x1F,0x1F,0x1E,0x3E,0x3E,0x3E,0x7E,0x7C,0x7C,0xF8,0xF8,0xF0,0xF0,
+    0xE0,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xFC,0xFE,0xFF,0x3F,0x1F,0x0F,0x07,0x07,
+    0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,
+    0x07,0x07,0x0F,0x1F,0x3F,0xFF,0xFE,0xFC,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00,
+    0x00,0xC0,0xF0,0xFC,0xFF,0xFF,0x7F,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+    0xE0,0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xF8,0xF8,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0xE0,0xF0,0xF8,0xF8,0xFC,0xFC,0xFC,0xF8,0xF8,0xF0,0xE0,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x7F,0xFF,0xFF,0xFC,0xF0,0xC0,0x00,
+    0xF8,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x07,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x07,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x07,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,
+    0x1F,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xC0,0xE0,0xE0,0xE0,0xE0,
+    0xE0,0xE0,0xC0,0xC0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFF,0x1F,
+    0x00,0x03,0x0F,0x3F,0xFF,0xFF,0xFE,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x40,0xF0,0xFC,0xFE,0xFF,0x7F,0x1F,0x0F,0x07,0x07,0x03,0x03,0x03,0x03,
+    0x03,0x03,0x07,0x07,0x0F,0x1F,0x3F,0xFF,0xFE,0xFC,0xF8,0x60,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xFE,0xFF,0xFF,0x3F,0x0F,0x03,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x0F,0x3F,0x7F,0xFE,0xFC,0xF8,0xF0,0xE0,0xC0,
+    0xC0,0x80,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x00,0x00,0x00,0x00,0x80,0xC0,
+    0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7F,0x3F,0x1F,0x07,0x03,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x03,0x07,0x07,
+    0x0F,0x1F,0x1F,0x1F,0x3E,0x3E,0x7E,0x7C,0x7C,0x7C,0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,
+    0xF8,0xF8,0xF8,0xF8,0xF8,0xF8,0x7C,0x7C,0x7C,0x7E,0x3E,0x3E,0x1F,0x1F,0x1F,0x0F,
+    0x07,0x07,0x03,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+char wmt_spi_lcd_display_print[][64]={
+    /* ͼ�� C:\Users\admin\Desktop\androd camera\yuhao\print.bmp   64x64   */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0xFF,0xFF,0xFF,0x1F,
+    0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,
+    0x1F,0x1F,0x1F,0x1F,0x1F,0xFF,0xFF,0xFF,0x1E,0x3C,0x78,0xF0,0xF0,0xE0,0xC0,0x80,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0xE0,0xE0,0xE0,0xE1,0xE3,0xE7,0xEF,
+    0xFF,0xFE,0xFC,0xF8,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0xF0,0xFC,0xFE,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFE,0xFC,0xF8,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x03,0x03,0x03,0x03,0x03,0x83,0x83,0x83,0x83,0x83,
+    0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+    0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,
+    0x83,0x83,0x83,0x83,0x83,0x03,0x03,0x03,0x03,0x03,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0x0F,
+    0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+    0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,
+    0x0F,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0x01,0x07,0x0F,0x1F,0x1F,0x3F,0x3F,0x3F,0x3F,0x3F,0xBF,0xFF,0xFF,0xFF,0xFF,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0xFF,0xFF,0xFF,0xFF,0xBF,0x3F,0x3F,0x3F,0x3F,0x3F,0x1F,0x1F,0x0F,0x07,0x03,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFF,0xF0,
+    0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
+    0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,0xF0,
+    0xF0,0xFF,0xFF,0xFF,0xFF,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+char wmt_spi_lcd_display_message[][64]={
+    /* ͼ�� C:\Users\admin\Desktop\androd camera\yuhao\message.bmp   64x64   */
+    0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,
+    0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,
+    0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xBF,0x3F,
+    0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+    0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,0x3F,
+    0x3F,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFC,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0x07,0x0F,0x1F,0x1F,0x3F,0x7F,0xFF,0xFF,
+    0xFE,0xFC,0xFC,0xF8,0xF0,0xF0,0xE0,0xC0,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xC0,0xE0,0xF0,0xF8,0xF8,0xFC,0xFE,0xFF,
+    0xFF,0x7F,0x3F,0x3F,0x1F,0x0F,0x07,0x07,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x01,0x03,0x03,0x07,0x0F,0x1F,0x1F,0x3F,0x7F,0x7F,0xFF,0xFE,0xFC,0xFC,0xF8,0xF0,
+    0xF8,0xF8,0xFC,0xFE,0xFF,0xFF,0x7F,0x3F,0x3F,0x1F,0x0F,0x07,0x07,0x03,0x01,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x03,0x07,0x07,
+    0x07,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
+    0x3F,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
+    0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
+    0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,
+    0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+
+const char wmt_spi_lcd_display_sun[][64]={
+    /* ͼ�� C:\Users\admin\Desktop\androd camera\yuhao\sun.bmp   64x64   */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,
+    0xF0,0xF0,0xF0,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xFE,0xFF,
+    0xFF,0xFE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0xF0,0xF0,0xF0,
+    0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+    0x03,0x0F,0x3F,0x7F,0x7F,0x7E,0x78,0x00,0x00,0x00,0x00,0x80,0x80,0x87,0x8F,0x8F,
+    0x8F,0x8F,0x87,0x80,0x80,0x00,0x00,0x00,0x30,0x7C,0x7F,0x7F,0x7F,0x3F,0x0F,0x03,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x80,0x80,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x07,0x0F,0x0F,0x1F,0x1F,0x3F,0x7E,0x7E,0x7C,0x7C,0x78,0x00,
+    0x00,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0x7E,0x3F,0x3F,0x1F,0x1F,0x0F,0x0F,0x0F,0x0F,
+    0x0F,0x0F,0x0F,0x0F,0x1F,0x1F,0x3F,0x7F,0x7E,0xFC,0xFC,0xF8,0xF0,0xE0,0x80,0x00,
+    0x30,0x78,0x7C,0x7C,0x7E,0x3F,0x3F,0x1F,0x1F,0x0F,0x0F,0x07,0x00,0x00,0x00,0x00,
+    0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0xF8,
+    0xFF,0xFF,0xFF,0xFF,0x0F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x1F,0xFF,0xFF,0xFF,0xFE,
+    0xF8,0x00,0x00,0x80,0xC0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xC0,0x80,
+    0x01,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x00,0x00,0x00,0x1F,
+    0xFF,0xFF,0xFF,0xFF,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF8,0xFF,0xFF,0xFF,0x7F,
+    0x1F,0x00,0x00,0x01,0x03,0x03,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x03,0x03,0x01,
+    0x00,0x00,0x00,0x00,0xE0,0xF0,0xF0,0xF8,0xFC,0xFC,0x7E,0x7E,0x3F,0x3F,0x1E,0x00,
+    0x00,0x01,0x07,0x0F,0x1F,0x3F,0x3F,0x7E,0x7E,0xFC,0xF8,0xF8,0xF0,0xF0,0xF0,0xF0,
+    0xF0,0xF0,0xF0,0xF8,0xF8,0xF8,0xFC,0x7E,0x7F,0x3F,0x1F,0x1F,0x0F,0x03,0x01,0x00,
+    0x0C,0x1E,0x3F,0x3F,0x7E,0x7E,0xFC,0xF8,0xF8,0xF0,0xF0,0xE0,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,
+    0xE0,0xF0,0xFC,0xFE,0xFF,0x7F,0x1E,0x00,0x00,0x00,0x00,0x01,0x01,0xE1,0xF1,0xF9,
+    0xF9,0xF1,0xE1,0x01,0x01,0x00,0x00,0x00,0x0C,0x3E,0x7F,0xFF,0xFE,0xFC,0xF0,0xC0,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,
+    0x0F,0x0F,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x7F,0xFF,
+    0xFF,0x7F,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x0F,
+    0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+const char wmt_spi_lcd_display_cloudy[][64]={
+    /* ͼ�� C:\Users\admin\Desktop\androd camera\yuhao\cloudy.bmp   64x64   */
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xE0,0xE0,0xE0,0xC0,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x87,0x8F,0x87,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x80,0x80,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC1,0xC1,0x81,0x80,0x80,0x18,0x38,
+    0x3C,0x1E,0x1E,0x0F,0x0F,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x0F,0x0F,0x1E,0x3E,
+    0x7C,0xF8,0xF0,0xE0,0xC0,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0xF0,0xF8,0x7C,0x3C,0x1E,0x0F,0x0F,
+    0x07,0x07,0x03,0x03,0x03,0x03,0x01,0x01,0x03,0x03,0x03,0x03,0x07,0x07,0x0F,0x0F,
+    0x1E,0x3C,0x7C,0xF8,0xF0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x03,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x20,0x70,0x70,0x70,0x70,0x20,
+    0x00,0x00,0x00,0x80,0xC0,0xE0,0xFC,0xFF,0xFF,0x0F,0x01,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x01,0x0F,0x1F,0x1F,0x0E,0x0F,0x0F,0x07,0x07,0x0F,0x0F,0x0F,0x1E,
+    0x1E,0x3C,0x78,0xF9,0xF3,0xC7,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0xF8,0xFE,0xFF,0x1F,0x07,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x81,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x03,0x0F,0x1F,0x3F,0x7C,0xF0,0xF0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
+    0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,
+    0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xE0,0xF0,
+    0xF0,0x78,0x3E,0x3F,0x0F,0x07,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+    0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,
+    0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+};
+
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+
+void wmt_spi_lcd_write_n_data(const char *wbuf,int wbuf_len)
+{
+    if(wbuf_len>=WMT_SPI_READ_BUF_MAX_LEN)
+    {
+        wmt_spi_lcd_err("error!!");
+        return;
+    }
+    gpio_direction_output(WMT_SPI_LCD_A0_PIN,1);
+    spi_write_then_read(wmt_spi_lcd_pContext->spi, wbuf, wbuf_len, NULL, 0);
+}
+
+void wmt_spi_lcd_write_data(unsigned char c)
+{
+    wmt_spi_lcd_write_n_data(&c,1);
+}
+
+
+//-------------------------------------------------------------------------------
+//�ӳ�������:lcdwc(unsigned char c).
+//����:��Һ����ʾ��������ָ��.
+//-------------------------------------------------------------------------------
+void wmt_spi_lcd_write_command(unsigned char c)
+{
+    gpio_direction_output(WMT_SPI_LCD_A0_PIN,0);
+    spi_write_then_read(wmt_spi_lcd_pContext->spi, &c, 1, NULL, 0);
+}
+
+void wmt_spi_lcd_reset(void)                     //Һ����ʾ��������ʼ���ӳ���
+{
+    #if 0
+        gpio_direction_output(WMT_SPI_LCD_RESET_PIN,0);
+        mdelay(200);
+        gpio_direction_output(WMT_SPI_LCD_RESET_PIN,1);
+        mdelay(200);
+    #endif
+    wmt_spi_lcd_write_command(0xe2);
+    mdelay(100);
+
+    wmt_spi_lcd_write_command(0x2c);/////set booster on
+    wmt_spi_lcd_write_command(0x2e); ////voltage regulator circuit on
+    wmt_spi_lcd_write_command(0x2f);//// voltage follower circuit on
+
+    wmt_spi_lcd_write_command(0xa0);//
+    wmt_spi_lcd_write_command(0xa6);//
+    mdelay(3);
+    wmt_spi_lcd_write_command(0xc8);//
+    mdelay(3);
+    wmt_spi_lcd_write_command(0xa2);//
+    mdelay(3);
+
+    wmt_spi_lcd_write_command(0xf8);  //set booster ratio
+    mdelay(2);
+    wmt_spi_lcd_write_command(0x00);  //set X2 X3 X4
+    mdelay(2);
+
+    wmt_spi_lcd_write_command(0x24);
+    mdelay(2);
+    wmt_spi_lcd_write_command(0x81);
+    mdelay(2);
+    wmt_spi_lcd_write_command(0x28);
+    mdelay(2);
+    wmt_spi_lcd_write_command(0xac);
+    mdelay(2);
+    wmt_spi_lcd_write_command(0x00);
+    mdelay(2);
+
+    wmt_spi_lcd_write_command(0xaf);
+    wmt_spi_lcd_write_command(0xA4);
+    mdelay(2);
+}
+
+
+void wmt_spi_lcd_display_picture(const char *picture)
+{
+    int page,k;
+    int skip=0;
+    for(page=0xB0;page<0xB8;page++)
+    {
+        wmt_spi_lcd_write_command(page);
+        wmt_spi_lcd_write_command(0x10);
+        wmt_spi_lcd_write_command(0x00);
+
+        for(k=0;k<8;k++)
+            wmt_spi_lcd_write_n_data(picture+skip+k*8,8);
+
+        skip+=64;
+    }
+}
+
+void wmt_spi_lcd_display_state_picture(void)
+{
+    switch(wmt_sub_lcd_display_state){
+    case WMT_SPI_LCD_STATE_HAPPY:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_happy[0]);
+        break;
+    case WMT_SPI_LCD_STATE_SUN:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_sun[0]);
+        break;
+    case WMT_SPI_LCD_STATE_CLOUDY:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_cloudy[0]);
+        break;
+    case WMT_SPI_LCD_STATE_SAD:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_sad[0]);
+        break;
+    case WMT_SPI_LCD_STATE_PRINT:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_print[0]);
+        break;
+    case WMT_SPI_LCD_STATE_MESSAGE:
+        wmt_spi_lcd_display_picture(wmt_spi_lcd_display_message[0]);
+        break;
+
+    default:
+        wmt_spi_lcd_printk("%s default wmt_sub_lcd_display_state=%d\n", __func__,wmt_sub_lcd_display_state);
+    }
+}
+
+
+static int wmt_spi_lcd_open(struct inode *inode, struct file *filp)
+{
+    struct wmt_spi_lcd_dev *spi_dev = container_of(filp->private_data,
+        struct wmt_spi_lcd_dev,
+        sub_lcd_misc_device);
+    filp->private_data = spi_dev;
+    wmt_spi_lcd_display_state_picture();
+   // mdelay(3000);
+
+    return 0;
+}
+
+static long wmt_spi_lcd_ioctl(struct file *file,
+    unsigned int cmd, unsigned long arg)
+{
+    void __user *argp = (void __user *)arg;
+    int interval, val;
+    struct wmt_spi_lcd_dev *spi_dev = file->private_data;
+
+    wmt_sub_lcd_display_state = cmd;
+    wmt_spi_lcd_display_state_picture();
+
+    switch(cmd){
+    case WMT_WIFI_POWER:
+        if(copy_from_user(&val, argp, sizeof(val)))
+            return -EFAULT;
+        if(val > 1)
+            return -EINVAL;
+        if(val)
+        {
+            gpio_direction_output(WMT_WIFI_POWER_PIN,1);
+        }
+        else
+        {
+            gpio_direction_output(WMT_WIFI_POWER_PIN,0);
+        }
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_WIFI_POWER_PIN val=%d\n",val);
+        break;
+    case WMT_AIT_POWER:
+        if(copy_from_user(&val, argp, sizeof(val)))
+            return -EFAULT;
+        if(val > 1)
+            return -EINVAL;
+        if(val)
+        {
+            gpio_direction_output(WMT_AIT_POWER_PIN,1);
+        }
+        else
+        {
+            gpio_direction_output(WMT_AIT_POWER_PIN,0);
+        }
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_AIT_POWER_PIN val=%d\n",val);
+        break;
+    case WMT_PRINT_POWER:
+        if(copy_from_user(&val, argp, sizeof(val)))
+            return -EFAULT;
+        if(val > 1)
+            return -EINVAL;
+        if(val)
+        {
+            gpio_direction_output(WMT_PRINT_POWER_PIN,1);
+        }
+        else
+        {
+            gpio_direction_output(WMT_PRINT_POWER_PIN,0);
+        }
+
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_PRINT_POWER_PIN val=%d\n",val);
+        break;
+    case WMT_SWITCH_OTG_PRINT:
+        if(copy_from_user(&val, argp, sizeof(val)))
+            return -EFAULT;
+        if(val > 1)
+            return -EINVAL;
+        if(val)
+        {
+            gpio_direction_output(WMT_OTG_PRINT_SWITCH_PIN,1);
+        }
+        else
+        {
+            gpio_direction_output(WMT_OTG_PRINT_SWITCH_PIN,0);
+        }
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_OTG_PRINT_SWITCH_PIN val=%d\n",val);
+        break;
+    case WMT_GET_LCD_POWER:
+        spi_dev->lcd_val = wmt_gpio_getpull(WMT_LCD_POWER_PIN);
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_LCD_POWER=%d\n", spi_dev->lcd_val);
+        interval = spi_dev->lcd_val;
+        if(copy_to_user(argp, &interval, sizeof(interval)))
+        {
+            wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_LCD_POWER fail\n");
+            return -EFAULT;
+        }
+        break;
+
+    case WMT_GET_WIFI_POWER:
+        spi_dev->wifi_val = wmt_gpio_getpull(WMT_WIFI_POWER_PIN);
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_WIFI_POWER=%d\n", spi_dev->wifi_val);
+        interval = spi_dev->wifi_val;
+        if(copy_to_user(argp, &interval, sizeof(interval)))
+        {
+            wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_WIFI_POWER fail\n");
+            return -EFAULT;
+        }
+        break;
+
+    case WMT_GET_AIT_POWER:
+        spi_dev->ait_val = wmt_gpio_getpull(WMT_AIT_POWER_PIN);
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_AIT_POWER=%d\n", spi_dev->ait_val);
+        interval = spi_dev->ait_val;
+        if(copy_to_user(argp, &interval, sizeof(interval)))
+        {
+            wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_AIT_POWER fail\n");
+            return -EFAULT;
+        }
+        break;
+
+    case WMT_GET_PRINT_POWER:
+        spi_dev->print_val = wmt_gpio_getpull(WMT_PRINT_POWER_PIN);
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_PRINT_POWER=%d\n", spi_dev->print_val);
+        interval = spi_dev->print_val;
+        if(copy_to_user(argp, &interval, sizeof(interval)))
+        {
+            wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_GET_PRINT_POWER fail\n");
+            return -EFAULT;
+        }
+        break;
+    case WMT_GET_OTG_PRINT_STATE:
+        spi_dev->otg_print_state = wmt_gpio_getpull(WMT_OTG_PRINT_SWITCH_PIN);
+        wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_OTG_PRINT_SWITCH_PIN=%d\n", spi_dev->otg_print_state);
+        interval = spi_dev->otg_print_state;
+        if(copy_to_user(argp, &interval, sizeof(interval)))
+        {
+            wmt_spi_lcd_printk("wmt_spi_lcd_ioctl WMT_OTG_PRINT_SWITCH_PIN fail\n");
+            return -EFAULT;
+        }
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    return 0;
+}
+
+
+static const struct file_operations wmt_spi_lcd_fops = {
+    .owner  = THIS_MODULE,
+    .llseek = no_llseek,
+    .open   = wmt_spi_lcd_open,
+    .unlocked_ioctl  = wmt_spi_lcd_ioctl,
+};
+
+
+static ssize_t wmt_spi_lcd_cat_dbg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+    return sprintf(buf, "%d\n", wmt_sub_lcd_display_state);
+}
+
+static ssize_t wmt_spi_lcd_echo_dbg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+    sscanf(buf,"%d", &wmt_sub_lcd_display_state);
+    wmt_sub_lcd_display_state += WMT_SPI_LCD_STATE_HAPPY;
+    wmt_spi_lcd_display_state_picture();
+    return count;
+}
+
+static DEVICE_ATTR(dbg, S_IRUGO | S_IWUSR, wmt_spi_lcd_cat_dbg, wmt_spi_lcd_echo_dbg);
+
+static struct attribute *sub_lcd_attributes[] = {
+    &dev_attr_dbg.attr,
+    NULL
+};
+
+static const struct attribute_group wmt_spi_lcd_group = {
+    .attrs = sub_lcd_attributes,
+};
+
+static int wmt_spi_lcd_sysfs_create_group(struct wmt_spi_lcd_dev *spi_dev, const struct attribute_group *group)
+{
+    int err;
+
+    spi_dev->kobj = kobject_create_and_add("wmt_spi_lcd", NULL) ;
+    if(!spi_dev->kobj){
+        wmt_spi_lcd_printk("kobj create failed.\n");
+        return -ENOMEM;
+    }
+
+    /* Register sysfs hooks */
+    err = sysfs_create_group(spi_dev->kobj, group);
+    if (err < 0){
+        kobject_del(spi_dev->kobj);
+        wmt_spi_lcd_printk("Create sysfs group failed!\n");
+        return -ENOMEM;
+    }
+
+    return 0;
+}
+
+static void wmt_spi_lcd_sysfs_remove_group(struct wmt_spi_lcd_dev *spi_dev, const struct attribute_group *group)
+{
+    sysfs_remove_group(spi_dev->kobj, group);
+    kobject_del(spi_dev->kobj);
+    return;
+}
+static int wmt_spi_lcd_probe(struct spi_device *spi)
+{
+    struct wmt_spi_lcd_dev *spi_dev = NULL;
+    int ret = 0;
+
+    ret = gpio_request(WMT_SPI_LCD_A0_PIN, "sub_lcd_control");
+    if (ret)
+        goto err_exit;
+
+    spi_dev = kzalloc(sizeof(*spi_dev), GFP_KERNEL);
+    if (spi_dev == NULL) {
+        wmt_spi_lcd_printk("failed to allocate memory for module data\n");
+        return -ENOMEM;
+    }
+
+    spi_dev->spi = spi;
+    spi_set_drvdata(spi, spi_dev);
+
+    ret = wmt_spi_lcd_sysfs_create_group(spi_dev, &wmt_spi_lcd_group);
+    if(ret < 0){
+        wmt_spi_lcd_printk("create sysfs group failed.\n");
+        goto exit_create_group;
+    }
+
+    /* init mutex and queues */
+    init_waitqueue_head(&spi_dev->read_wq);
+    mutex_init(&spi_dev->read_mutex);
+    spin_lock_init(&spi_dev->irq_enabled_lock);
+
+    spi_dev->sub_lcd_misc_device.minor = MISC_DYNAMIC_MINOR;
+    spi_dev->sub_lcd_misc_device.name = "wmt_spi_lcd";
+    spi_dev->sub_lcd_misc_device.fops = &wmt_spi_lcd_fops;
+
+    ret = misc_register(&spi_dev->sub_lcd_misc_device);
+    if (ret) {
+        wmt_spi_lcd_printk("%s : misc_register failed\n", __FILE__);
+        goto err_misc_register;
+    }
+
+    wmt_spi_lcd_pContext  = spi_dev;
+
+    return 0;
+
+err_misc_register:
+    mutex_destroy(&spi_dev->read_mutex);
+    kfree(spi_dev);
+err_exit:
+    gpio_free(WMT_SPI_LCD_A0_PIN);
+exit_create_group:
+    destroy_workqueue(&spi_dev->read_wq);
+
+    return ret;
+}
+
+static int wmt_spi_lcd_remove(struct spi_device *spi)
+{
+    struct wmt_spi_lcd_dev *spi_dev = wmt_spi_lcd_pContext;
+    misc_deregister(&spi_dev->sub_lcd_misc_device);
+    mutex_destroy(&spi_dev->read_mutex);
+    gpio_free(WMT_SPI_LCD_A0_PIN);
+
+    wmt_spi_lcd_sysfs_remove_group(spi_dev, &wmt_spi_lcd_group);
+    kfree(spi_dev);
+
+    return 0;
+}
+
+static int wmt_spi_lcd_suspend(struct spi_device *spi, pm_message_t mesg)
+{
+        printk("%s\n",__func__);
+
+    return 0;
+}
+
+static int wmt_spi_lcd_resume(struct spi_device *spi)
+{
+    printk("%s\n",__func__);
+    wmt_spi_lcd_reset();
+    wmt_spi_lcd_display_state_picture();
+    return 0;
+}
+
+
+static struct spi_driver wmt_spi_lcd_driver = {
+    .driver = {
+        .name         = "wmt_spi_lcd",
+        .bus        = &spi_bus_type,
+        .owner        = THIS_MODULE,
+    },
+    .probe = wmt_spi_lcd_probe,
+    .remove = wmt_spi_lcd_remove,
+    .suspend = wmt_spi_lcd_suspend,
+    .resume = wmt_spi_lcd_resume,
+};
+
+static struct spi_board_info wmt_spi_lcd_board_info[] __initdata = {
+    {
+        .modalias               = "wmt_spi_lcd",
+        .bus_num                = 0,
+        .chip_select            = 0,
+        .max_speed_hz           = 12000000,
+        .irq                    = -1,
+        .mode = SPI_MODE_0,
+        .controller_data = NULL,
+    },
+};
+
+static int wmt_spi_lcd_register_device (void)
+{
+    int ret = 0;
+    ret = spi_register_board_info(wmt_spi_lcd_board_info, ARRAY_SIZE(wmt_spi_lcd_board_info));
+    return ret;
+}
+
+static int wmt_spi_lcd_init(void)
+{
+    int ret = 0;
+    unsigned char buf[40];
+    int buflen = 40;
+    unsigned int value;
+    char *endp;
+
+    if(wmt_getsyspara("wmt.support.lcd.spi", buf, &buflen) == 0) {
+            value = simple_strtoul(buf, &endp, 0);
+            if(value == 0)
+        return -1;
+    } else
+            return -1;
+
+    if (wmt_spi_lcd_register_device()<0)
+    {
+        wmt_spi_lcd_printk(" Error to run wmt_spi_lcd_register_device()!\n");
+        return -1;
+    }
+
+    ret = spi_register_driver(&wmt_spi_lcd_driver);
+    if (ret != 0)
+        {
+        wmt_spi_lcd_printk("failed to register wmt_spi_lcd SPI driver: %d\n", ret);
+        goto out;
+    }
+
+out:
+    return ret;
+}
+
+static void wmt_spi_lcd_exit(void)
+{
+    wmt_spi_lcd_printk("Unloading wmt_spi_lcd driver\n");
+    spi_unregister_driver(&wmt_spi_lcd_driver);
+}
+
+module_init(wmt_spi_lcd_init);
+module_exit(wmt_spi_lcd_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/video/wmt/devices/lcd.c b/drivers/video/wmt/devices/lcd.c
new file mode 100755
index 00000000..a6099294
--- /dev/null
+++ b/drivers/video/wmt/devices/lcd.c
@@ -0,0 +1,440 @@
+/*++
+ * linux/drivers/video/wmt/lcd.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LCD_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../lcd.h"
+#include "../vout.h"
+#ifdef CONFIG_KERNEL
+#include <linux/gpio.h>
+#endif
+
+#ifdef CONFIG_VPP_SHENZHEN
+#include <mach/wmt_iomux.h>
+#endif
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  LCD_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LCD_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lcd_xxx_t; *//*Example*/
+struct lcd_device_t {
+    struct lcd_parm_t* (*get_parm)(int arg);
+};
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lcd.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lcd_xxx;        *//*Example*/
+struct lcd_device_t lcd_device_array[LCD_PANEL_MAX];
+int lcd_panel_on = 1;
+int lcd_pwm_enable;
+enum lcd_panel_t lcd_panel_id = LCD_PANEL_MAX;
+int lcd_panel_bpp = 24;
+
+struct vout_dev_t lcd_vout_dev_ops;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lcd_xxx(void); *//*Example*/
+enum lcd_panel_t lcd_lvds_id = LCD_PANEL_MAX;
+int lcd_type;
+
+/*----------------------- Function Body --------------------------------------*/
+/*----------------------- Backlight --------------------------------------*/
+void lcd_set_type(int type)
+{
+    lcd_type = type; /* 0-LCD, 1-LVDS */
+}
+
+int lcd_get_type(void)
+{
+    return lcd_type;
+}
+
+#ifdef CONFIG_VPP_SHENZHEN
+
+#define MAX_LCD_GPIO_NUM    5
+
+static struct {
+    int gpio;
+    int active;
+} lcd_power[MAX_LCD_GPIO_NUM] = {{-1, 0}};
+
+static int parse_uboot_param(void)
+{
+    char buf[64];
+    unsigned int parm[32];
+    int l = sizeof(buf);
+    int ret, i, gpio_num;
+
+    for(i = 0; i < MAX_LCD_GPIO_NUM; i++)
+        lcd_power[i].gpio = -1;
+
+    /*
+    * In hardware, maybe there are several gpio to control LCD power
+    * We can set the wmt.lcd.power as follows:
+    *   setenv wmt.lcd.power gpio0:active0,gpio1:active1,....,gpio4:active4
+    */
+    if (wmt_getsyspara("wmt.lcd.power", buf, &l)) {
+        pr_err("please set wmt.lcd.power\n");
+        return -EINVAL;
+    }
+
+    i = vpp_parse_param(buf, parm, 2 * MAX_LCD_GPIO_NUM, 0);
+    gpio_num = i / 2;
+
+    for(i = 0; i < gpio_num; i++) {
+
+        lcd_power[i].gpio = parm[i * 2];
+        lcd_power[i].active = parm[i * 2 + 1];
+
+        ret = gpio_request(lcd_power[i].gpio, "lcd power");
+        if (ret) {
+            pr_err("request gpio %d failed for lcd power\n",
+                lcd_power[i].gpio);
+            return ret;
+        }
+
+        DPRINT("lcd power%d: gpio%d, active %d\n",
+            i, lcd_power[i].gpio, lcd_power[i].active);
+    }
+
+    return 0;
+}
+
+void lcd_power_on(bool on)
+{
+    int i;
+
+    for(i = 0; i < MAX_LCD_GPIO_NUM; i++) {
+        if (lcd_power[i].gpio < 0)
+            return;
+
+        gpio_direction_output(lcd_power[i].gpio, on ?
+            lcd_power[i].active : !lcd_power[i].active);
+
+        DBG_MSG("lcd_power_on: i = %d, on = %d, gpio = %d, active = %d\n",
+         i, on, lcd_power[i].gpio, lcd_power[i].active);
+    }
+}
+#endif
+
+void lcd_set_lvds_id(int id)
+{
+    lcd_lvds_id = id;
+}
+
+int lcd_get_lvds_id(void)
+{
+    return lcd_lvds_id;
+}
+
+void lcd_set_parm(int id, int bpp)
+{
+    lcd_panel_id = id;
+    lcd_panel_bpp = bpp;
+}
+
+struct lcd_parm_t *lcd_get_parm(enum lcd_panel_t id, unsigned int arg)
+{
+    struct lcd_device_t *p;
+
+    p = &lcd_device_array[id];
+    if (p && p->get_parm)
+        return p->get_parm(arg);
+    return 0;
+}
+
+struct vout_dev_t *lcd_get_dev(void)
+{
+    if (lcd_panel_id >= LCD_PANEL_MAX)
+        return 0;
+    return &lcd_vout_dev_ops;
+}
+
+#ifdef CONFIG_KERNEL
+static DEFINE_SEMAPHORE(lcd_sem);
+#endif
+void lcd_set_mutex(int lock)
+{
+#ifdef CONFIG_KERNEL
+    if (lock)
+        down(&lcd_sem);
+    else
+        up(&lcd_sem);
+#endif
+}
+
+void lcd_set_enable(int enable)
+{
+    DBG_MSG("%d\n", enable);
+    if (!p_lcd)
+        return;
+
+    lcd_set_mutex(1);
+    if (enable) {
+        if (p_lcd->initial)
+            p_lcd->initial();
+        else {
+            lcd_enable_signal(1); /* singal enable */
+#ifndef CONFIG_VPP_SHENZHEN
+            outl(inl(GPIO_BASE_ADDR + 0x80) | 0x801,
+                GPIO_BASE_ADDR + 0x80);
+            outl(inl(GPIO_BASE_ADDR + 0xC0) | 0x801,
+                GPIO_BASE_ADDR + 0xC0);
+#endif
+        }
+    } else {
+        if (p_lcd->uninitial)
+            p_lcd->uninitial();
+        else {
+            lcd_enable_signal(0); /* singal disable */
+#ifndef CONFIG_VPP_SHENZHEN
+            outl(inl(GPIO_BASE_ADDR + 0xC0) & ~0x801,
+                GPIO_BASE_ADDR + 0xC0);
+#endif
+        }
+    }
+    lcd_set_mutex(0);
+}
+
+void lcd_enable_signal(int enable)
+{
+    int hdmi_off;
+
+    DBG_MSG("%d\n", enable);
+    if (lcd_get_type()) { /* LVDS */
+        /* TODO */
+    } else { /* LCD */
+        govrh_set_dvo_enable(p_govrh2, enable);
+    }
+
+    hdmi_off = (govrh_get_MIF_enable(p_govrh)) ? 0 : 1;
+    vpp_set_clock_enable(DEV_DVO, (hdmi_off && !enable) ? 0 : 1, 1);
+}
+
+#ifdef __KERNEL__
+/*----------------------- LCD --------------------------------------*/
+static int __init lcd_arg_panel_id
+(
+    char *str           /*!<; // argument string */
+)
+{
+    sscanf(str, "%d", (int *) &lcd_panel_id);
+    if (lcd_panel_id >= LCD_PANEL_MAX)
+        lcd_panel_id = LCD_PANEL_MAX;
+    DBGMSG(KERN_INFO "set lcd panel id = %d\n", lcd_panel_id);
+    return 1;
+} /* End of lcd_arg_panel_id */
+
+__setup("lcdid=", lcd_arg_panel_id);
+#endif
+int lcd_panel_register(int no, void (*get_parm)(int mode))
+{
+    struct lcd_device_t *p;
+
+    if (no >= LCD_PANEL_MAX) {
+        DBGMSG(KERN_ERR "*E* lcd device no max is %d !\n",
+            LCD_PANEL_MAX);
+        return -1;
+    }
+
+    p = &lcd_device_array[no];
+    if (p->get_parm) {
+        DBGMSG(KERN_ERR "*E* lcd device %d exist !\n", no);
+        return -1;
+    }
+    p->get_parm = (void *) get_parm;
+    return 0;
+} /* End of lcd_device_register */
+
+/*----------------------- vout device plugin --------------------------------*/
+void lcd_set_power_down(int enable)
+{
+#ifdef CONFIG_VPP_SHENZHEN
+    static int save_state = -1;
+
+    if (save_state != enable) {
+        /* lcd enable control by user */
+        lcd_power_on(enable ? false : true);
+        lcd_set_enable(enable ? false : true);
+        save_state = enable;
+    }
+#endif
+}
+
+static void wmt_config_govrh_polar(struct vout_t *vo)
+{
+    /* wmt.display.polar [clock polar]:[hsync polart]:[vsync polar]*/
+    char buf[64];
+    int l = sizeof(buf);
+    int clk_pol, hsync_pol, vsync_pol;
+    unsigned int parm[3];
+
+    if (wmt_getsyspara("wmt.display.polar", buf, &l))
+        return;
+
+    vpp_parse_param(buf, (unsigned int *)parm, 3, 0);
+    clk_pol = parm[0];
+    hsync_pol = parm[1];
+    vsync_pol = parm[2];
+    DBG_MSG("govrh polar: clk-pol %d, hsync %d, vsync %d\n",
+        clk_pol, hsync_pol, vsync_pol);
+    govrh_set_dvo_clock_delay(vo->govr, clk_pol ? 0 : 1, 0);
+    govrh_set_dvo_sync_polar(vo->govr,
+        hsync_pol ? 0 : 1, vsync_pol ? 0 : 1);
+}
+
+int lcd_set_mode(unsigned int *option)
+{
+    struct vout_t *vo;
+    enum vout_inf_mode_t inf_mode;
+
+    DBG_MSG("option %d,%d\n", option[0], option[1]);
+
+    vo = lcd_vout_dev_ops.vout;
+    inf_mode = vo->inf->mode;
+    if (option) {
+        unsigned int capability;
+
+        if (lcd_panel_id == 0)
+            p_lcd = lcd_get_oem_parm(vo->resx, vo->resy);
+        else
+            p_lcd = lcd_get_parm(lcd_panel_id, lcd_panel_bpp);
+
+        if (!p_lcd) {
+            DBG_ERR("lcd %d not support\n", lcd_panel_id);
+            return -1;
+        }
+        DBG_MSG("[%s] %s (id %d,bpp %d)\n", vout_inf_str[inf_mode],
+            p_lcd->vmode.name, lcd_panel_id, lcd_panel_bpp);
+        capability = p_lcd->capability;
+        switch (inf_mode) {
+        case VOUT_INF_LVDS:
+            lvds_set_sync_polar(
+                (capability & LCD_CAP_HSYNC_HI) ? 0 : 1,
+                (capability & LCD_CAP_VSYNC_HI) ? 0 : 1);
+            lvds_set_rgb_type(lcd_panel_bpp);
+            break;
+        case VOUT_INF_DVI:
+            govrh_set_dvo_clock_delay(vo->govr,
+                (capability & LCD_CAP_CLK_HI) ? 0 : 1, 0);
+            govrh_set_dvo_sync_polar(vo->govr,
+                (capability & LCD_CAP_HSYNC_HI) ? 0 : 1,
+                (capability & LCD_CAP_VSYNC_HI) ? 0 : 1);
+            switch (lcd_panel_bpp) {
+            case 15:
+                govrh_IGS_set_mode(vo->govr, 0, 1, 1);
+                break;
+            case 16:
+                govrh_IGS_set_mode(vo->govr, 0, 3, 1);
+                break;
+            case 18:
+                govrh_IGS_set_mode(vo->govr, 0, 2, 1);
+                break;
+            case 24:
+                govrh_IGS_set_mode(vo->govr, 0, 0, 0);
+                break;
+            default:
+                break;
+            }
+            break;
+        default:
+            break;
+        }
+    } else
+        p_lcd = 0;
+
+    wmt_config_govrh_polar(vo);
+    return 0;
+}
+
+int lcd_check_plugin(int hotplug)
+{
+    return (p_lcd) ? 1 : 0;
+}
+
+int lcd_get_edid(char *buf)
+{
+    return 1;
+}
+
+int lcd_config(struct vout_info_t *info)
+{
+    info->resx = p_lcd->vmode.xres;
+    info->resy = p_lcd->vmode.yres;
+    info->fps = p_lcd->vmode.refresh;
+    return 0;
+}
+
+int lcd_init(struct vout_t *vo)
+{
+    DBG_MSG("%d\n", lcd_panel_id);
+
+    /* vo_set_lcd_id(LCD_CHILIN_LW0700AT9003); */
+    if (lcd_panel_id >= LCD_PANEL_MAX)
+        return -1;
+
+    if (lcd_panel_id == 0)
+        p_lcd = lcd_get_oem_parm(vo->resx, vo->resy);
+    else
+        p_lcd = lcd_get_parm(lcd_panel_id, 24);
+
+    if (p_lcd == 0)
+        return -1;
+
+    /* set default parameters */
+    vo->resx = p_lcd->vmode.xres;
+    vo->resy = p_lcd->vmode.yres;
+    vo->pixclk = PICOS2KHZ(p_lcd->vmode.pixclock) * 1000;
+    return 0;
+}
+
+struct vout_dev_t lcd_vout_dev_ops = {
+    .name = "LCD",
+    .mode = VOUT_INF_DVI,
+    .capability = VOUT_DEV_CAP_FIX_RES + VOUT_DEV_CAP_FIX_PLUG,
+
+    .init = lcd_init,
+    .set_power_down = lcd_set_power_down,
+    .set_mode = lcd_set_mode,
+    .config = lcd_config,
+    .check_plugin = lcd_check_plugin,
+    .get_edid = lcd_get_edid,
+};
+
+int lcd_module_init(void)
+{
+    parse_uboot_param();
+
+    vout_device_register(&lcd_vout_dev_ops);
+    return 0;
+} /* End of lcd_module_init */
+module_init(lcd_module_init);
+/*--------------------End of Function Body -----------------------------------*/
+#undef LCD_C
diff --git a/drivers/video/wmt/devices/ts8224b.h b/drivers/video/wmt/devices/ts8224b.h
new file mode 100755
index 00000000..87866284
--- /dev/null
+++ b/drivers/video/wmt/devices/ts8224b.h
@@ -0,0 +1,446 @@
+#ifndef _TS8224B_H_
+#define _TS8224B_H_
+
+//Enable Page1	  hsd4.0
+0xFF00, 0x55,
+0xFF01, 0xAA,
+0xFF02, 0x52,
+0xFF03, 0x08,
+0xFF04, 0x80,
+
+0xF200, 0x00,
+0xF201, 0x84,
+0xF202, 0x02,
+
+0xF40A, 0x13,
+
+0xF000, 0x55,
+0xF001, 0xAA,
+0xF002, 0x52,
+0xF003, 0x08,
+0xF004, 0x01,
+
+0xB000, 0x0D,
+0xB001, 0x0D,
+0xB002, 0x0D,
+
+0xB600, 0x34,
+0xB601, 0x34,
+0xB602, 0x34,
+
+0xB100, 0x0D,
+0xB101, 0x0D,
+0xB102, 0x0D,
+
+// AVEE: manual,  -6V : -2.5xVCI)
+0xB700, 0x34,
+0xB701, 0x34,
+0xB702, 0x34,
+
+//Power Control for VCL
+0xB200, 0x00,
+0xB201, 0x00,
+0xB202, 0x00,
+
+0xB800, 0x24,
+0xB801, 0x24,
+0xB802, 0x24,
+
+// VGH: Clamp Enable,  2*AVDD-AVEE, //11V
+0xBF00, 0X01,
+
+0xB300, 0x0F,
+0xB301, 0x0F,
+0xB302, 0x0F,
+
+0xB900, 0x34,//34
+0xB901, 0x34,
+0xB902, 0x34,
+
+// VGL_REG(VGLO):-10V
+0xB500, 0x08,
+0xB501, 0x08,
+0xB502, 0x08,
+
+0xC200, 0x03,
+
+//VGL(LVGL):
+0xBA00, 0x24,
+0xBA01, 0x24,
+0xBA02, 0x24,
+
+
+// VGMP/VGSP:     4.8v
+0xBC00, 0X00,
+0xBC01, 0x78,
+0xBC02, 0X00,
+
+// VGMN/VGSN  -4.8v
+0xBD00, 0x00,
+0xBD01, 0x78,
+0xBD02, 0x00,
+
+// VCOM=-0.1
+0xBE00, 0x00,
+0xBE01, 0x80,  //2f
+//R+
+0xD100, 0x00,
+0xD101, 0x05,
+0xD102, 0x00,
+0xD103, 0x06,
+0xD104, 0x00,
+0xD105, 0x0E,
+0xD106, 0x00,
+0xD107, 0x19,
+0xD108, 0x00,
+0xD109, 0x29,
+0xD10A, 0x00,
+0xD10B, 0x55,
+0xD10C, 0x00,
+0xD10D, 0x80,
+0xD10E, 0x00,
+0xD10F, 0xC7,
+0xD110, 0x00,
+0xD111, 0xFC,
+0xD112, 0x01,
+0xD113, 0x48,
+0xD114, 0x01,
+0xD115, 0x7C,
+0xD116, 0x01,
+0xD117, 0xC5,
+0xD118, 0x01,
+0xD119, 0xFE,
+0xD11A, 0x02,
+0xD11B, 0x00,
+0xD11C, 0x02,
+0xD11D, 0x30,
+0xD11E, 0x02,
+0xD11F, 0x60,
+0xD120, 0x02,
+0xD121, 0x7A,
+0xD122, 0x02,
+0xD123, 0x9A,
+0xD124, 0x02,
+0xD125, 0xAC,
+0xD126, 0x02,
+0xD127, 0xC4,
+0xD128, 0x02,
+0xD129, 0xD3,
+0xD12A, 0x02,
+0xD12B, 0xE9,
+0xD12C, 0x02,
+0xD12D, 0xF8,
+0xD12E, 0x03,
+0xD12F, 0x0D,
+0xD130, 0x03,
+0xD131, 0x3B,
+0xD132, 0x05,
+0xD133, 0xB5,
+//G+
+0xD200, 0x00,
+0xD201, 0x05,
+0xD202, 0x00,
+0xD203, 0x06,
+0xD204, 0x00,
+0xD205, 0x0E,
+0xD206, 0x00,
+0xD207, 0x19,
+0xD208, 0x00,
+0xD209, 0x29,
+0xD20A, 0x00,
+0xD20B, 0x55,
+0xD20C, 0x00,
+0xD20D, 0x80,
+0xD20E, 0x00,
+0xD20F, 0xC7,
+0xD210, 0x00,
+0xD211, 0xFC,
+0xD212, 0x01,
+0xD213, 0x48,
+0xD214, 0x01,
+0xD215, 0x7C,
+0xD216, 0x01,
+0xD217, 0xC5,
+0xD218, 0x01,
+0xD219, 0xFE,
+0xD21A, 0x02,
+0xD21B, 0x00,
+0xD21C, 0x02,
+0xD21D, 0x30,
+0xD21E, 0x02,
+0xD21F, 0x60,
+0xD220, 0x02,
+0xD221, 0x7A,
+0xD222, 0x02,
+0xD223, 0x9A,
+0xD224, 0x02,
+0xD225, 0xAC,
+0xD226, 0x02,
+0xD227, 0xC4,
+0xD228, 0x02,
+0xD229, 0xD3,
+0xD22A, 0x02,
+0xD22B, 0xE9,
+0xD22C, 0x02,
+0xD22D, 0xF8,
+0xD22E, 0x03,
+0xD22F, 0x0D,
+0xD230, 0x03,
+0xD231, 0x3B,
+0xD232, 0x05,
+0xD233, 0xB5,
+//B+
+0xD300, 0x00,
+0xD301, 0x05,
+0xD302, 0x00,
+0xD303, 0x06,
+0xD304, 0x00,
+0xD305, 0x0E,
+0xD306, 0x00,
+0xD307, 0x19,
+0xD308, 0x00,
+0xD309, 0x29,
+0xD30A, 0x00,
+0xD30B, 0x55,
+0xD30C, 0x00,
+0xD30D, 0x80,
+0xD30E, 0x00,
+0xD30F, 0xC7,
+0xD310, 0x00,
+0xD311, 0xFC,
+0xD312, 0x01,
+0xD313, 0x48,
+0xD314, 0x01,
+0xD315, 0x7C,
+0xD316, 0x01,
+0xD317, 0xC5,
+0xD318, 0x01,
+0xD319, 0xFE,
+0xD31A, 0x02,
+0xD31B, 0x00,
+0xD31C, 0x02,
+0xD31D, 0x30,
+0xD31E, 0x02,
+0xD31F, 0x60,
+0xD320, 0x02,
+0xD321, 0x7A,
+0xD322, 0x02,
+0xD323, 0x9A,
+0xD324, 0x02,
+0xD325, 0xAC,
+0xD326, 0x02,
+0xD327, 0xC4,
+0xD328, 0x02,
+0xD329, 0xD3,
+0xD32A, 0x02,
+0xD32B, 0xE9,
+0xD32C, 0x02,
+0xD32D, 0xF8,
+0xD32E, 0x03,
+0xD32F, 0x0D,
+0xD330, 0x03,
+0xD331, 0x3B,
+0xD332, 0x05,
+0xD333, 0xB5,
+//R-
+0xD400, 0x00,
+0xD401, 0x05,
+0xD402, 0x00,
+0xD403, 0x06,
+0xD404, 0x00,
+0xD405, 0x0E,
+0xD406, 0x00,
+0xD407, 0x19,
+0xD408, 0x00,
+0xD409, 0x29,
+0xD40A, 0x00,
+0xD40B, 0x55,
+0xD40C, 0x00,
+0xD40D, 0x80,
+0xD40E, 0x00,
+0xD40F, 0xC7,
+0xD410, 0x00,
+0xD411, 0xFC,
+0xD412, 0x01,
+0xD413, 0x48,
+0xD414, 0x01,
+0xD415, 0x7C,
+0xD416, 0x01,
+0xD417, 0xC5,
+0xD418, 0x01,
+0xD419, 0xFE,
+0xD41A, 0x02,
+0xD41B, 0x00,
+0xD41C, 0x02,
+0xD41D, 0x30,
+0xD41E, 0x02,
+0xD41F, 0x60,
+0xD420, 0x02,
+0xD421, 0x7A,
+0xD422, 0x02,
+0xD423, 0x9A,
+0xD424, 0x02,
+0xD425, 0xAC,
+0xD426, 0x02,
+0xD427, 0xC4,
+0xD428, 0x02,
+0xD429, 0xD3,
+0xD42A, 0x02,
+0xD42B, 0xE9,
+0xD42C, 0x02,
+0xD42D, 0xF8,
+0xD42E, 0x03,
+0xD42F, 0x0D,
+0xD430, 0x03,
+0xD431, 0x3B,
+0xD432, 0x05,
+0xD433, 0xB5,
+//G-
+0xD500, 0x00,
+0xD501, 0x05,
+0xD502, 0x00,
+0xD503, 0x06,
+0xD504, 0x00,
+0xD505, 0x0E,
+0xD506, 0x00,
+0xD507, 0x19,
+0xD508, 0x00,
+0xD509, 0x29,
+0xD50A, 0x00,
+0xD50B, 0x55,
+0xD50C, 0x00,
+0xD50D, 0x80,
+0xD50E, 0x00,
+0xD50F, 0xC7,
+0xD510, 0x00,
+0xD511, 0xFC,
+0xD512, 0x01,
+0xD513, 0x48,
+0xD514, 0x01,
+0xD515, 0x7C,
+0xD516, 0x01,
+0xD517, 0xC5,
+0xD518, 0x01,
+0xD519, 0xFE,
+0xD51A, 0x02,
+0xD51B, 0x00,
+0xD51C, 0x02,
+0xD51D, 0x30,
+0xD51E, 0x02,
+0xD51F, 0x60,
+0xD520, 0x02,
+0xD521, 0x7A,
+0xD522, 0x02,
+0xD523, 0x9A,
+0xD524, 0x02,
+0xD525, 0xAC,
+0xD526, 0x02,
+0xD527, 0xC4,
+0xD528, 0x02,
+0xD529, 0xD3,
+0xD52A, 0x02,
+0xD52B, 0xE9,
+0xD52C, 0x02,
+0xD52D, 0xF8,
+0xD52E, 0x03,
+0xD52F, 0x0D,
+0xD530, 0x03,
+0xD531, 0x3B,
+0xD532, 0x05,
+0xD533, 0xB5,
+//B-
+0xD600, 0x00,
+0xD601, 0x05,
+0xD602, 0x00,
+0xD603, 0x06,
+0xD604, 0x00,
+0xD605, 0x0E,
+0xD606, 0x00,
+0xD607, 0x19,
+0xD608, 0x00,
+0xD609, 0x29,
+0xD60A, 0x00,
+0xD60B, 0x55,
+0xD60C, 0x00,
+0xD60D, 0x80,
+0xD60E, 0x00,
+0xD60F, 0xC7,
+0xD610, 0x00,
+0xD611, 0xFC,
+0xD612, 0x01,
+0xD613, 0x48,
+0xD614, 0x01,
+0xD615, 0x7C,
+0xD616, 0x01,
+0xD617, 0xC5,
+0xD618, 0x01,
+0xD619, 0xFE,
+0xD61A, 0x02,
+0xD61B, 0x00,
+0xD61C, 0x02,
+0xD61D, 0x30,
+0xD61E, 0x02,
+0xD61F, 0x60,
+0xD620, 0x02,
+0xD621, 0x7A,
+0xD622, 0x02,
+0xD623, 0x9A,
+0xD624, 0x02,
+0xD625, 0xAC,
+0xD626, 0x02,
+0xD627, 0xC4,
+0xD628, 0x02,
+0xD629, 0xD3,
+0xD62A, 0x02,
+0xD62B, 0xE9,
+0xD62C, 0x02,
+0xD62D, 0xF8,
+0xD62E, 0x03,
+0xD62F, 0x0D,
+0xD630, 0x03,
+0xD631, 0x3B,
+0xD632, 0x05,
+0xD633, 0xB5,
+
+//Enable Page0
+0xF000, 0x55,
+0xF001, 0xAA,
+0xF002, 0x52,
+0xF003, 0x08,
+0xF004, 0x00,
+
+
+0xB100, 0xcc,
+0xB101, 0x00,
+
+0xB600, 0x05,
+
+//// Gate EQ:
+0xB700, 0x70,
+0xB701, 0x70,
+
+//// Source EQ:
+0xB800, 0x01,
+0xB801, 0x03,
+0xB802, 0x03,
+0xB803, 0x03,
+
+// #Inversion mode  (2-dot)
+0xBC00, 0x02,
+0xBC01, 0x00,
+0xBC02, 0x00,
+
+// Timing control 4H w/ 4-delay
+0xC900, 0xD0,
+0xC901, 0x02,
+0xC902, 0x50,
+0xC903, 0x50,
+0xC904, 0x50,
+// Display Timing:
+
+0x3600, 0x00,
+0x3500, 0x00,
+
+0x3a00, 0x66,
+
+#endif
diff --git a/drivers/video/wmt/devices/vt1625.c b/drivers/video/wmt/devices/vt1625.c
new file mode 100755
index 00000000..83d1a403
--- /dev/null
+++ b/drivers/video/wmt/devices/vt1625.c
@@ -0,0 +1,946 @@
+/*++
+ * linux/drivers/video/wmt/vt1625.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VT1625_C
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../vout.h"
+
+#ifdef CONFIG_KERNEL
+#include <linux/workqueue.h>
+#endif
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  VT1625_XXXX  xxxx    *//*Example*/
+#ifdef CONFIG_KERNEL
+#define CONFIG_VT1625_INTERRUPT
+#endif
+#define CONFIG_VT1625_POWER
+#define CONFIG_VM700
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VT1625_XXXX    1     *//*Example*/
+#define VT1625_ADDR 0x40
+
+enum {
+	VT1625_INPUT_SELECTION = 0x00,
+	VT1625_SYNC_SELECTION_0 = 0x01,
+	VT1625_SYNC_SELECTION_1 = 0x02,
+	VT1625_FILTER_SELECTION = 0x03,
+	VT1625_OUTPUT_MODE = 0x04,
+	VT1625_CLOCK_CONTROL = 0x05,
+
+	/* start position & overflow */
+	VT1625_OVERFLOW = 0x06,
+	VT1625_START_ACTIVE_VIDEO = 0x07,
+	VT1625_START_HORIZONTAL_POSITION = 0x08,
+	VT1625_START_VERTICAL_POSITION = 0x09,
+
+	/* amplitude factor */
+	VT1625_CR_AMPLITUDE_FACTOR = 0x0A,
+	VT1625_BLACK_LEVEL = 0x0B,
+	VT1625_Y_AMPLITUDE_FACTOR = 0x0C,
+	VT1625_CB_AMPLITUDE_FACTOR = 0x0D,
+
+	VT1625_POWER_MANAGEMENT = 0x0E,
+	VT1625_STATUS = 0x0F,
+
+	/* Hue */
+	VT1625_HUE_ADJUSTMENT = 0x10,
+	VT1625_OVERFLOW_MISC = 0x11,
+
+	/* PLL */
+	VT1625_PLL_P2 = 0x12,
+	VT1625_PLL_D = 0x13,
+	VT1625_PLL_N = 0x14,
+	VT1625_PLL_OVERFLOW = 0x15,
+
+	/* Sub Carrier */
+	VT1625_SUBCARRIER_VALUE_0 = 0x16,
+	VT1625_SUBCARRIER_VALUE_1 = 0x17,
+	VT1625_SUBCARRIER_VALUE_2 = 0x18,
+	VT1625_SUBCARRIER_VALUE_3 = 0x19,
+
+	VT1625_VERSION_ID = 0x1B,
+	VT1625_DAC_OVERFLOW = 0x1C,
+
+	/* test */
+	VT1625_TEST_0 = 0x1D,
+	VT1625_TEST_1 = 0x1E,
+
+	VT1625_FILTER_SWITCH = 0x1F,
+	VT1625_TV_SYNC_STEP = 0x20,
+	VT1625_TV_BURST_ENVELOPE_STEP = 0x21,
+	VT1625_TV_SUB_CARRIER_PHASE_ADJUST = 0x22,
+	VT1625_TV_BLANK_LEVEL = 0x23,
+	VT1625_TV_SIGNAL_OVERFLOW = 0x24,
+
+	/* DAC & GPO */
+	VT1625_DAC_SELECTION_0 = 0x4A,
+	VT1625_DAC_SELECTION_1 = 0x4B,
+	VT1625_GPO = 0x4C,
+
+	VT1625_COLBAR_LUMA_DELAY = 0x4D,
+	VT1625_UV_DELAY = 0x4E,
+	VT1625_BURST_MAX_AMPLITUDE = 0x4F,
+
+	/* Graphic timing */
+	VT1625_GRAPHIC_H_TOTAL = 0x50,
+	VT1625_GRAPHIC_H_ACTIVE = 0x51,
+	VT1625_GRAPHIC_H_OVERFLOW = 0x52,
+	VT1625_GRAPHIC_V_TOTAL = 0x53,
+	VT1625_GRAPHIC_V_OVERFLOW = 0x54,
+
+	/* TV timing */
+	VT1625_TV_H_TOTAL = 0x55,
+	VT1625_TV_H_ACTIVE = 0x56,
+	VT1625_TV_H_SYNC_WIDTH = 0x57,
+	VT1625_TV_H_OVERFLOW = 0x58,
+	VT1625_TV_BURST_START = 0x59,
+	VT1625_TV_BURST_END = 0x5A,
+	VT1625_TV_VIDEO_START = 0x5B,
+	VT1625_TV_VIDEO_END = 0x5C,
+	VT1625_TV_VIDEO_OVERFLOW = 0x5D,
+
+	/* scale factor */
+	VT1625_V_SCALE_FACTOR = 0x5E,
+	VT1625_H_SCALE_FACTOR = 0x5F,
+	VT1625_SCALE_OVERFLOW = 0x60,
+	VT1625_H_BLUR_SCALE_OVERFLOW = 0x61,
+	VT1625_ADAPTIVE_DEFLICKER_THR = 0x62,
+	VT1625_SCALE_H_TOTAL = 0x63,
+	VT1625_SCALE_H_TOTAL_OVERFLOW = 0x64,
+
+	/* Amplitude factor */
+	VT1625_PY_AMP_FACTOR = 0x65,
+	VT1625_PB_AMP_FACTOR = 0x66,
+	VT1625_PR_AMP_FACTOR = 0x67,
+
+	VT1625_POST_ADJUST = 0x68,
+	VT1625_AUTO_CORRECT_SENSE = 0x69,
+
+	/* WSS 0x6A - 0x73 */
+	VT1625_INT_WSS_2 = 0x71,
+
+	/* Close Caption 0x74 - 0x7A */
+
+	/* Signature Value 0x7B - 0x82 */
+} vt1625_reg_t;
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx vt1625_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vt1625.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  vt1625_xxx;        *//*Example*/
+
+static char vt1625_ntsc_param[] = {
+	0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x82, /* 00 - 07 */
+#ifdef CONFIG_VM700
+         0x14, 0x05, 0x6E, 0x15, 0x51, 0x50, 0x37, 0xB7, /* 08 - 0f */
+         0x00, 0x80, 0x04, 0x08, 0x08, 0x90, 0xD6, 0x7B, /* 10 - 17 */
+#else
+	0x14, 0x05, 0x6E, 0x15, 0x52, 0x4E, 0x37, 0xB7, /* 08 - 0f */
+	0x08, 0x80, 0x04, 0x08, 0x08, 0x90, 0xD6, 0x7B, /* 10 - 17 */
+#endif
+         0xF0, 0x21, 0x02, 0x50, 0x43, 0x80, 0x00, 0xFC, /* 18 - 1f */
+         0x16, 0x08, 0xDC, 0x7D, 0x02, 0x56, 0x33, 0x8F, /* 20 - 27 */
+         0x58, 0x00, 0x00, 0xA6, 0x29, 0xD4, 0x81, 0x00, /* 28 - 2f */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 37 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38 - 3f */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40 - 47 */
+#ifdef CONFIG_VM700
+         0x00, 0x00, 0xC5, 0x0F, 0x08, 0x01, 0x01, 0x43, /* 48 - 4f */
+#else
+	0x00, 0x00, 0xC5, 0x0F, 0x00, 0x01, 0x10, 0x44, /* 48 - 4f */
+#endif
+         0x59, 0xCF, 0x23, 0x0C, 0x02, 0x59, 0xCF, 0x7F, /* 50 - 57 */
+         0x23, 0x94, 0xD6, 0x00, 0x9C, 0x06, 0x00, 0x00, /* 58 - 5f */
+         0x80, 0x28, 0xFF, 0x59, 0x03, 0x55, 0x56, 0x56, /* 60 - 67 */
+         0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* 68 - 6f */
+         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 - 77 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78 - 7f */
+         0x00, 0x00, 0x00
+};
+
+static char vt1625_pal_param[] = {
+	0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x8C, /* 00 - 07 */
+#ifdef CONFIG_VM700
+         0x0E, 0x01, 0x6E, 0x00, 0x51, 0x50, 0x37, 0xB7, /* 08 - 0f */
+         0x00, 0x80, 0x04, 0x08, 0x08, 0x90, 0xCB, 0x8A, /* 10 - 17 */
+#else
+	0x0E, 0x01, 0x7a, 0x00, 0x55, 0x58, 0x37, 0xB7, /* 08 - 0f */
+	0xff, 0x87, 0x04, 0x08, 0x08, 0x90, 0xCB, 0x8A, /* 10 - 17 */
+#endif
+         0x09, 0x2A, 0x06, 0x50, 0x41, 0x80, 0x00, 0xFC, /* 18 - 1f */
+         0x17, 0x0C, 0x4E, 0x76, 0x02, 0x5F, 0x34, 0x8C, /* 20 - 27 */
+         0x4F, 0x5E, 0x15, 0xA2, 0x22, 0x80, 0xD3, 0x10, /* 28 - 2f */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 37 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 38 - 3f */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 40 - 47 */
+#ifdef CONFIG_VM700
+         0x00, 0x00, 0xC5, 0x0F, 0x08, 0x02, 0x01, 0x43, /* 48 - 4f */
+#else
+	0x00, 0x00, 0xC5, 0x0F, 0x00, 0x02, 0x10, 0x4C, /* 48 - 4f */
+#endif
+         0x5f, 0xCF, 0x23, 0x70, 0x02, 0x5F, 0xD0, 0x7F, /* 50 - 57 */
+         0x23, 0x92, 0xCE, 0xDF, 0xA0, 0x06, 0x00, 0x00, /* 58 - 5f */
+         0x80, 0x20, 0xFF, 0x5F, 0x03, 0x5f, 0x00, 0x00, /* 60 - 67 */
+         0x00, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, /* 68 - 6f */
+         0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 70 - 77 */
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 78 - 7f */
+         0x00, 0x00, 0x00
+};
+
+enum vt1625_out_t {
+	VT1625_OUT_CVBS,
+	VT1625_OUT_YUV,
+	VT1625_OUT_VGA,
+	VT1625_OUT_MAX
+};
+
+enum vt1625_out_t vt1625_out_mode;
+
+int vt1625_tv_mode;
+vdo_color_fmt vt1625_colfmt;
+
+static int pre_plugin;
+
+/*
+* VT1625 U-Boot Env to Set Register
+*/
+typedef struct {
+	unsigned char offset;
+	unsigned char value;
+} vt1625_reg_env_t;
+
+#define VT1625_REG_MAX_OFFSET  0x82  /* Register Offset: 0x00 ~ 0x82 */
+/*
+* setenv wmt.vt1625.pal.reg regOffset1=regValue1,regOffset2=regValue2,...
+* for example:
+*    setenv wmt.vt1625.pal.reg  0a=75,0c=53,23=7a,4f=48
+*    setenv wmt.vt1625.ntsc.reg 0a=75,0c=53,23=7a,4f=48
+*/
+#define VT1625_PAL_REG_ENV  "wmt.vt1625.pal.reg"
+#define VT1625_NTSC_REG_ENV "wmt.vt1625.ntsc.reg"
+
+/*
+* setenv wmt.vt1625.cvbs.always.turnon 1
+*     The cvbs is always turned on event if the av line is pluged out
+* setenv wmt.vt1625.cvbs.always.turnon 0
+*     The cvbs is turned on if the av line is pluged in.
+*     And the cvbs is turned off if the av line is pluged out
+*/
+#define VT1625_CVBS_ALWAYS_TURNON  "wmt.vt1625.cvbs.always.turnon"
+
+static int vt1625_cvbs_always_turnon;
+
+#ifdef CONFIG_KERNEL
+/*
+* VT1625 Timer to Monitor Register
+*/
+/*
+* Monitor the vt1625 register for avoiding the register is cleared.
+* 	setenv wmt.vt1625.reg.monitor 1
+*
+* If the wmt.vt1625.reg.monitor is Not set or set to 0,
+* it will not monitor the register
+*
+*/
+#define VT1625_REG_MONITOR_ENV "wmt.vt1625.reg.monitor"
+
+#define VT1625_TIMER_INTERVAL   1000   // 1000 ms
+
+static struct timer_list vt1625_timer;
+static struct work_struct vt1625_work;
+
+static void vt1625_set_tv_mode(int ntsc);
+
+#endif
+
+#ifdef CONFIG_UBOOT
+#define msleep  mdelay
+#endif
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vt1625_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+/*
+* Function: register_is_right()
+* Parametr:
+*   ntsc = 0: PAL
+*   ntsc = 1: NTSC
+* Return  :
+*   0: the register's values is wrong
+*   1: the register's values is right
+*/
+static int register_is_right(int ntsc)
+{
+	int i;
+	char buf[32];
+
+    vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+        VT1625_INPUT_SELECTION, buf, 32);
+
+    for(i = 0; i < 32; i++) {
+        /*
+        * reg 0x0E is power management register. Skip it
+        * reg 0x0F is status register. it is volatile. Skip it
+        */
+        if(i == 14 || i == 15)
+            continue;
+
+
+        if(i == 0) {
+            if(vt1625_colfmt == VDO_COL_FMT_YUV444) {
+                if(buf[0] != 0x3A)
+                    break;
+            } else {
+                if(buf[0] != 0x03)
+                    break;
+            }
+        } else {
+            if(ntsc) {
+                /*
+                * NTSC
+                */
+                if(buf[i] != vt1625_ntsc_param[i])
+                    break;
+            } else {
+                /*
+                * PAL
+                */
+                if(buf[i] != vt1625_pal_param[i])
+                    break;
+            }
+        }
+    }
+
+    if(i != 32)
+        return 0;
+    else
+        return 1;
+}
+
+#ifdef CONFIG_KERNEL
+static void vt1625_reconfig(struct work_struct *work)
+{
+    int right;
+
+	if(vt1625_tv_mode) {
+        right = register_is_right((vt1625_tv_mode == 1) ? 1 : 0);
+		if(right == 0) {
+			DBG_ERR("VT1625 Reg Error, re-init the register\n");
+
+			vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0);
+		}
+	}
+
+	mod_timer(&vt1625_timer, jiffies + msecs_to_jiffies(VT1625_TIMER_INTERVAL));
+}
+
+static DECLARE_WORK(vt1625_work, vt1625_reconfig);
+
+static void vt1625_config_timer(unsigned long fcontext)
+{
+    schedule_work(&vt1625_work);
+}
+
+static void init_vt1625_timer(void)
+{
+	char buf[40];
+	int varlen = 40;
+	char *endp;
+	int value, reg_monitor;
+
+	reg_monitor = 0;
+
+	if (wmt_getsyspara(VT1625_REG_MONITOR_ENV, buf, &varlen) == 0) {
+		value = simple_strtoul(buf, &endp, 0);
+		if( value != 0)
+			reg_monitor = 1;
+	}
+
+	if(reg_monitor) {
+		init_timer(&vt1625_timer);
+		vt1625_timer.function = vt1625_config_timer;
+		vt1625_timer.data = 0;
+	} else
+		vt1625_timer.function = NULL;
+
+}
+
+static void start_vt1625_timer(void)
+{
+	if(vt1625_timer.function)
+		mod_timer(&vt1625_timer, jiffies + msecs_to_jiffies(VT1625_TIMER_INTERVAL));
+}
+
+static void stop_vt1625_timer(void)
+{
+	if(vt1625_timer.function)
+		del_timer_sync(&vt1625_timer);
+}
+#endif
+
+/*
+* Function : vt1625_parse_reg_env
+* Parameter:
+*    p_env   : env name
+*    p_reg   : store the vt1625 register offset and value
+*    p_regnum: register number
+* Return:
+*    0  : the env is set and the env's value is available
+*   -1  : the env is Not set or the env's value is wrong
+*   -12 : no memory for parsing register env
+*/
+static int vt1625_parse_reg_env(char *p_env,
+		vt1625_reg_env_t *p_reg, int *p_regnum)
+{
+	int i;
+	char *buf;
+	int buflen = 1024;
+	unsigned int value;
+	const char *p;
+	char *endp;
+
+	buf = kmalloc(buflen, GFP_KERNEL);
+	if(buf == NULL) {
+		DBG_ERR("kzalloc fail\n");
+		return -12;
+	}
+
+	if(wmt_getsyspara(p_env, buf, &buflen) != 0) {
+		kfree(buf);
+		return -1;
+	}
+
+	*p_regnum = 0;
+	p = buf;
+
+	for(i = 0; i <= VT1625_REG_MAX_OFFSET; i++) {
+		value = simple_strtoul(p, &endp, 16);
+		if(value > VT1625_REG_MAX_OFFSET) {
+			DBG_ERR("wrong register offset\n");
+			kfree(buf);
+			return -1;
+		}
+		(p_reg + i)->offset = value;
+		/*
+		* reg_offset must be followed reg_value
+		* If reg_offset is NOT followed any reg_value, It is wrong format
+		*/
+		if(*endp == '\0'|| *(endp + 1) == '\0') {
+			DBG_ERR("wrong env(%s) format\n", p_env);
+			kfree(buf);
+			return -1;
+		}
+
+		p = endp + 1;
+
+		value = simple_strtoul(p, &endp, 16);
+		if(value > 0xFF) {
+			DBG_ERR("wrong register value\n");
+			kfree(buf);
+			return -1;
+		}
+		(p_reg + i)->value = value;
+		*p_regnum = *p_regnum + 1;
+
+		if(*endp == '\0')
+			break;
+
+		p = endp + 1;
+	}
+
+	kfree(buf);
+	return 0;
+}
+
+/*the define and struct i2c_msg were declared int linux/i2c.h*/
+void vt1625_reg_dump(void)
+{
+	int i;
+	char buf[256];
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INPUT_SELECTION,
+		buf, 128);
+	for (i = 0; i < 128; i += 8) {
+		MSG("0x%02X : 0x%02X,0x%02X,0x%02X,0x%02X",
+			i, buf[i], buf[i + 1], buf[i + 2], buf[i + 3]);
+		MSG(",0x%02X,0x%02X,0x%02X,0x%02X\n",
+			buf[i + 4], buf[i + 5], buf[i + 6], buf[i + 7]);
+	}
+}
+
+static char vt1625_get_dac_val(enum vt1625_out_t mode)
+{
+	char ret;
+
+	switch (mode) {
+	case VT1625_OUT_CVBS:
+		ret = 0x37;
+		break;
+	case VT1625_OUT_VGA:
+		ret = 0x38;
+		break;
+	case VT1625_OUT_YUV:
+	default:
+		ret = 0x0;
+		break;
+	}
+	return ret;
+}
+
+static void vt1625_set_tv_mode(int ntsc)
+{
+	char *p;
+	char buf[10];
+
+/*
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_INPUT_SELECTION, buf, 5);
+	DBG_MSG("ntsc %d, 0x%x, 0x%x\n", ntsc, buf[0], buf[4]);
+	vt1625_tv_mode = (ntsc) ? 1 : 2;
+#ifdef CONFIG_KERNEL
+	if (buf[0] && (vt1625_out_mode != VT1625_OUT_MAX)) {
+		if (ntsc && !(buf[4] & BIT0))
+			return;
+		if (!ntsc && (buf[4] & BIT0))
+			return;
+	}
+#endif
+*/
+	vt1625_tv_mode = (ntsc) ? 1 : 2;
+	if(register_is_right(ntsc))
+		return;
+
+	DBG_MSG("tv %s,mode %d\n", (ntsc) ? "NTSC" : "PAL", vt1625_out_mode);
+
+	p = (char *)((ntsc) ?  vt1625_ntsc_param : vt1625_pal_param);
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INPUT_SELECTION,
+				&p[VT1625_INPUT_SELECTION], 0x71);
+	if (vt1625_out_mode == VT1625_OUT_MAX) { /* not stable so no use */
+		buf[0] = 0x0;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_POWER_MANAGEMENT, buf, 1);
+		mdelay(10);
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_STATUS, buf, 1);
+		vt1625_out_mode = (buf[0] & 0x7) ?
+			VT1625_OUT_CVBS : VT1625_OUT_VGA;
+		DBG_MSG("get out mode %d, 0x%x\n", vt1625_out_mode, buf[0]);
+	}
+
+	if (vt1625_out_mode == VT1625_OUT_VGA) {
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_SYNC_SELECTION_1, buf, 1);
+		buf[0] |= 0xA0;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_SYNC_SELECTION_1, buf, 1);
+
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_DAC_OVERFLOW, buf, 1);
+		buf[0] |= 0x20;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_DAC_OVERFLOW, buf, 1);
+
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_TEST_1, buf, 1);
+		buf[0] |= 0x40;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_TEST_1, buf, 1);
+	} else {
+#ifdef CONFIG_VT1625_INTERRUPT
+		/* interrupt (VGA no work) */
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_INT_WSS_2, buf, 1);
+		buf[0] |= 0xA0; /* enable sense interrupt */
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_INT_WSS_2, buf, 1);
+#endif
+	}
+
+	if (vt1625_colfmt == VDO_COL_FMT_YUV444) {
+		/*
+		* Force write reg0x00 and reg0x4C
+		*/
+		buf[0] = 0x3A;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_INPUT_SELECTION, buf, 1);
+		buf[0] = 0x08;
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_GPO, buf, 1);
+	}
+
+#ifdef CONFIG_VT1625_POWER
+	buf[0] = vt1625_get_dac_val(vt1625_out_mode);
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_POWER_MANAGEMENT, buf, 1);
+#endif
+}
+
+static int vt1625_check_plugin(int hotplug)
+{
+	char buf[2];
+	char cur[1];
+	int plugin;
+
+	/*
+	* Enable VT1625 Power First
+	*/
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_POWER_MANAGEMENT, cur, 1);
+
+	buf[0] = vt1625_get_dac_val(vt1625_out_mode);
+
+	if(cur[0] != buf[0]) {
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_POWER_MANAGEMENT, buf, 1);
+
+		msleep(10);
+	}
+
+	if((vt1625_out_mode == VT1625_OUT_CVBS) && vt1625_cvbs_always_turnon)
+		return 1;
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_POWER_MANAGEMENT,
+		buf, 2);
+	plugin = ~buf[1] & (~buf[0] & 0x3F);
+	DBG_MSG("[VT1625] DAC A %d, B %d, C %d, D %d, E %d, F %d\n",
+		(plugin & 0x20) ? 1 : 0, (plugin & 0x10) ? 1 : 0,
+		(plugin & 0x08) ? 1 : 0, (plugin & 0x04) ? 1 : 0,
+		(plugin & 0x02) ? 1 : 0, (plugin & 0x01) ? 1 : 0);
+	return (plugin) ? 1 : 0;
+}
+
+static int vt1625_init(struct vout_t *vo)
+{
+	char buf[40];
+	int varlen = 40;
+	char *endp;
+	unsigned int value;
+
+	DBG_MSG("\n");
+	if (vt1625_tv_mode) { /* resume reinit */
+		MSG("[VT1625] DVI reinit\n");
+		vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0);
+		if (govrh_get_dvo_enable(p_govrh2) == 0)
+			govrh_set_dvo_enable(p_govrh2, VPP_FLAG_ENABLE);
+		pre_plugin = 0;
+		return 0;
+	}
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_VERSION_ID, buf, 1);
+	if (buf[0] != 0x50) /* check version id */
+		return -1;
+
+	if (wmt_getsyspara("wmt.display.vt1625.mode", buf, &varlen) == 0) {
+		if (memcmp(buf, "yuv", 3) == 0)
+			vt1625_out_mode = VT1625_OUT_YUV;
+		else if (memcmp(buf, "vga", 3) == 0)
+			vt1625_out_mode = VT1625_OUT_VGA;
+		else
+			vt1625_out_mode = VT1625_OUT_CVBS;
+		DPRINT("[VT1625] mode %d\n", vt1625_out_mode);
+	} else
+		vt1625_out_mode = VT1625_OUT_CVBS; /* VT1625_OUT_MAX; */
+
+#ifdef CONFIG_VM700
+	vt1625_colfmt = VDO_COL_FMT_YUV444;
+#else
+	vt1625_colfmt = VDO_COL_FMT_ARGB;
+#endif
+	if (wmt_getsyspara("wmt.display.vt1625.colfmt", buf, &varlen) == 0) {
+		if (memcmp(buf, "yuv", 3) == 0)
+			vt1625_colfmt = VDO_COL_FMT_YUV444;
+		else if (memcmp(buf, "rgb", 3) == 0)
+			vt1625_colfmt = VDO_COL_FMT_ARGB;
+	}
+
+	vo->option[0] = (unsigned int) vt1625_colfmt;
+	vo->option[1] = (unsigned int) VPP_DATAWIDHT_12;
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_INPUT_SELECTION, buf, 5);
+	if (buf[0])
+		vt1625_tv_mode = (buf[4]) ? 2 : 1;
+
+    p_govrh2->fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255;
+
+	if (wmt_getsyspara(VT1625_CVBS_ALWAYS_TURNON, buf, &varlen) == 0) {
+		value = simple_strtoul(buf, &endp, 0);
+		if(value != 0)
+			vt1625_cvbs_always_turnon = 1;
+		else
+			vt1625_cvbs_always_turnon = 0;
+	} else
+		vt1625_cvbs_always_turnon = 0;
+
+#ifdef CONFIG_KERNEL
+    vt1625_set_tv_mode((vt1625_tv_mode == 1) ? 1 : 0);
+
+	start_vt1625_timer();
+#endif
+
+	MSG("[VT1625] DVI ext device\n");
+	return 0;
+}
+
+static int vt1625_set_mode(unsigned int *option)
+{
+#ifdef CONFIG_VT1625_INTERRUPT
+	char buf[1];
+#endif
+
+	DBG_MSG("\n");
+#ifdef CONFIG_VT1625_INTERRUPT
+	if (!g_vpp.dvi_int_disable) {
+	vout_set_int_type(1);
+	vout_set_int_enable(1);
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_INT_WSS_2, buf, 1);
+	buf[0] |= 0xA0; /* enable sense interrupt */
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_INT_WSS_2, buf, 1);
+	}
+#endif
+	return 0;
+}
+
+static void vt1625_set_power_down(int enable)
+{
+	struct vout_t *vo;
+	char buf[1];
+	char cur[1];
+
+	/*
+	bit 0-2 : DAC D/E/F - VGA
+	bit 3 : DAC C - CVBS
+	bit 3-5 : DAC A/B/C - YPbPr
+	bit 6 : PLL
+	bit 7 : IO pad
+	*/
+	vo = vout_get_entry(VPP_VOUT_NUM_DVI);
+	if (vo->status & (VPP_VOUT_STS_BLANK + VPP_VOUT_STS_POWERDN))
+		enable = 1;
+
+	/* power down for not support resolution */
+//#ifndef CONFIG_VT1625_INTERRUPT
+	if ((vt1625_tv_mode != 0) && enable && g_vpp.dvi_int_disable)
+		buf[0] = 0xFF;
+	else
+//#endif
+		buf[0] = vt1625_get_dac_val(vt1625_out_mode);
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_POWER_MANAGEMENT, cur, 1);
+
+	if (cur[0] == buf[0])
+		return;
+
+	DBG_MSG("enable %d,cur 0x%x,new 0x%x\n", enable, cur[0], buf[0]);
+#if 1
+	if (enable == 0) {
+		cur[0] &= ~0x40; /* turn on PLL */
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_POWER_MANAGEMENT, cur, 1);
+		mdelay(3);
+
+		cur[0] &= ~0x80; /* turn on IO pad */
+		vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_POWER_MANAGEMENT, cur, 1);
+		mdelay(3);
+	}
+#endif
+#ifdef CONFIG_VT1625_POWER
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+		VT1625_POWER_MANAGEMENT, buf, 1);
+#endif
+}
+
+static int vt1625_config(struct vout_info_t *info)
+{
+	int ntsc = -1;
+
+	DBG_MSG("%d,%d\n", info->resx, info->resy);
+	if (info->resx == 720) {
+		switch (info->resy) {
+		case 480:
+			ntsc = 1;
+			break;
+		case 576:
+			ntsc = 0;
+			break;
+		default:
+			break;
+		}
+	}
+
+	if (ntsc != -1)
+		vt1625_set_tv_mode(ntsc);
+	else
+		vt1625_tv_mode = 0;
+	DBG_MSG("end\n");
+	return 0;
+}
+
+static int vt1625_get_edid(char *buf)
+{
+	return 0;
+}
+
+#ifdef CONFIG_VT1625_INTERRUPT
+static int vt1625_interrupt(void)
+{
+	char buf[1];
+
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x4c0, 0x1 << VPP_VOINT_NO,
+			VPP_VOINT_NO, 0x0); /* GPIO pull-up */
+	/* interrupt */
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INT_WSS_2, buf, 1);
+	DBG_MSG("0x%x\n", buf[0]);
+	buf[0] &= ~0x40; /* clear interrupt */
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR, VT1625_INT_WSS_2, buf, 1);
+	return vt1625_check_plugin(1);
+}
+#endif
+
+static void vt1625_poll(void)
+{
+	int plugin;
+	char buf[1];
+	char cur[1];
+
+	if (govrh_get_dvo_enable(p_govrh2) == 0)
+		govrh_set_dvo_enable(p_govrh2, VPP_FLAG_ENABLE);
+
+	plugin = vt1625_check_plugin(0);
+	if (plugin != pre_plugin) {
+		struct vout_t *vo;
+
+		vo = vout_get_entry(VPP_VOUT_NUM_DVI);
+		vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin);
+#ifdef CONFIG_KERNEL
+		vpp_netlink_notify_plug(VPP_VOUT_NUM_DVI, plugin);
+#endif
+		pre_plugin = plugin;
+		DMSG("%d\n", plugin);
+	}
+
+	/*
+	* Disable VT1625 Power if CVBS Not plugin
+	*/
+	if(plugin == 0) {
+		vpp_i2c_read(VPP_DVI_I2C_ID, VT1625_ADDR,
+			VT1625_POWER_MANAGEMENT, cur, 1);
+
+		buf[0] = 0xFF;
+
+		if(cur[0] != buf[0]) {
+			vpp_i2c_write(VPP_DVI_I2C_ID, VT1625_ADDR,
+				VT1625_POWER_MANAGEMENT, buf, 1);
+		}
+	}
+}
+
+static int vt1625_suspend(void)
+{
+	DMSG("\n");
+
+#ifdef CONFIG_KERNEL
+	stop_vt1625_timer();
+#endif
+
+	return 0;
+}
+
+static int vt1625_resume(void)
+{
+	DMSG("\n");
+
+#ifdef CONFIG_KERNEL
+	start_vt1625_timer();
+#endif
+	return 0;
+}
+
+/*----------------------- vout device plugin ---------------------------------*/
+struct vout_dev_t vt1625_vout_dev_ops = {
+	.name = "VT1625",
+	.mode = VOUT_INF_DVI,
+
+	.init = vt1625_init,
+	.set_power_down = vt1625_set_power_down,
+	.set_mode = vt1625_set_mode,
+	.config = vt1625_config,
+	.check_plugin = vt1625_check_plugin,
+	.get_edid = vt1625_get_edid,
+#ifdef CONFIG_VT1625_INTERRUPT
+	.interrupt = vt1625_interrupt,
+#endif
+	.poll = vt1625_poll,
+	.suspend = vt1625_suspend,
+	.resume = vt1625_resume,
+};
+
+int vt1625_module_init(void)
+{
+	vt1625_reg_env_t *p_reg;
+	int i, ret, regnum;
+
+	p_reg = kmalloc((VT1625_REG_MAX_OFFSET + 1) * sizeof(vt1625_reg_env_t),
+		GFP_KERNEL);
+	if(p_reg) {
+		ret = vt1625_parse_reg_env(VT1625_PAL_REG_ENV, p_reg, &regnum);
+		if(ret == 0) {
+			for(i = 0; i < regnum; i++)
+				vt1625_pal_param[(p_reg + i)->offset] =
+					(p_reg + i)->value;
+		}
+
+		ret = vt1625_parse_reg_env(VT1625_NTSC_REG_ENV, p_reg, &regnum);
+		if(ret == 0) {
+			for(i = 0; i < regnum; i++)
+				vt1625_ntsc_param[(p_reg + i)->offset] =
+					(p_reg + i)->value;
+		}
+
+		kfree(p_reg);
+	} else
+		DBG_ERR("kzalloc fail\n");
+
+#ifdef CONFIG_KERNEL
+	init_vt1625_timer();
+#endif
+
+	vout_device_register(&vt1625_vout_dev_ops);
+
+	return 0;
+}
+module_init(vt1625_module_init);
+/*--------------------End of Function Body -----------------------------------*/
+#undef VT1625_C
diff --git a/drivers/video/wmt/devices/vt1632.c b/drivers/video/wmt/devices/vt1632.c
new file mode 100755
index 00000000..b3950c0f
--- /dev/null
+++ b/drivers/video/wmt/devices/vt1632.c
@@ -0,0 +1,157 @@
+/*++
+ * linux/drivers/video/wmt/vt1632.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VT1632_C
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "../vout.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  VT1632_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VT1632_XXXX    1     *//*Example*/
+#define VT1632_ADDR 0x10
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx vt1632_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vt1632.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  vt1632_xxx;        *//*Example*/
+static int vt1632_not_ready;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vt1632_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+
+/*the define and struct i2c_msg were declared int linux/i2c.h*/
+int vt1632_check_plugin(int hotplug)
+{
+	char buf[1];
+	int plugin;
+
+	if (vt1632_not_ready)
+		return 1;
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x9, buf, 1);
+	plugin = (buf[0] & 0x4) ? 1 : 0;
+	DPRINT("[VT1632] DVI plug%s\n", (plugin) ? "in" : "out");
+	vout_set_int_type(4);
+	return plugin;
+}
+
+int vt1632_init(struct vout_t *vo)
+{
+	char buf[16];
+
+	vt1632_not_ready = 1;
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x0, buf, 2);
+	if ((buf[0] != 0x06) || (buf[1] != 0x11)) /* check vender id */
+		return -1;
+	vt1632_not_ready = 0;
+
+	buf[0x0] = 0x37;
+	buf[0x1] = 0x20;
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 2);
+	DPRINT("[VT1632] DVI ext device\n");
+	return 0;
+}
+
+int vt1632_set_mode(unsigned int *option)
+{
+	char buf[1];
+	vpp_datawidht_t dwidth;
+
+	if (vt1632_not_ready)
+		return -1;
+
+	dwidth = option[1] & BIT0;
+	DBGMSG("vt1632_set_mode(%d)\n", (dwidth) ? 24 : 12);
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1);
+	if (dwidth == VPP_DATAWIDHT_12) {
+		buf[0] &= ~BIT2;
+		buf[0] |= BIT3;
+	} else {
+		buf[0] |= BIT2;
+		buf[0] &= ~BIT3;
+	}
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1);
+	return 0;
+}
+
+void vt1632_set_power_down(int enable)
+{
+	char buf[1];
+
+	if (vt1632_not_ready)
+		return;
+
+	DBGMSG("vt1632_set_power_down(%d)\n", enable);
+
+	vpp_i2c_read(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1);
+	if (enable)
+		buf[0] &= ~BIT0;
+	else
+		buf[0] |= BIT0;
+	vpp_i2c_write(VPP_DVI_I2C_ID, VT1632_ADDR, 0x8, buf, 1);
+}
+
+int vt1632_config(struct vout_info_t *info)
+{
+	return 0;
+}
+
+int vt1632_get_edid(char *buf)
+{
+	return 0;
+}
+
+int vt1632_interrupt(void)
+{
+	return vt1632_check_plugin(1);
+}
+/*----------------------- vout device plugin ---------------------------------*/
+struct vout_dev_t vt1632_vout_dev_ops = {
+	.name = "VT1632",
+	.mode = VOUT_INF_DVI,
+
+	.init = vt1632_init,
+	.set_power_down = vt1632_set_power_down,
+	.set_mode = vt1632_set_mode,
+	.config = vt1632_config,
+	.check_plugin = vt1632_check_plugin,
+	.get_edid = vt1632_get_edid,
+	.interrupt = vt1632_interrupt,
+};
+
+int vt1632_module_init(void)
+{
+	vout_device_register(&vt1632_vout_dev_ops);
+	return 0;
+} /* End of vt1632_module_init */
+module_init(vt1632_module_init);
+/*--------------------End of Function Body -----------------------------------*/
+#undef VT1632_C
diff --git a/drivers/video/wmt/edid.h b/drivers/video/wmt/edid.h
new file mode 100755
index 00000000..b476a780
--- /dev/null
+++ b/drivers/video/wmt/edid.h
@@ -0,0 +1,168 @@
+/*++
+ * linux/drivers/video/wmt/edid.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef EDID_H
+#define EDID_H
+
+#define EDID_BLOCK_MAX	4
+
+/*------------------------------------------------------------------------------
+    Following definitions, please refer spec of EDID. You may refer it on
+    http://en.wikipedia.org/wiki/EDID#EDID_1.3_data_format
+------------------------------------------------------------------------------*/
+
+#define EDID_LENGTH	0x80
+
+/*------------------------------------------------------------------------------
+  Offset 00-19: HEADER INFORMATION
+------------------------------------------------------------------------------*/
+/*  00�V07: Header information "00h FFh FFh FFh FFh FFh FFh 00h" */
+#define EDID_HEADER	0x00
+#define EDID_HEADER_END	0x07
+
+/* 08�V09: Manufacturer ID. These IDs are assigned by Microsoft.
+	"00001=A��; ��00010=B��; ... ��11010=Z��. Bit 7 (at address 08h) is 0,
+	the first character (letter) is located at bits 6 �� 2
+	(at address 08h), the second character (letter) is located at
+	bits 1 & 0 (at address 08h) and bits 7 �� 5 (at address 09h), and the
+	third character (letter) is located at bits 4 �� 0 (at address 09h).
+*/
+#define ID_MANUFACTURER_NAME		0x08
+#define ID_MANUFACTURER_NAME_END	0x09
+
+/*  10�V11: Product ID Code (stored as LSB first). Assigned by manufacturer */
+#define ID_MODEL	0x0a
+
+/*  12�V15: 32-bit Serial Number. No requirement for the format. Usually
+	stored as LSB first. In order to maintain compatibility with previous
+	requirements the field should set at least one byte of the field to be
+	non-zero if an ASCII serial number descriptor is
+	provided in the detailed timing section.
+*/
+#define ID_SERIAL_NUMBER	0x0c
+
+/* 16: Week of Manufacture. This varies by manufacturer. One way is to count
+	January 1-7 as week 1, January 8-15 as week 2 and so on. Some count
+	based on the week number (Sunday-Saturday). Valid range is 1-54.
+	17: Year of Manufacture. Add 1990 to the value for actual year. */
+#define MANUFACTURE_WEEK	0x10
+#define MANUFACTURE_YEAR	0x11
+
+/*	18: EDID Version Number. "01h"
+	19: EDID Revision Number "03h" */
+#define EDID_STRUCT_VERSION	0x12
+#define EDID_STRUCT_REVISION	0x13
+
+#define EDID_MAX_HOR_IMAGE_SIZE 0x15
+#define EDID_MAX_VER_IMAGE_SIZE 0x16
+
+/*------------------------------------------------------------------------------
+  Offset 20-24: BASIC DISPLAY PARAMETERS
+------------------------------------------------------------------------------*/
+#define DPMS_FLAGS		0x18
+#define ESTABLISHED_TIMING_I	0x23
+#define ESTABLISHED_TIMING_II	0x24
+#define MANUFACTURERS_TIMINGS	0x25
+
+#define STANDARD_TIMING_IDENTIFICATION_START	0x26
+#define STANDARD_TIMING_IDENTIFICATION_SIZE	16
+
+#define DETAILED_TIMING_DESCRIPTIONS_START	0x36
+#define DETAILED_TIMING_DESCRIPTION_SIZE	18
+#define NO_DETAILED_TIMING_DESCRIPTIONS		4
+
+#define DETAILED_TIMING_DESCRIPTION_1		0x36
+#define DETAILED_TIMING_DESCRIPTION_2		0x48
+#define DETAILED_TIMING_DESCRIPTION_3		0x5a
+#define DETAILED_TIMING_DESCRIPTION_4		0x6c
+
+#define EDID_TMR_INTERLACE	BIT(31)
+#define EDID_TMR_FREQ		0xFF
+struct edid_timing_t {
+	unsigned int resx;
+	unsigned int resy;
+	int freq;	/* EDID_TMR_XXX */
+};
+
+struct vic_3d_t {
+	char vic;
+	unsigned int mask;
+};
+
+/* EDID option flag */
+#define EDID_OPT_VALID		0x01
+#define EDID_OPT_YUV422		0x10
+#define EDID_OPT_YUV444		0x20
+#define EDID_OPT_AUDIO		0x40
+#define EDID_OPT_UNDERSCAN	0x80
+#define EDID_OPT_HDMI		0x100
+#define EDID_OPT_3D		BIT(9)
+#define EDID_OPT_16_9		BIT(10)
+
+struct edid_info_t {
+	unsigned int establish_timing;
+	struct edid_timing_t standard_timing[8];
+	struct fb_videomode detail_timing[4];
+	struct fb_videomode cea_timing[6];
+	char cea_vic[8];
+	struct vic_3d_t vic_3d[16];
+	unsigned int pixel_clock_limit;
+	unsigned int option;
+	unsigned short hdmi_phy_addr;
+	int width;
+	int height;
+};
+
+#define VENDOR_NAME_LEN              4
+#define MONITOR_NAME_LEN             20
+#define AUD_SAD_NUM                  32
+struct sad_t {
+	char flag; /* 0: sad available, 1: sad invalid */
+	char sad_byte[3];
+};
+
+struct tv_name_t{
+	char vendor_name[VENDOR_NAME_LEN];
+	char monitor_name[MONITOR_NAME_LEN];
+};
+
+struct edid_parsed_t {
+        struct tv_name_t tv_name;
+	struct sad_t sad[AUD_SAD_NUM];
+};
+
+extern struct edid_info_t edid_info;
+extern int edid_msg_enable;
+extern int edid_disable;
+extern struct edid_parsed_t edid_parsed;
+
+extern int edid_parse(char *edid, struct edid_info_t *info);
+extern int edid_find_support(struct edid_info_t *info, unsigned int resx,
+	unsigned int resy, int freq, struct fb_videomode **vmode);
+extern void edid_dump(char *edid);
+extern int edid_checksum(char *edid, int len);
+extern unsigned int edid_get_hdmi_phy_addr(void);
+extern unsigned int edid_get_hdmi_3d_mask(struct edid_info_t *info,
+	int vic);
+
+#endif
diff --git a/drivers/video/wmt/ge/Makefile b/drivers/video/wmt/ge/Makefile
new file mode 100755
index 00000000..819c710a
--- /dev/null
+++ b/drivers/video/wmt/ge/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for WonderMedia GE driver
+#
+obj-$(CONFIG_FB_WMT_GE) += ge.o
+ge-objs := ge_main.o ge_accel.o
diff --git a/drivers/video/wmt/ge/ge_accel.c b/drivers/video/wmt/ge/ge_accel.c
new file mode 100755
index 00000000..753d264c
--- /dev/null
+++ b/drivers/video/wmt/ge/ge_accel.c
@@ -0,0 +1,372 @@
+/*
+ * Copyright (c) 2008-2013 WonderMedia Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/moduleparam.h>
+#include <mach/hardware.h>
+#include "ge_accel.h"
+
+int flipcnt;
+int flipreq;
+int vbl;
+int vsync = 1;
+int debug;
+
+module_param(flipcnt, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(flipcnt, "Flip count");
+
+module_param(flipreq, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(flipreq, "Flip request count");
+
+module_param(vbl, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(vbl, "Wait vsync for each frame (0)");
+
+module_param(vsync, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(vsync, "Can use vsync (1)");
+
+module_param(debug, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(debug, "Show debug information");
+
+/**************************
+ *    Export functions    *
+ **************************/
+
+#define M(x) ((x)<<20)
+
+unsigned int phy_mem_end(void)
+{
+	unsigned int memsize = (num_physpages << PAGE_SHIFT);
+	unsigned int n = 32 << 20;
+
+	while (n <= memsize)
+		n <<= 1;
+
+	memsize = n;
+	printk(KERN_DEBUG "Detected RAM size %d MB\n", memsize>>20);
+
+	return memsize;
+}
+
+unsigned int phy_mem_end_sub(u32 size)
+{
+	return phy_mem_end() - M(size);
+}
+EXPORT_SYMBOL(phy_mem_end_sub);
+
+/* ge_vo_functions depends vpu to work */
+
+void ge_vo_get_default_var(struct fb_var_screeninfo *var)
+{
+#ifdef HAVE_VPP
+	vpp_get_info(0, var);
+#endif
+}
+
+void ge_vo_wait_vsync(void)
+{
+#ifdef HAVE_VPP
+	if (vsync)
+		vpp_wait_vsync(0, 1);
+#endif
+}
+
+static int ge_vo_pan_display(struct fb_var_screeninfo *var,
+			     struct fb_info *info)
+{
+#ifdef HAVE_VPP
+	wmtfb_set_mutex(info, 1);
+	vpp_pan_display(var, info);
+	wmtfb_set_mutex(info, 0);
+#endif
+	flipcnt++;
+
+	return 0;
+}
+
+struct ge_var {
+	struct fb_info *info;
+	struct fb_var_screeninfo var[1];
+	struct fb_var_screeninfo new_var[1];
+	struct timeval most_recent_flip_time;
+	int dirty;
+	int force_sync;
+	spinlock_t lock[1];
+	void (*start)(struct ge_var *ge_var);
+	void (*stop)(struct ge_var *ge_var);
+	void (*get)(struct ge_var *ge_var, struct fb_var_screeninfo *var);
+	void (*set)(struct ge_var *ge_var, struct fb_var_screeninfo *var);
+	void (*sync)(struct ge_var *ge_var, int wait);
+};
+
+static struct ge_var *ge_var_s;
+
+static void ge_var_start(struct ge_var *ge_var);
+static void ge_var_stop(struct ge_var *ge_var);
+static void ge_var_get(struct ge_var *ge_var, struct fb_var_screeninfo *var);
+static void ge_var_set(struct ge_var *ge_var, struct fb_var_screeninfo *var);
+static void ge_var_sync(struct ge_var *ge_var, int wait);
+
+static struct ge_var *create_ge_var(struct fb_info *info)
+{
+	struct ge_var *ge_var;
+
+	ge_var = (struct ge_var *)
+		kcalloc(1, sizeof(struct ge_var), GFP_KERNEL);
+
+	ge_var->info = info;
+	ge_var->start = &ge_var_start;
+	ge_var->stop = &ge_var_stop;
+	ge_var->get = &ge_var_get;
+	ge_var->set = &ge_var_set;
+	ge_var->sync = &ge_var_sync;
+
+	do_gettimeofday(&ge_var->most_recent_flip_time);
+
+	ge_var->start(ge_var);
+
+	return ge_var;
+}
+
+static void release_ge_var(struct ge_var *ge_var)
+{
+	if (ge_var) {
+		ge_var->stop(ge_var);
+		kfree(ge_var);
+	}
+}
+
+static void ge_var_start(struct ge_var *ge_var)
+{
+	spin_lock_init(ge_var->lock);
+}
+
+static void ge_var_stop(struct ge_var *ge_var)
+{
+}
+
+static void ge_var_get(struct ge_var *ge_var, struct fb_var_screeninfo *var)
+{
+	spin_lock(ge_var->lock);
+	memcpy(var, ge_var->var, sizeof(struct fb_var_screeninfo));
+	spin_unlock(ge_var->lock);
+}
+
+static void ge_var_set(struct ge_var *ge_var, struct fb_var_screeninfo *var)
+{
+	int wait;
+
+	spin_lock(ge_var->lock);
+	if (memcmp(ge_var->new_var, var, sizeof(struct fb_var_screeninfo))) {
+		memcpy(ge_var->new_var, var, sizeof(struct fb_var_screeninfo));
+		ge_var->dirty++;
+	}
+	spin_unlock(ge_var->lock);
+
+	wait = vbl || (var->activate & FB_ACTIVATE_VBL);
+	ge_var->sync(ge_var, wait);
+}
+
+static void ge_var_sync(struct ge_var *ge_var, int wait)
+{
+	struct timeval t;
+	struct timeval *mrft;
+	unsigned long us;
+
+	spin_lock(ge_var->lock);
+
+	if (ge_var->dirty == 0) {
+		spin_unlock(ge_var->lock);
+		return;
+	}
+
+	memcpy(ge_var->var, ge_var->new_var, sizeof(struct fb_var_screeninfo));
+
+	mrft = &ge_var->most_recent_flip_time;
+	do_gettimeofday(&t);
+
+	us = (t.tv_sec - mrft->tv_sec) * 1000000 +
+		(t.tv_usec - mrft->tv_usec);
+
+	spin_unlock(ge_var->lock);
+
+	ge_vo_pan_display(ge_var->var, ge_var->info);
+	ge_var->dirty = 0;
+
+	/* 60 fps */
+	if (wait && us < 16667) {
+		if (debug) {
+			struct timeval t1;
+			struct timeval t2;
+			int ms;
+			do_gettimeofday(&t1);
+			ge_vo_wait_vsync();
+			do_gettimeofday(&t2);
+			ms = (t2.tv_sec - t1.tv_sec) * 1000 +
+			     (t2.tv_usec - t1.tv_usec) / 1000;
+			printk(KERN_DEBUG "ge: wait vsync for %d ms\n", ms);
+		} else
+			ge_vo_wait_vsync();
+	}
+
+	do_gettimeofday(&ge_var->most_recent_flip_time);
+}
+
+static int fb_var_cmp(struct fb_var_screeninfo *var1,
+		      struct fb_var_screeninfo *var2)
+{
+	/* Compare from xres to bits_per_pixel should be enough */
+	return memcmp(var1, var2, 28);
+}
+
+/**
+ * ge_init - Initial and display framebuffer.
+ *
+ * Fill the framebuffer with a default color, back.
+ * Display the framebuffer using GE AMX.
+ *
+ * Although VQ is supported in design, I just can't find any benefit
+ * from VQ. It wastes extra continuous physical memory, and runs much
+ * slower than direct register access. Moreover, the source code
+ * becomes more complex and is hard to maintain. Accessing VQ from
+ * the user space is also a nightmare. In brief, the overhead of VQ makes
+ * it useless. In order to gain the maximum performance
+ * from GE and to keep the driver simple, I'm going to stop using VQ.
+ * I will use VQ only when it is necessary.
+ *
+ * @info is the fb_info provided by framebuffer driver.
+ * @return zero on success.
+ */
+int ge_init(struct fb_info *info)
+{
+	static int boot_init; /* boot_init = 0 */
+	/*
+	 * Booting time initialization
+	 */
+	if (!boot_init) {
+		ge_var_s = create_ge_var(info);
+		boot_init = 1;
+	}
+
+	return 0;
+}
+
+/**
+ * ge_exit - Disable GE.
+ *
+ * No memory needs to be released here.
+ * Turn off the AMX to stop displaying framebuffer.
+ * Update the index of MMU.
+ *
+ * @info is fb_info from fbdev.
+ * @return zero on success.
+ */
+int ge_exit(struct fb_info *info)
+{
+	release_ge_var(ge_var_s);
+	release_mem_region(info->fix.mmio_start, info->fix.mmio_len);
+
+	return 0;
+}
+
+int ge_release(struct fb_info *info)
+{
+	struct ge_var *ge_var = ge_var_s;
+
+	ge_var->sync(ge_var, 0); /* apply pending changes */
+
+	return 0;
+}
+
+/**
+ * ge_pan_display - Pans the display.
+ *
+ * Pan (or wrap, depending on the `vmode' field) the display using the
+ * `xoffset' and `yoffset' fields of the `var' structure.
+ * If the values don't fit, return -EINVAL.
+ *
+ * @var: frame buffer variable screen structure
+ * @info: frame buffer structure that represents a single frame buffer
+ *
+ * Returns negative errno on error, or zero on success.
+ */
+int ge_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct ge_var *ge_var;
+
+	ge_var = ge_var_s;
+
+	if (debug)
+		printk(KERN_DEBUG "pan_display\n");
+	/*
+	printk(KERN_DEBUG "%s: xoff = %d, yoff = %d, xres = %d, yres = %d\n",
+	       __func__, var->xoffset, var->yoffset,
+	       info->var.xres, info->var.yres);
+	*/
+	flipreq++;
+
+	if ((var->xoffset + info->var.xres > info->var.xres_virtual) ||
+	    (var->yoffset + info->var.yres > info->var.yres_virtual)) {
+		/* Y-pan is used in most case.
+		 * So please make sure that yres_virtual is
+		 * greater than (yres + yoffset).
+		 */
+		printk(KERN_ERR "%s: out of range\n", __func__);
+		return -EINVAL;
+	}
+
+	if ((var->activate & FB_ACTIVATE_MASK) == FB_ACTIVATE_NOW &&
+	    fb_var_cmp(ge_var->new_var, var))
+		ge_var->set(ge_var, var);
+
+	return 0;
+}
+
+int ge_sync(struct fb_info *info)
+{
+	return 0;
+}
+
+int ge_blank(int mode, struct fb_info *info)
+{
+#ifdef HAVE_VPP
+	return vpp_set_blank(info, mode);
+#else
+	return 0;
+#endif
+}
+
+int ge_suspend(struct fb_info *info)
+{
+	return 0;
+}
+
+int ge_resume(struct fb_info *info)
+{
+	return 0;
+}
diff --git a/drivers/video/wmt/ge/ge_accel.h b/drivers/video/wmt/ge/ge_accel.h
new file mode 100755
index 00000000..c6934daa
--- /dev/null
+++ b/drivers/video/wmt/ge/ge_accel.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2008-2013 WonderMedia Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+ */
+
+#ifndef GE_ACCEL_H
+#define GE_ACCEL_H
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fb.h>
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#define GE_DEBUG 0
+#define FB_ACCEL_WMT 0x8910
+#define MAX_XRES 1920
+#define MAX_YRES 1080
+#define GE_FB_NUM 3
+
+#define HAVE_MALI
+#define HAVE_VPP
+
+extern int vbl;
+extern int vsync;
+
+unsigned int phy_mem_end(void);
+unsigned int phy_mem_end_sub(unsigned int size);
+int ge_init(struct fb_info *info);
+int ge_exit(struct fb_info *info);
+int ge_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg);
+int ge_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+int ge_sync(struct fb_info *info);
+int ge_release(struct fb_info *info);
+int ge_blank(int mode, struct fb_info *info);
+int ge_suspend(struct fb_info *info);
+int ge_resume(struct fb_info *info);
+
+void ge_vo_get_default_var(struct fb_var_screeninfo *var);
+void ge_vo_wait_vsync(void);
+
+#ifdef HAVE_VPP
+#include "../vpp.h"
+extern void vpp_wait_vsync(int idx, int cnt);
+extern void wmtfb_set_mutex(struct fb_info *info, int lock);
+extern int vpp_get_info(int fbn, struct fb_var_screeninfo *var);
+extern int vpp_pan_display(struct fb_var_screeninfo *var, struct fb_info *info);
+extern int vpp_set_blank(struct fb_info *info, int blank);
+extern int vpp_set_par(struct fb_info *info);
+extern int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info);
+#endif /* HAVE_VPP */
+
+#ifdef HAVE_MALI
+extern unsigned int mali_ump_secure_id;
+extern unsigned int (*mali_get_ump_secure_id)(unsigned int addr,
+					      unsigned int size);
+extern void         (*mali_put_ump_secure_id)(unsigned int ump_id);
+#endif /* HAVE_MALI */
+
+#endif
diff --git a/drivers/video/wmt/ge/ge_main.c b/drivers/video/wmt/ge/ge_main.c
new file mode 100755
index 00000000..4b362fe3
--- /dev/null
+++ b/drivers/video/wmt/ge/ge_main.c
@@ -0,0 +1,795 @@
+/*
+ * Copyright (c) 2008-2013 WonderMedia Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/uaccess.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+
+#include "ge_accel.h"
+
+#define HAVE_MALI
+#define WMT_MB
+
+#ifdef HAVE_MALI
+#include "../mali.h"
+static struct mali_device *malidev;
+#define UMP_INVALID_SECURE_ID    ((unsigned int)-1)
+#define GET_UMP_SECURE_ID        _IOWR('m', 310, unsigned int)
+#define GET_UMP_SECURE_ID_BUF1   _IOWR('m', 311, unsigned int)
+#define GET_UMP_SECURE_ID_BUF2   _IOWR('m', 312, unsigned int)
+#define MALI_GET_UMP_SECURE_ID   _IOWR('m', 320, unsigned int)
+#define MALI_PUT_UMP_SECURE_ID   _IOWR('m', 321, unsigned int)
+#endif /* HAVE_MALI */
+
+#ifndef FBIO_WAITFORVSYNC
+#define FBIO_WAITFORVSYNC _IOW('F', 0x20, u_int32_t)
+#endif
+
+#define GEIO_MAGIC		0x69
+
+#ifdef GEIO_MAGIC
+#define GEIOGET_CHIP_ID		_IOR(GEIO_MAGIC, 5, unsigned int)
+#endif
+
+static int vtotal = 32;
+static int mbsize;
+
+module_param(vtotal, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(vtotal, "Maximum GE memory size in MiB");
+
+module_param(mbsize, int, S_IRUSR | S_IWUSR | S_IWGRP | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(mbsize, "WMT-MB size in MiB");
+
+static struct fb_fix_screeninfo gefb_fix = {
+	.id             = "gefb",
+	.smem_start     = 0,
+	.smem_len       = 0,
+	.type           = FB_TYPE_PACKED_PIXELS,
+	.type_aux       = 0,
+	.visual         = FB_VISUAL_TRUECOLOR,
+	.xpanstep       = 1,
+	.ypanstep       = 1,
+	.ywrapstep      = 1,
+	.line_length    = 0,
+#ifdef HAVE_MALI
+	.mmio_start     = 0xd8080000,
+	.mmio_len       = 0x10000,
+#else
+	.mmio_start     = 0,
+	.mmio_len       = 0,
+#endif
+	.accel          = FB_ACCEL_WMT
+};
+
+static struct fb_var_screeninfo gefb_var = {
+	.xres           = CONFIG_DEFAULT_RESX,
+	.yres           = CONFIG_DEFAULT_RESY,
+	.xres_virtual   = CONFIG_DEFAULT_RESX,
+	.yres_virtual   = CONFIG_DEFAULT_RESY,
+	/*
+	.bits_per_pixel = 32,
+	.red            = {16, 8, 0},
+	.green          = {8, 8, 0},
+	.blue           = {0, 8, 0},
+	.transp         = {0, 0, 0},
+	*/
+	.bits_per_pixel = 16,
+	.red            = {11, 5, 0},
+	.green          = {5, 6, 0},
+	.blue           = {0, 5, 0},
+	.transp         = {0, 0, 0},
+	.activate       = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE,
+	.height         = -1,
+	.width          = -1,
+	.pixclock       = 39721,
+	.left_margin    = 40,
+	.right_margin   = 24,
+	.upper_margin   = 32,
+	.lower_margin   = 11,
+	.hsync_len      = 96,
+	.vsync_len      = 2,
+	.vmode          = FB_VMODE_NONINTERLACED
+};
+
+static int gefb_open(struct fb_info *info, int user)
+{
+	return 0;
+}
+
+static int gefb_release(struct fb_info *info, int user)
+{
+	return ge_release(info);
+}
+
+static int gefb_check_var(struct fb_var_screeninfo *var,
+			      struct fb_info *info)
+{
+#ifdef HAVE_VPP
+	return wmtfb_check_var(var, info);
+#else
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		if (var->red.offset > 8) {
+			/* LUT8 */
+			var->red.offset = 0;
+			var->red.length = 8;
+			var->green.offset = 0;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 16:
+		if (var->transp.length) {
+			/* ARGB 1555 */
+			var->red.offset = 10;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else {
+			/* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24:
+		/* RGB 888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	case 32:
+		/* ARGB 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	}
+	return 0;
+#endif
+}
+
+static int gefb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	/* init your hardware here */
+	if (var->bits_per_pixel == 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+
+	if (ge_init(info))
+		return -ENOMEM;
+
+#ifdef HAVE_VPP
+	vpp_set_par(info);
+#endif
+
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+
+	return 0;
+}
+
+static int gefb_setcolreg(unsigned regno, unsigned red,
+			      unsigned green, unsigned blue,
+			      unsigned transp, struct fb_info *info)
+{
+	if (regno >= 256)  /* no. of hw registers */
+		return -EINVAL;
+
+	/* grayscale */
+
+	if (info->var.grayscale) {
+		/* grayscale = 0.30*R + 0.59*G + 0.11*B */
+		red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8;
+	}
+
+	/*  The following is for fbcon. */
+
+	if (info->fix.visual == FB_VISUAL_TRUECOLOR ||
+		info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
+
+		if (regno >= 16)
+			return -EINVAL;
+
+		switch (info->var.bits_per_pixel) {
+		case 16:
+			((unsigned int *)(info->pseudo_palette))[regno] =
+				(red & 0xf800) |
+				((green & 0xfc00) >> 5) |
+				((blue & 0xf800) >> 11);
+				break;
+		case 24:
+		case 32:
+			red   >>= 8;
+			green >>= 8;
+			blue  >>= 8;
+			((unsigned int *)(info->pseudo_palette))[regno] =
+				(red << info->var.red.offset) |
+				(green << info->var.green.offset) |
+				(blue  << info->var.blue.offset);
+			break;
+		}
+	}
+	return 0;
+}
+
+static int gefb_ioctl(struct fb_info *info, unsigned int cmd,
+			  unsigned long arg)
+{
+	int retval = 0;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		ge_vo_wait_vsync();
+		break;
+#ifdef HAVE_MALI
+	case GET_UMP_SECURE_ID:
+	case GET_UMP_SECURE_ID_BUF1:
+	case GET_UMP_SECURE_ID_BUF2: {
+		unsigned int ump_id;
+		if (mali_get_ump_secure_id)
+			ump_id = (*mali_get_ump_secure_id)(info->fix.smem_start,
+							   info->fix.smem_len);
+		else
+			ump_id = UMP_INVALID_SECURE_ID;
+		return put_user((unsigned int) ump_id,
+				(unsigned int __user *) arg);
+	}
+	case MALI_GET_UMP_SECURE_ID: {
+		unsigned int args[3];
+		unsigned int ump_id;
+		copy_from_user(args, (void *)arg, sizeof(unsigned int) * 3);
+
+		if (mali_get_ump_secure_id)
+			ump_id = (*mali_get_ump_secure_id)(args[0], args[1]);
+		else
+			ump_id = UMP_INVALID_SECURE_ID;
+
+		return put_user((unsigned int) ump_id,
+				(unsigned int __user *) args[2]);
+	}
+	case MALI_PUT_UMP_SECURE_ID: {
+		unsigned int ump_id = (unsigned int)arg;
+		if (mali_put_ump_secure_id)
+			(*mali_put_ump_secure_id)(ump_id);
+		break;
+	}
+#endif /* HAVE_MALI */
+#ifdef GEIO_MAGIC
+	case GEIOGET_CHIP_ID: {
+		unsigned int chip_id =
+			(*(unsigned int *)SYSTEM_CFG_CTRL_BASE_ADDR);
+		copy_to_user((void *)arg, (void *)&chip_id,
+			sizeof(unsigned int));
+		break;
+	}
+#endif /* GEIO_MAGIC */
+	default:
+		break;
+	}
+
+	return retval;
+}
+
+int gefb_hw_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	return 0;
+}
+
+static int gefb_mmap(struct fb_info *info, struct vm_area_struct *vma)
+{
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+	int ismmio = 0;
+
+	if (!info)
+		return -ENODEV;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	/* frame buffer memory */
+	start = info->fix.smem_start;
+	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+	if (off >= len) {
+		/* memory mapped io */
+		off -= len;
+		/*
+		if (info->var.accel_flags) {
+			return -EINVAL;
+		}
+		*/
+		start = info->fix.mmio_start;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+		ismmio = 1;
+	}
+	start &= PAGE_MASK;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	/* This is an IO map - tell maydump to skip this VMA */
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
+
+	if (ismmio)
+		vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	else
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			     vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	return 0;
+}
+
+static struct fb_ops gefb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = gefb_open,
+	.fb_release     = gefb_release,
+	.fb_check_var   = gefb_check_var,
+	.fb_set_par     = gefb_set_par,
+	.fb_setcolreg   = gefb_setcolreg,
+	.fb_pan_display = ge_pan_display,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_blank       = ge_blank,
+	.fb_cursor      = gefb_hw_cursor,
+	.fb_ioctl       = gefb_ioctl,
+	.fb_sync	= ge_sync,
+	.fb_mmap	= gefb_mmap,
+};
+
+#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
+#define OPT_INTVAL(opt, name) kstrtoul(opt + strlen(name) + 1, 0, NULL)
+#define OPT_STRVAL(opt, name) (opt + strlen(name))
+
+static inline char *get_opt_string(const char *this_opt, const char *name)
+{
+	const char *p;
+	int i;
+	char *ret;
+
+	p = OPT_STRVAL(this_opt, name);
+	i = 0;
+	while (p[i] && p[i] != ' ' && p[i] != ',')
+		i++;
+	ret = kmalloc(i + 1, GFP_KERNEL);
+	if (ret) {
+		strncpy(ret, p, i);
+		ret[i] = '\0';
+	}
+	return ret;
+}
+
+static inline int get_opt_int(const char *this_opt, const char *name,
+				  int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (!OPT_EQUAL(this_opt, name))
+		return 0;
+
+	*ret = OPT_INTVAL(this_opt, name);
+
+	return 1;
+}
+
+static inline int get_opt_bool(const char *this_opt, const char *name,
+				   int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (OPT_EQUAL(this_opt, name)) {
+		if (this_opt[strlen(name)] == '=')
+			*ret = kstrtoul(this_opt + strlen(name) + 1, 0, NULL);
+		else
+			*ret = 1;
+	} else {
+		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
+			*ret = 0;
+		else
+			return 0;
+	}
+	return 1;
+}
+
+static int __init gefb_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	/* The syntax is:
+	 *     video=gefb:[<param>][,<param>=<val>] ...
+	 * e.g.,
+	 *     video=gefb:vtotal=12,
+	 */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (get_opt_int(this_opt, "vtotal", &vtotal))
+			;
+		else if (get_opt_int(this_opt, "mbsize", &mbsize))
+			;
+		else if (get_opt_bool(this_opt, "vbl", &vbl))
+			;
+		else if (get_opt_bool(this_opt, "vsync", &vsync))
+			;
+	}
+
+	return 0;
+}
+
+#ifdef HAVE_MALI
+static struct mali_device *add_mali_device(unsigned int *smem_start_ptr,
+					   unsigned int *smem_len_ptr)
+{
+	unsigned int len;
+	struct mali_device *dev = create_mali_device();
+	if (dev) {
+		dev->set_memory_base(*smem_start_ptr);
+		dev->get_memory_size(&len);
+		*smem_start_ptr += len;
+		*smem_len_ptr -= len;
+		dev->set_mem_validation_base(*smem_start_ptr);
+		dev->set_mem_validation_size(*smem_len_ptr);
+	}
+	return dev;
+}
+#endif /* HAVE_MALI */
+
+#ifdef WMT_MB
+static int get_mbsize(void)
+{
+	/* It is bad to read U-Boot partition directly.
+	 * I will remove this code soon.
+	 * -- Vincent
+	 */
+	unsigned char buf[32];
+	int varlen = 32;
+	int val;
+
+	if (wmt_getsyspara("mbsize", buf, &varlen) == 0)
+		sscanf(buf, "%dM", &val);
+	else
+		val = 0;
+
+	return val;
+}
+
+static void add_mb_device(unsigned int *smem_start_ptr,
+			  unsigned int *smem_len_ptr)
+{
+	unsigned int len = mbsize << 20;
+
+	if (*smem_len_ptr > len)
+		*smem_len_ptr -= len;
+}
+#endif /* WMT_MB */
+
+static int __devinit gefb_probe(struct platform_device *dev)
+{
+	struct fb_info *info;
+	int cmap_len, retval;
+/*	char mode_option[] = "1024x768@60"; */
+	unsigned int smem_start;
+	unsigned int smem_len;
+	unsigned int len;
+	unsigned int min_smem_len;
+	unsigned int id;
+
+	/* Allocate fb_info and par.*/
+	info = framebuffer_alloc(sizeof(unsigned int) * 16, &dev->dev);
+	if (!info)
+		return -ENOMEM;
+
+	/* Set default fb_info */
+	info->fbops = &gefb_ops;
+	info->fix = gefb_fix;
+
+	info->var = gefb_var;
+	ge_vo_get_default_var(&info->var);
+
+	smem_start = (num_physpages << PAGE_SHIFT);
+	smem_len = phy_mem_end() - smem_start;
+
+	/* If newer than WM3498, reserve 1MiB for U-Boot env */
+	id = (*(unsigned int *)SYSTEM_CFG_CTRL_BASE_ADDR) >> 16;
+	if (id > 0x3498) {
+		smem_start += 0x100000;
+		smem_len   -= 0x100000;
+	}
+
+#ifdef HAVE_MALI
+	malidev = add_mali_device(&smem_start, &smem_len);
+#endif /* HAVE_MALI */
+
+#ifdef WMT_MB
+	add_mb_device(&smem_start, &smem_len);
+#endif /* WMT_MB */
+
+	/* Set frame buffer region */
+
+	len = info->var.xres * info->var.yres *
+		(info->var.bits_per_pixel >> 3);
+	len *= GE_FB_NUM;
+	min_smem_len = (len + PAGE_MASK) & ~PAGE_MASK;
+
+	if (smem_len < min_smem_len) {
+		printk(KERN_ERR "%s: claim region of 0x%08x-0x%08x failed!\n",
+			__func__, smem_start, smem_start + min_smem_len);
+		return -EIO;
+	}
+
+	info->fix.smem_start = smem_start;
+
+	if (smem_len > (vtotal << 20))
+		smem_len = (vtotal << 20);
+
+	info->fix.smem_len = smem_len;
+
+	if (!request_mem_region(info->fix.smem_start,
+		info->fix.smem_len, "gefb")) {
+		printk(KERN_WARNING
+			"%s: request memory region failed at 0x%08lx\n",
+			__func__, info->fix.smem_start);
+	}
+
+	info->screen_base = ioremap(info->fix.smem_start,
+		info->fix.smem_len);
+	if (!info->screen_base) {
+		printk(KERN_ERR "%s: ioremap fail %d bytes at %p\n",
+			__func__, info->fix.smem_len,
+			(void *)info->fix.smem_start);
+		return -EIO;
+	}
+
+	printk(KERN_INFO
+		"gefb: phys 0x%08lx, virt 0x%08lx, total %d KB\n",
+		info->fix.smem_start, (unsigned long)info->screen_base,
+		info->fix.smem_len >> 10);
+
+	/*
+	 * The pseudopalette is an 16-member array for fbcon.
+	 */
+	info->pseudo_palette = info->par;
+	info->par = NULL;
+	info->flags = FBINFO_DEFAULT;	/* flag for fbcon */
+
+#if 0
+	/*
+	 * This should give a reasonable default video mode.
+	 */
+	retval = fb_find_mode(&info->var, info, mode_option,
+			      NULL, 0, NULL, 8);
+
+	if (!retval || retval == 4)
+		return -EINVAL;
+#endif
+	/*
+	 *  This has to been done !!!
+	 */
+	cmap_len = 256;	/* Be the same as VESA */
+	retval = fb_alloc_cmap(&info->cmap, cmap_len, 0);
+	if (retval < 0)
+		printk(KERN_ERR "%s: fb_alloc_cmap fail.\n", __func__);
+
+	/*
+	 *  The following is done in the case of
+	 *  having hardware with a static mode.
+	 */
+	info->var = gefb_var;
+
+	/*
+	 *  Get setting from video output device.
+	 */
+	ge_vo_get_default_var(&info->var);
+
+	/*
+	 *  For drivers that can...
+	 */
+	gefb_check_var(&info->var, info);
+
+	/*
+	 *  Apply setting
+	 */
+	gefb_set_par(info);
+	ge_pan_display(&info->var, info);
+
+	if (register_framebuffer(info) < 0) {
+		ge_exit(info);
+		return -EINVAL;
+	}
+	info->dev->power.async_suspend = 1; /* Add by Charles */
+	dev_set_drvdata(&dev->dev, info);
+
+	return 0;
+}
+
+static int gefb_remove(struct platform_device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(&dev->dev);
+
+	if (info) {
+		ge_exit(info);
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+static int gefb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	struct fb_info *info = dev_get_drvdata(&dev->dev);
+
+	if (info)
+		ge_suspend(info);
+
+#ifdef HAVE_MALI
+	if (malidev)
+		malidev->suspend(1);
+#endif
+
+	return 0;
+}
+
+static int gefb_resume(struct platform_device *dev)
+{
+	struct fb_info *info = dev_get_drvdata(&dev->dev);
+
+	if (info)
+		ge_resume(info);
+
+#ifdef HAVE_MALI
+	if (malidev)
+		malidev->resume(1);
+#endif
+
+	return 0;
+}
+
+static struct platform_driver gefb_driver = {
+	.driver.name    = "gefb",
+	.probe          = gefb_probe,
+	.remove         = gefb_remove,
+	.suspend        = gefb_suspend,
+	.resume         = gefb_resume,
+};
+
+static u64 gefb_dma_mask = 0xffffffffUL;
+static struct platform_device gefb_device = {
+	.name   = "gefb",
+	.dev    = {
+		.dma_mask = &gefb_dma_mask,
+		.coherent_dma_mask = ~0,
+	},
+};
+
+#ifdef WMT_MB
+static int __init mbsize_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		sscanf(this_opt, "%dM", &mbsize);
+		printk(KERN_DEBUG "gefb: detected mbsize = %d MiB\n", mbsize);
+	}
+
+	return 0;
+}
+__setup("mbsize=", mbsize_setup);
+#endif /* WMT_MB */
+
+static int __init gefb_init(void)
+{
+	int ret;
+	char *option = NULL;
+
+	fb_get_options("gefb", &option);
+	gefb_setup(option);
+
+#ifdef WMT_MB
+	/* It is bad to read U-Boot partition directly.
+	 * I will remove this code soon.
+	 * -- Vincent
+	 */
+	if (!mbsize) {
+		mbsize = get_mbsize();
+		printk(KERN_ERR "Please add \'mbsize=%dM\' in bootargs!",
+			mbsize);
+	}
+#endif /* WMT_MB */
+
+	ret = platform_driver_register(&gefb_driver);
+	if (!ret) {
+		ret = platform_device_register(&gefb_device);
+		if (ret)
+			platform_driver_unregister(&gefb_driver);
+	}
+
+	return ret;
+}
+module_init(gefb_init);
+
+static void __exit gefb_exit(void)
+{
+	release_mali_device(malidev);
+
+	platform_driver_unregister(&gefb_driver);
+	platform_device_unregister(&gefb_device);
+	return;
+}
+
+module_exit(gefb_exit);
+
+MODULE_AUTHOR("WonderMedia Technologies, Inc.");
+MODULE_DESCRIPTION("WMT GE driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/wmt/govrh.c b/drivers/video/wmt/govrh.c
new file mode 100755
index 00000000..42635abf
--- /dev/null
+++ b/drivers/video/wmt/govrh.c
@@ -0,0 +1,1932 @@
+/*++
+ * linux/drivers/video/wmt/govrh.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define GOVRH_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "govrh.h"
+
+#ifdef WMT_FTBLK_GOVRH
+void govrh_reg_dump(struct vpp_mod_base_t *base)
+{
+	struct govrh_mod_t *p_govr = (struct govrh_mod_t *) base;
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	int igs_mode[4] = {888, 555, 666, 565};
+
+	DPRINT("========== GOVRH register dump ==========\n");
+	vpp_reg_dump((unsigned int)base->mmio, 512);
+	DPRINT("=========================================\n");
+	DPRINT("MIF enable %d\n", regs->mif.b.enable);
+	DPRINT("color bar enable %d,mode %d,inv %d\n",
+		regs->cb_enable.b.enable, regs->cb_enable.b.mode,
+		regs->cb_enable.b.inversion);
+	DPRINT("---------- frame buffer ----------\n");
+	DPRINT("colr format %s\n",
+		vpp_colfmt_str[govrh_get_color_format(p_govr)]);
+	DPRINT("width active %d,fb %d\n", regs->pixwid, regs->bufwid);
+	DPRINT("Y addr 0x%x, C addr 0x%x\n", regs->ysa, regs->csa);
+	DPRINT("Y addr2 0x%x, C addr2 0x%x\n", regs->ysa2, regs->csa2);
+	DPRINT("H crop %d, V crop %d\n", regs->hcrop, regs->vcrop);
+	DPRINT("source format %s,H264 %d\n",
+		(regs->srcfmt) ? "field" : "frame", regs->h264_input_en);
+	DPRINT("H scaleup %d,dirpath %d\n", regs->hscale_up, regs->dirpath);
+	DPRINT("---------- GOVRH TG1 ----------\n");
+	DPRINT("TG enable %d, Twin mode %d\n",
+		regs->tg_enable.b.enable, regs->tg_enable.b.mode);
+	DPRINT("DVO clk %d,%d,Read cyc %d\n",
+		vpp_get_base_clock(p_govr->mod),
+		auto_pll_divisor((p_govr->mod == VPP_MOD_GOVRH) ?
+			DEV_HDMILVDS : DEV_DVO, GET_FREQ, 0, 0),
+		regs->read_cyc);
+	DPRINT("H total %d, Sync %d, beg %d, end %d\n",
+		regs->h_allpxl, regs->hdmi_hsynw,
+		regs->actpx_bg, regs->actpx_end);
+	DPRINT("V total %d, Sync %d, beg %d, end %d\n",
+		regs->v_allln, regs->hdmi_vbisw,
+		regs->actln_bg, regs->actln_end);
+	DPRINT("VBIE %d,PVBI %d\n", regs->vbie_line, regs->pvbi_line);
+	DPRINT("---------- GOVRH TG2 ----------\n");
+	DPRINT("H total %d, Sync %d, beg %d, end %d\n",
+		regs->h_allpxl2, regs->hdmi_hsynw2,
+		regs->actpx_bg2, regs->actpx_end2);
+	DPRINT("V total %d, Sync %d, beg %d, end %d\n",
+		regs->v_allln2, regs->hdmi_vbisw2,
+		regs->actln_bg2, regs->actln_end2);
+	DPRINT("VBIE %d,PVBI %d\n", regs->vbie_line2, regs->pvbi_line2);
+	DPRINT("---------- DVO ----------------\n");
+	DPRINT("DVO enable %d,data width %d bits\n",
+		regs->dvo_set.b.enable, (regs->dvo_set.b.outwidth) ? 12 : 24);
+	DPRINT("DVO color format %s\n",
+		vpp_colfmt_str[govrh_get_dvo_color_format(p_govr)]);
+	DPRINT("Polar H %s,V %s\n",
+		(regs->dvo_set.b.hsync_polar) ? "Low" : "High",
+		(regs->dvo_set.b.vsync_polar) ? "Low" : "High");
+	DPRINT("DVO RGB mode %d,%s\n", igs_mode[regs->igs_mode.b.mode],
+		(regs->igs_mode.b.ldi) ? "msb" : "lsb");
+	DPRINT("RGB swap %d\n", regs->dvo_set.b.rgb_swap);
+	DPRINT("---------- CSC ----------------\n");
+	DPRINT("CSC mode %s\n",
+		(regs->csc_mode.b.mode) ? "YUV2RGB" : "RGB2YUV");
+	DPRINT("CSC enable DVO %d,DISP %d,LVDS %d,HDMI %d\n",
+		regs->yuv2rgb.b.dvo, regs->yuv2rgb.b.disp,
+		regs->yuv2rgb.b.lvds, regs->yuv2rgb.b.hdmi);
+	DPRINT("---------- Misc ----------------\n");
+	DPRINT("Contrast 0x%x,Brightness 0x%x\n",
+		regs->contrast.val, regs->brightness);
+	DPRINT("LVDS RGB mode %d,%s\n", igs_mode[regs->igs_mode2.b.mode],
+		(regs->igs_mode2.b.ldi) ? "msb" : "lsb");
+	DPRINT("HDMI 3D mode %d,blank 0x%x\n",
+		regs->hdmi_3d.b.mode, regs->hdmi_3d.b.blank_value);
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+	DPRINT("---------- CURSOR -------------\n");
+	DPRINT("enable %d,field %d\n",
+		regs->cur_status.b.enable, regs->cur_status.b.out_field);
+	DPRINT("width %d,fb width %d\n", regs->cur_width, regs->cur_fb_width);
+	DPRINT("crop(%d,%d)\n", regs->cur_hcrop, regs->cur_vcrop);
+	DPRINT("coord H(%d,%d),V(%d,%d)\n",
+		regs->cur_hcoord.b.start, regs->cur_hcoord.b.end,
+		regs->cur_vcoord.b.start, regs->cur_vcoord.b.end);
+	DPRINT("color key enable 0x%x,color key 0x%x,alpha enable %d\n",
+		regs->cur_color_key.b.enable, regs->cur_color_key.b.colkey,
+		regs->cur_color_key.b.alpha);
+#endif
+}
+
+
+void govrh_set_tg_enable(struct govrh_mod_t *base, vpp_flag_t enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+				1 : 2, enable);
+
+	regs->tg_enable.b.enable = enable;
+}
+
+unsigned int govrh_set_clock(struct govrh_mod_t *base,
+	unsigned int pixel_clock)
+{
+	int pmc_clk = 0;
+
+	DBG_MSG("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+		1 : 2, pixel_clock);
+
+	base->vo_clock = pixel_clock;
+	if (base->mod == VPP_MOD_GOVRH) {
+		pmc_clk = auto_pll_divisor(DEV_HDMILVDS, SET_PLLDIV,
+			0, pixel_clock);
+		DBG_MSG("set %d,get %d\n", pixel_clock,
+			auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0));
+		g_vpp.hdmi_pixel_clock = pmc_clk;
+	} else
+		pmc_clk = auto_pll_divisor(DEV_DVO, SET_PLLDIV, 0, pixel_clock);
+	return 0;
+}
+
+void govrh_set_tg1(struct govrh_mod_t *base, vpp_clock_t *timing)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	regs->tg_enable.b.mode = 0;
+	regs->dstfmt = 0;
+	regs->read_cyc = timing->read_cycle;
+
+	regs->actpx_bg = timing->begin_pixel_of_active;
+	regs->actpx_end = timing->end_pixel_of_active;
+	regs->h_allpxl = timing->total_pixel_of_line;
+
+	regs->actln_bg = timing->begin_line_of_active + 1;
+	regs->actln_end = timing->end_line_of_active + 1;
+	regs->v_allln = timing->total_line_of_frame;
+
+	regs->vbie_line = timing->line_number_between_VBIS_VBIE;
+	/* pre vbi should more 6 to avoid garbage line */
+	regs->pvbi_line = (timing->line_number_between_PVBI_VBIS < 6) ?
+				6 : timing->line_number_between_PVBI_VBIS;
+
+	regs->hdmi_hsynw = timing->hsync;
+	regs->hdmi_vbisw = timing->vsync;
+
+#ifdef DEBUG_DETAIL
+	vpp_show_timing("govrh tg1", 0, timing);
+#endif
+}
+
+int govrh_get_tg_mode(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return regs->tg_enable.b.mode;
+}
+
+void govrh_set_tg2(struct govrh_mod_t *base, vpp_clock_t *timing)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	regs->tg_enable.b.mode = 1;
+	regs->dstfmt = 1;
+
+	regs->actpx_bg2 = timing->begin_pixel_of_active;
+	regs->actpx_end2 = timing->end_pixel_of_active;
+	regs->h_allpxl2 = timing->total_pixel_of_line;
+
+	regs->actln_bg2 = timing->begin_line_of_active + 1;
+	regs->actln_end2 = timing->end_line_of_active + 1;
+	regs->v_allln2 = timing->total_line_of_frame;
+
+	regs->vbie_line2 = timing->line_number_between_VBIS_VBIE;
+	regs->pvbi_line2 = (timing->line_number_between_PVBI_VBIS < 6) ?
+		6 : timing->line_number_between_PVBI_VBIS;
+
+	regs->hdmi_hsynw2 = timing->hsync;
+	regs->hdmi_vbisw2 = timing->vsync;
+
+#ifdef DEBUG_DETAIL
+	vpp_show_timing("govrh tg2", 0, timing);
+#endif
+}
+
+void govrh_get_tg(struct govrh_mod_t *base, vpp_clock_t *tmr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	tmr->read_cycle = regs->read_cyc;
+	tmr->total_pixel_of_line = regs->h_allpxl;
+	tmr->begin_pixel_of_active = regs->actpx_bg;
+	tmr->end_pixel_of_active = regs->actpx_end;
+
+	tmr->total_line_of_frame = regs->v_allln;
+	tmr->begin_line_of_active = (regs->actln_bg - 1);
+	tmr->end_line_of_active = (regs->actln_end - 1);
+
+	tmr->line_number_between_VBIS_VBIE = regs->vbie_line;
+	tmr->line_number_between_PVBI_VBIS = regs->pvbi_line;
+
+	tmr->hsync = regs->hdmi_hsynw;
+	tmr->vsync = regs->hdmi_vbisw;
+
+	if (regs->tg_enable.b.mode) {
+		tmr->vsync = (tmr->vsync - 1) * 2;
+		tmr->begin_line_of_active = (tmr->begin_line_of_active - 1) * 2;
+		tmr->end_line_of_active = (tmr->end_line_of_active - 1) * 2;
+		tmr->total_line_of_frame = (tmr->total_line_of_frame - 1) * 2;
+	}
+}
+
+int govrh_get_hscale_up(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	int reg;
+
+	reg = regs->hscale_up & 0x1;
+	DBG_DETAIL("(govr %d,reg %d)\n", (base->mod == VPP_MOD_GOVRH) ?
+		1 : 2, reg);
+	return reg;
+}
+
+void govrh_set_direct_path(struct govrh_mod_t *base, int enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+		1 : 2, enable);
+
+	regs->dirpath = enable;
+}
+
+enum vpp_int_err_t govrh_get_int_status(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	enum vpp_int_err_t int_sts;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	int_sts = 0;
+	if (regs->interrupt.b.err_sts)
+		int_sts |= VPP_INT_ERR_GOVRH_MIF;
+	return int_sts;
+}
+
+void govrh_clean_int_status(struct govrh_mod_t *base,
+	enum vpp_int_err_t int_sts)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	unsigned int val;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+		1 : 2, int_sts);
+
+	if (int_sts & VPP_INT_ERR_GOVRH_MIF) {
+		val = regs->interrupt.val;
+		val = (val & 0xff) + 0x20000;
+		regs->interrupt.val = val;
+	}
+}
+
+void govrh_set_int_enable(struct govrh_mod_t *base,
+			vpp_flag_t enable, enum vpp_int_err_t int_bit)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+				1 : 2, enable);
+
+	/* clean status first before enable/disable interrupt */
+	govrh_clean_int_status(base, int_bit);
+
+	if (int_bit & VPP_INT_ERR_GOVRH_MIF)
+		regs->interrupt.b.mem_enable = enable;
+}
+
+int govrh_get_dvo_enable(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	return regs->dvo_set.b.enable;
+}
+
+void govrh_set_dvo_enable(struct govrh_mod_t *base, vpp_flag_t enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+/*	DPRINT("[GOVRH] %s(%d)\n",__FUNCTION__,enable); */
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable);
+
+	regs->dvo_set.b.enable = enable;
+	if (enable) {
+		/* GPIO to function pin */
+		outl(0x0, GPIO_BASE_ADDR + 0x44);
+		/* GPIO pull disable */
+		outl(0x0, GPIO_BASE_ADDR + 0x484);
+		/* 1:pullup,0:pulldn */
+		outl(0x0, GPIO_BASE_ADDR + 0x4C4);
+		return;
+	}
+	/* disable dvo */
+	outl(0xFFFFFFFF, GPIO_BASE_ADDR + 0x44); /* Enable GPIO */
+	outl(0x0, GPIO_BASE_ADDR + 0x84);  /* GPIO output enable */
+	outl(0x0, GPIO_BASE_ADDR + 0x484); /* GPIO pull disable */
+	outl(0x0, GPIO_BASE_ADDR + 0x4C4); /* 1:pullup,0:pulldn */
+}
+
+void govrh_set_dvo_sync_polar(struct govrh_mod_t *base,
+					vpp_flag_t hsync, vpp_flag_t vsync)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, hsync, vsync);
+
+	regs->dvo_set.b.hsync_polar = hsync;
+	regs->dvo_set.b.vsync_polar = vsync;
+}
+
+vdo_color_fmt govrh_get_dvo_color_format(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	if (regs->dvo_pix.b.rgb)
+		return VDO_COL_FMT_ARGB;
+	if (regs->dvo_pix.b.yuv422)
+		return VDO_COL_FMT_YUV422H;
+	return VDO_COL_FMT_YUV444;
+}
+
+void govrh_set_dvo_color_format(struct govrh_mod_t *base,
+	vdo_color_fmt fmt)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%s)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, vpp_colfmt_str[fmt]);
+
+	switch (fmt) {
+	case VDO_COL_FMT_ARGB:
+		regs->dvo_pix.b.rgb = 1;
+		regs->dvo_pix.b.yuv422 = 0;
+		break;
+	case VDO_COL_FMT_YUV422H:
+		regs->dvo_pix.b.rgb = 0;
+		regs->dvo_pix.b.yuv422 = 1;
+		break;
+	case VDO_COL_FMT_YUV444:
+	default:
+		regs->dvo_pix.b.rgb = 0;
+		regs->dvo_pix.b.yuv422 = 0;
+		break;
+	}
+}
+
+void govrh_set_dvo_outdatw(struct govrh_mod_t *base,
+	vpp_datawidht_t width)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	unsigned int clk_delay;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, width);
+
+	regs->dvo_set.b.outwidth = (width == VPP_DATAWIDHT_12) ? 1 : 0;
+
+	clk_delay = (width == VPP_DATAWIDHT_24) ?
+		VPP_GOVR_DVO_DELAY_24 : VPP_GOVR_DVO_DELAY_12;
+	govrh_set_dvo_clock_delay(base, ((clk_delay & BIT14) != 0x0),
+		clk_delay & 0x3FFF);
+}
+
+void govrh_set_dvo_clock_delay(struct govrh_mod_t *base,
+					int inverse, int delay)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d,%d)\n", (base->mod == VPP_MOD_GOVRH) ?
+		1 : 2, inverse, delay);
+
+#ifdef CONFIG_HW_DVO_DELAY
+	regs = p_govrh->mmio;
+#endif
+
+	regs->dvo_dly_sel.b.inv = inverse;
+	regs->dvo_dly_sel.b.delay = delay;
+}
+
+void govrh_set_colorbar(struct govrh_mod_t *base,
+				vpp_flag_t enable, int mode, int inv)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable);
+
+	regs->cb_enable.b.enable = enable;
+	regs->cb_enable.b.mode = mode;
+	regs->cb_enable.b.inversion = inv;
+}
+
+void govrh_set_contrast(struct govrh_mod_t *base, unsigned int value)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, value);
+
+	regs->contrast.val = value;
+}
+
+unsigned int govrh_get_contrast(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return regs->contrast.val;
+}
+
+void govrh_set_brightness(struct govrh_mod_t *base, unsigned int value)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, value);
+
+	regs->brightness = value;
+}
+
+unsigned int govrh_get_brightness(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return regs->brightness;
+}
+
+void govrh_set_saturation(struct govrh_mod_t *base, unsigned int value)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, value);
+
+	regs->saturation.val = value;
+	regs->saturation_enable.b.enable = 1;
+}
+
+unsigned int govrh_get_saturation(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return regs->saturation.val;
+}
+
+void govrh_set_MIF_enable(struct govrh_mod_t *base, vpp_flag_t enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable);
+
+	regs->mif.b.enable = enable;
+}
+
+int govrh_get_MIF_enable(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return regs->mif.b.enable;
+}
+
+void govrh_set_frame_mode(struct govrh_mod_t *base,
+				unsigned int width, vdo_color_fmt colfmt)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	int y_byte, c_byte;
+	int enable;
+
+	enable = 1;
+	vpp_get_colfmt_bpp(colfmt, &y_byte, &c_byte);
+	y_byte = width * y_byte / 8;
+	if (y_byte % 8)
+		enable = 0;
+	if (c_byte) {
+		c_byte = width * c_byte / 8;
+		if (c_byte % 8)
+			enable = 0;
+	}
+	if (regs->bufwid % 128)
+		enable = 0;
+	if (width == 720)
+		enable = 0;
+	regs->mif_frame_mode.b.frame_enable = enable;
+	regs->mif_frame_mode.b.req_num =
+		(y_byte / 128) + ((y_byte % 128) ? 1 : 0);
+	regs->mif_frame_mode.b.req_num_c =
+		(c_byte) ? ((c_byte / 128) + ((c_byte % 128) ? 1 : 0)) : 0;
+}
+
+void govrh_set_color_format(struct govrh_mod_t *base,
+	vdo_color_fmt format)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%s)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, vpp_colfmt_str[format]);
+
+	if (format < VDO_COL_FMT_ARGB)
+		regs->yuv2rgb.b.rgb_mode = 0;
+
+	switch (format) {
+	case VDO_COL_FMT_YUV420:
+		regs->colfmt = 1;
+		regs->colfmt2 = 0;
+		break;
+	case VDO_COL_FMT_YUV422H:
+		regs->colfmt = 0;
+		regs->colfmt2 = 0;
+		break;
+	case VDO_COL_FMT_YUV444:
+		regs->colfmt = 0;
+		regs->colfmt2 = 1;
+		break;
+	case VDO_COL_FMT_ARGB:
+		regs->yuv2rgb.b.rgb_mode = 1;
+		break;
+	case VDO_COL_FMT_RGB_1555:
+		regs->yuv2rgb.b.rgb_mode = 2;
+		break;
+	case VDO_COL_FMT_RGB_565:
+		regs->yuv2rgb.b.rgb_mode = 3;
+		break;
+	default:
+		DBGMSG("*E* check the parameter\n");
+		return;
+	}
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+	govrh_CUR_set_colfmt((struct govrh_cursor_mod_t *)p_cursor, format);
+#endif
+	govrh_set_frame_mode(base, regs->pixwid, format);
+	regs->saturation_enable.b.format = (regs->yuv2rgb.b.rgb_mode) ? 1 : 0;
+}
+
+vdo_color_fmt govrh_get_color_format(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	switch (regs->yuv2rgb.b.rgb_mode) {
+	case 1:
+		return VDO_COL_FMT_ARGB;
+	case 2:
+		return VDO_COL_FMT_RGB_1555;
+	case 3:
+		return VDO_COL_FMT_RGB_565;
+	default:
+		break;
+	}
+	if (regs->colfmt2)
+		return VDO_COL_FMT_YUV444;
+	if (regs->colfmt)
+		return VDO_COL_FMT_YUV420;
+	return VDO_COL_FMT_YUV422H;
+}
+
+void govrh_set_source_format(struct govrh_mod_t *base,
+					vpp_display_format_t format)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, format);
+
+	regs->srcfmt = (format == VPP_DISP_FMT_FIELD) ? 1 : 0;
+}
+
+void govrh_set_output_format(struct govrh_mod_t *base,
+					vpp_display_format_t field)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, field);
+
+	regs->dstfmt = (field == VPP_DISP_FMT_FIELD) ? 1 : 0;
+}
+
+void govrh_set_fb_addr(struct govrh_mod_t *base,
+			unsigned int y_addr, unsigned int c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	/* DBG_DETAIL("(govr %d,0x%x,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH)? 1:2,y_addr,c_addr); */
+#ifdef DEBUG
+	if ((y_addr % GOVRH_FRAMEBUF_ALIGN) || (c_addr % GOVRH_FRAMEBUF_ALIGN))
+		DBG_ERR("addr should align %d(0x%x,0x%x)\n",
+		GOVRH_FRAMEBUF_ALIGN, y_addr, c_addr);
+#endif
+	regs->ysa = y_addr;
+	regs->csa = c_addr;
+}
+
+void govrh_get_fb_addr(struct govrh_mod_t *base,
+				unsigned int *y_addr, unsigned int *c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	*y_addr = regs->ysa;
+	*c_addr = regs->csa;
+
+	DBG_DETAIL("(govr %d,0x%x,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, *y_addr, *c_addr);
+}
+
+void govrh_set_fb2_addr(struct govrh_mod_t *base,
+			unsigned int y_addr, unsigned int c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,0x%x,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, y_addr, c_addr);
+#ifdef DEBUG
+	if ((y_addr % GOVRH_FRAMEBUF_ALIGN) || (c_addr % GOVRH_FRAMEBUF_ALIGN))
+		DBG_ERR("addr should align %d(0x%x,0x%x)\n",
+				GOVRH_FRAMEBUF_ALIGN, y_addr, c_addr);
+#endif
+	regs->ysa2 = y_addr;
+	regs->csa2 = c_addr;
+}
+
+void govrh_get_fb2_addr(struct govrh_mod_t *base,
+			unsigned int *y_addr, unsigned int *c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	*y_addr = regs->ysa2;
+	*c_addr = regs->csa2;
+
+	DBG_DETAIL("(govr %d,0x%x,0x%x)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, *y_addr, *c_addr);
+}
+
+void govrh_set_fb_width(struct govrh_mod_t *base, unsigned int width)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, width);
+
+	regs->bufwid = width;
+}
+
+#define GOVRH_CURSOR_RIGHT_POS		6
+void govrh_set_fb_info(struct govrh_mod_t *base, unsigned int width,
+	unsigned int act_width, unsigned int x_offset, unsigned int y_offset)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,fb_w %d,img_w %d,x %d,y %d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2,
+		width, act_width, x_offset, y_offset);
+
+	regs->pixwid = act_width;
+	regs->bufwid = width;
+	regs->hcrop = x_offset;
+	regs->vcrop = y_offset;
+	govrh_set_frame_mode(base, act_width, govrh_get_color_format(base));
+
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+	/* cursor postion over when change resolution */
+	if ((regs->actpx_end - regs->actpx_bg) != regs->pixwid) {
+		if (regs->cur_hcoord.b.end >=
+			(regs->pixwid - GOVRH_CURSOR_RIGHT_POS)) {
+			int pos;
+
+			pos = regs->pixwid - GOVRH_CURSOR_RIGHT_POS;
+			regs->cur_hcoord.b.end = pos;
+			pos -= regs->cur_width;
+			regs->cur_hcoord.b.start = (pos+1);
+
+			p_cursor->posx = pos;
+		}
+	}
+#endif
+}
+
+void govrh_get_fb_info(struct govrh_mod_t *base, unsigned int *width,
+	unsigned int *act_width, unsigned int *x_offset, unsigned int *y_offset)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	*act_width = regs->pixwid;
+	*width = regs->bufwid;
+	*x_offset = regs->hcrop;
+	*y_offset = regs->vcrop;
+}
+
+void govrh_set_fifo_index(struct govrh_mod_t *base, unsigned int index)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, index);
+
+	regs->fhi = index;
+}
+
+void govrh_set_reg_level(struct govrh_mod_t *base, vpp_reglevel_t level)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, level);
+
+	regs->sts.b.level = (level == VPP_REG_LEVEL_1) ? 0 : 1;
+}
+
+void govrh_set_reg_update(struct govrh_mod_t *base, vpp_flag_t enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, enable);
+
+	regs->sts.b.update = enable;
+}
+
+void govrh_set_tg(struct govrh_mod_t *base,
+			vpp_clock_t *tmr, unsigned int pixel_clock)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	int tg_enable;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, pixel_clock);
+
+	tg_enable = regs->tg_enable.b.enable;
+	regs->tg_enable.b.enable = 0;
+
+	tmr->read_cycle = govrh_set_clock(base, pixel_clock);
+	govrh_set_tg1(base, tmr);
+
+	regs->tg_enable.b.enable = tg_enable;
+}
+
+void govrh_set_csc_mode(struct govrh_mod_t *base, vpp_csc_t mode)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	vdo_color_fmt src_fmt, dst_fmt;
+	unsigned int enable;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode);
+
+	enable = 0;
+	src_fmt = (govrh_get_color_format(base) < VDO_COL_FMT_ARGB) ?
+		VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB;
+	dst_fmt = (govrh_get_dvo_color_format(base) < VDO_COL_FMT_ARGB) ?
+		VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB;
+	if (src_fmt == VDO_COL_FMT_ARGB)
+		enable |= (dst_fmt != VDO_COL_FMT_ARGB) ? BIT0 : 0x00; /* DVO */
+	else
+		enable |= (dst_fmt == VDO_COL_FMT_ARGB) ? BIT0 : 0x00; /* DVO */
+#ifdef WMT_FTBLK_LVDS
+	vpp_set_clock_enable(DEV_LVDS, 1, 0);
+	if (src_fmt == VDO_COL_FMT_ARGB) {
+		if (lvds_get_colfmt() < VDO_COL_FMT_ARGB)
+			enable |= BIT3;
+	} else {
+		if (lvds_get_colfmt() >= VDO_COL_FMT_ARGB)
+			enable |= BIT3;
+	}
+	vpp_set_clock_enable(DEV_LVDS, 0, 0);
+#endif
+#ifdef WMT_FTBLK_HDMI
+	vpp_set_clock_enable(DEV_HDMI, 1, 0);
+	if (src_fmt == VDO_COL_FMT_ARGB) {
+		if (hdmi_get_output_colfmt() < VDO_COL_FMT_ARGB)
+			enable |= BIT4;
+	} else {
+		if (hdmi_get_output_colfmt() >= VDO_COL_FMT_ARGB)
+			enable |= BIT4;
+	}
+	vpp_set_clock_enable(DEV_HDMI, 0, 0);
+#endif
+	mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, enable);
+	if (mode >= VPP_CSC_MAX) {
+		enable = 0;
+		/* for internal color bar (YUV base) */
+		mode = base->fb_p->csc_mode;
+	}
+
+	mode = (base->csc_mode_force) ? base->csc_mode_force : mode;
+
+	regs->dmacsc_coef0 = vpp_csc_parm[mode][0]; /* C1,C2 */
+	regs->dmacsc_coef1 = vpp_csc_parm[mode][1]; /* C3,C4 */
+	regs->dmacsc_coef2 = vpp_csc_parm[mode][2]; /* C5,C6 */
+	regs->dmacsc_coef3 = vpp_csc_parm[mode][3]; /* C7,C8 */
+	regs->dmacsc_coef4 = vpp_csc_parm[mode][4] & 0xFFFF; /* C9 */
+	regs->dmacsc_coef5 = ((vpp_csc_parm[mode][4] & 0xFFFF0000) >> 16) +
+			((vpp_csc_parm[mode][5] & 0xFFFF) << 16); /* I,J */
+	regs->dmacsc_coef6 = (vpp_csc_parm[mode][5] & 0xFFFF0000) >> 16; /* K */
+	regs->csc_mode.val = (vpp_csc_parm[mode][6] & BIT0) +
+			((vpp_csc_parm[mode][6] & BIT8) ? BIT1 : 0x0);
+
+	/* enable bit0:DVO, bit1:VGA, bit2:DISP, bit3:LVDS, bit4:HDMI */
+	regs->yuv2rgb.b.blank_zero = 1;
+	regs->yuv2rgb.b.dac_clkinv = 1;
+	regs->yuv2rgb.b.reserved1 =
+		(mode >= VPP_CSC_RGB2YUV_SDTV_0_255) ? 1 : 0;
+	regs->yuv2rgb.b.dvo = (enable & BIT0) ? 1 : 0;
+#ifdef WMT_FTBLK_LVDS
+	regs->yuv2rgb.b.lvds = (enable & BIT3) ? 1 : 0;
+#endif
+#ifdef WMT_FTBLK_HDMI
+	regs->yuv2rgb.b.hdmi = (enable & BIT4) ? 1 : 0;
+#endif
+}
+
+void govrh_set_media_format(struct govrh_mod_t *base, vpp_flag_t h264)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, h264);
+
+	regs->mif.b.h264 = h264;
+}
+
+void govrh_HDMI_set_blank_value(struct govrh_mod_t *base,
+	unsigned int val)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2, val);
+
+	regs->hdmi_3d.b.blank_value = val;
+}
+
+void govrh_HDMI_set_3D_mode(struct govrh_mod_t *base, int mode)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode);
+
+	/* 0-disable,3-frame pack progress(use fb1&2),7-frame pack interlace */
+	regs->hdmi_3d.b.mode = mode;
+}
+
+int govrh_is_top_field(struct govrh_mod_t *base)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	return (regs->field_status) ? 1 : 0;
+}
+
+/*----------------------- GOVRH IGS --------------------------------------*/
+void govrh_IGS_set_mode(struct govrh_mod_t *base,
+				int no, int mode_18bit, int msb)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2, no);
+
+	if (no == 0) { /* DVO */
+		/* 0-24bit,10-18bit,01-555,11-565 */
+		regs->igs_mode.b.mode = mode_18bit;
+		regs->igs_mode.b.ldi = msb; /* 0-lsb,1-msb */
+	} else { /* LVDS */
+		/* 0-24bit,10-18bit,01-555,11-565 */
+		regs->igs_mode2.b.mode = mode_18bit;
+		regs->igs_mode2.b.ldi = msb; /* 0-lsb,1-msb */
+	}
+}
+
+void govrh_IGS_set_RGB_swap(struct govrh_mod_t *base, int mode)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	DBG_DETAIL("(govr %d,%d)\n",
+		(base->mod == VPP_MOD_GOVRH) ? 1 : 2, mode);
+
+	/* 0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7] */
+	regs->dvo_set.b.rgb_swap = mode;
+}
+
+/*----------------------- GOVRH CURSOR --------------------------------------*/
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+#define CONFIG_GOVR2_CURSOR
+void *govrh_CUR_get_mmio(struct govrh_cursor_mod_t *base)
+{
+#ifdef CONFIG_GOVR2_CURSOR
+	base = (struct govrh_cursor_mod_t *)
+		((govrh_get_MIF_enable(p_govrh)) ? p_govrh : p_govrh2);
+#endif
+	return base->mmio;
+}
+
+void govrh_CUR_set_enable(struct govrh_cursor_mod_t *base,
+	vpp_flag_t enable)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x,%d)\n", base->mmio, enable);
+
+	regs->cur_status.b.enable = enable;
+}
+
+void govrh_CUR_set_fb_addr(struct govrh_cursor_mod_t *base,
+				unsigned int y_addr, unsigned int c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x,0x%x,0x%x)\n", base->mmio, y_addr, c_addr);
+
+	regs->cur_addr = y_addr;
+}
+
+void govrh_CUR_get_fb_addr(struct govrh_cursor_mod_t *base,
+			unsigned int *y_addr, unsigned int *c_addr)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	*y_addr = regs->cur_addr;
+	*c_addr = 0;
+
+	DBG_DETAIL("(0x%x,0x%x,0x%x)\n", base->mmio, *y_addr, *c_addr);
+}
+
+void govrh_CUR_set_coordinate(struct govrh_cursor_mod_t *base,
+	unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x)\n", base->mmio);
+
+	regs->cur_hcoord.b.start = x1;
+	regs->cur_hcoord.b.end = x2;
+	regs->cur_vcoord.b.start = y1;
+	regs->cur_vcoord.b.end = y2;
+}
+
+void govrh_CUR_set_position(struct govrh_cursor_mod_t *base,
+					unsigned int x, unsigned int y)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+	unsigned int w, h;
+
+	DBG_DETAIL("(0x%x,%d,%d)\n", base->mmio, x, y);
+
+/*	w = regs->cur_hcoord.b.end - regs->cur_hcoord.b.start; */
+	w = regs->cur_width - 1;
+	h = regs->cur_vcoord.b.end - regs->cur_vcoord.b.start;
+	govrh_CUR_set_coordinate(base, x, y, x+w, y+h);
+}
+
+void govrh_CUR_set_color_key_mode(struct govrh_cursor_mod_t *base,
+					int enable, int alpha, int mode)
+{
+	/*
+		if( colkey_en )
+			colkey_hit = (mode)? (data == colkey):(data != colkey);
+
+		if( (alpha_en) or (colkey_hit) or (alpha value) )
+			show pixel
+	*/
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x,%d,%d,%d)\n", base->mmio, enable, alpha, mode);
+
+	regs->cur_color_key.b.alpha = alpha;
+	regs->cur_color_key.b.enable = enable;
+	regs->cur_color_key.b.invert = mode;
+}
+
+void govrh_CUR_set_color_key(struct govrh_cursor_mod_t *base,
+				int enable, int alpha, unsigned int colkey)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x,0x%x)\n", base->mmio, colkey);
+
+	regs->cur_color_key.b.colkey = colkey;
+	regs->cur_color_key.b.alpha = 0;
+	regs->cur_color_key.b.enable = 0;
+
+#ifdef __KERNEL__
+	if (!(alpha) && enable) {
+		int i, j;
+		unsigned int *ptr1, *ptr2;
+		int yuv2rgb;
+
+		ptr1 = (unsigned int *)mb_phys_to_virt(regs->cur_addr);
+		for (i = 0; i < base->fb_p->fb.fb_h; i++) {
+			for (j = 0; j < base->fb_p->fb.fb_w; j++) {
+				if ((*ptr1 & 0xFFFFFF) == (colkey & 0xFFFFFF))
+					*ptr1 &= 0xFFFFFF;
+				else
+					*ptr1 |= 0xFF000000;
+				ptr1++;
+			}
+		}
+
+		yuv2rgb = (base->colfmt < VDO_COL_FMT_ARGB) ? 1 : 0;
+		ptr1 = (unsigned int *) mb_phys_to_virt(base->cursor_addr1);
+		ptr2 = (unsigned int *) mb_phys_to_virt(base->cursor_addr2);
+		for (i = 0; i < base->fb_p->fb.fb_h; i++) {
+			for (j = 0; j < base->fb_p->fb.fb_w; j++) {
+				*ptr2 = vpp_convert_colfmt(yuv2rgb, *ptr1);
+				ptr1++;
+				ptr2++;
+			}
+		}
+	}
+#endif
+}
+
+void govrh_CUR_set_colfmt(struct govrh_cursor_mod_t *base,
+					vdo_color_fmt colfmt)
+{
+#ifdef __KERNEL__
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+#endif
+
+	DBG_DETAIL("(0x%x,%s)\n", base->mmio, vpp_colfmt_str[colfmt]);
+
+	colfmt = (colfmt < VDO_COL_FMT_ARGB) ?
+			VDO_COL_FMT_YUV444 : VDO_COL_FMT_ARGB;
+	if (base->fb_p->fb.col_fmt == colfmt)
+		return;
+
+	base->fb_p->fb.col_fmt = colfmt;
+#ifdef __KERNEL__
+	regs->cur_addr = (base->colfmt == colfmt) ?
+			base->cursor_addr1 : base->cursor_addr2;
+#endif
+	DBG_DETAIL("(0x%x)\n", regs->cur_addr);
+}
+
+int govrh_irqproc_set_position(void *arg)
+{
+	struct govrh_cursor_mod_t *base = (struct govrh_cursor_mod_t *) arg;
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	int begin;
+	int pos_x, pos_y;
+	int crop_x, crop_y;
+	int width, height;
+	int govrh_w, govrh_h;
+
+	govrh_w = regs->actpx_end - regs->actpx_bg;
+	govrh_h = regs->actln_end - regs->actln_bg;
+	if (regs->tg_enable.b.mode)
+		govrh_h *= 2;
+
+	/* cursor H */
+	width = base->fb_p->fb.img_w;
+	begin = base->posx - base->hotspot_x;
+	if (begin < 0) {	/* over left edge */
+		pos_x = 0;
+		crop_x = 0 - begin;
+		width = width - crop_x;
+	} else {
+		pos_x = begin;
+		crop_x = 0;
+	}
+	if ((begin + base->fb_p->fb.img_w) > govrh_w) /* over right edge */
+		width = govrh_w - begin;
+
+/*	DPRINT("[CURSOR] H pos %d,hotspot %d,posx %d,crop %d,width %d\n",
+		p_cursor->posx,p_cursor->hotspot_x,pos_x,crop_x,width); */
+
+	/* cursor V */
+	height = base->fb_p->fb.img_h;
+	begin = base->posy - base->hotspot_y;
+	if (begin < 0) { /* over top edge */
+		pos_y = 0;
+		crop_y = 0 - begin;
+		height = height - crop_y;
+	} else {
+		pos_y = begin;
+		crop_y = 0;
+	}
+	if ((begin + base->fb_p->fb.img_h) > govrh_h) /* over right edge */
+		height = govrh_h - begin;
+
+	if (regs->tg_enable.b.mode) {
+		regs->cur_fb_width = (base->fb_p->fb.fb_w*2);
+		pos_y /= 2;
+		crop_y /= 2;
+		height /= 2;
+	} else
+		regs->cur_fb_width = base->fb_p->fb.fb_w;
+
+/*	DPRINT("[CURSOR] V pos %d,hotspot %d,posx %d,crop %d,height %d\n",
+		p_cursor->posy,p_cursor->hotspot_y,pos_y,crop_y,height); */
+
+	regs->cur_width = width;
+	regs->cur_vcrop = crop_y;
+	regs->cur_hcrop = crop_x;
+	govrh_CUR_set_coordinate(base, pos_x, pos_y,
+		pos_x + width - 1, pos_y + height - 1);
+	return 0;
+}
+
+void govrh_CUR_irqproc(int arg)
+{
+	if (p_cursor->enable) {
+		if (p_cursor->chg_flag) {
+			p_cursor->hide_cnt = 0;
+			govrh_CUR_set_enable(p_cursor, 1);
+		} else {
+			p_cursor->hide_cnt++;
+			if (p_cursor->hide_cnt >
+			(GOVRH_CURSOR_HIDE_TIME * p_govrh->fb_p->framerate))
+				govrh_CUR_set_enable(p_cursor, 0);
+		}
+	}
+
+	if (p_cursor->chg_flag) {
+		govrh_irqproc_set_position(p_cursor);
+		p_cursor->chg_flag = 0;
+	}
+}
+
+void govrh_CUR_proc_view(struct govrh_cursor_mod_t *base,
+					int read, vdo_view_t *view)
+{
+	vdo_framebuf_t *fb;
+
+	DBG_DETAIL("(0x%x)\n", base->mmio);
+
+	fb = &base->fb_p->fb;
+	if (read) {
+		view->resx_src = fb->fb_w;
+		view->resy_src = fb->fb_h;
+		view->resx_virtual = fb->img_w;
+		view->resy_virtual = fb->img_h;
+		view->resx_visual = fb->img_w;
+		view->resy_visual = fb->img_h;
+		view->posx = base->posx;
+		view->posy = base->posy;
+		view->offsetx = fb->h_crop;
+		view->offsety = fb->v_crop;
+	} else {
+		base->posx = view->posx;
+		base->posy = view->posy;
+		base->chg_flag = 1;
+	}
+}
+
+void govrh_CUR_set_framebuffer(struct govrh_cursor_mod_t *base,
+					vdo_framebuf_t *fb)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) govrh_CUR_get_mmio(base);
+
+	DBG_DETAIL("(0x%x)\n", base->mmio);
+
+	regs->cur_addr = fb->y_addr;
+	regs->cur_width = fb->img_w;
+	if (regs->tg_enable.b.mode)
+		regs->cur_fb_width = (fb->fb_w*2);
+	else
+		regs->cur_fb_width = fb->fb_w;
+	regs->cur_vcrop = fb->v_crop;
+	regs->cur_hcrop = fb->h_crop;
+	regs->cur_status.b.out_field = vpp_get_fb_field(fb);
+	govrh_irqproc_set_position(base);
+	base->colfmt = fb->col_fmt;
+	base->cursor_addr1 = fb->y_addr;
+#ifdef __KERNEL__
+	if (base->cursor_addr2 == 0)
+		base->cursor_addr2 = mb_alloc(64*64*4);
+#endif
+	vpp_cache_sync();
+}
+
+void govrh_CUR_init(void *base)
+{
+#ifdef CONFIG_GOVR2_CURSOR
+	HW_REG struct govrh_regs *regs;
+
+	regs = (HW_REG struct govrh_regs *) p_govrh->mmio;
+	regs->cur_color_key.b.invert = 1;
+	regs = (HW_REG struct govrh_regs *) p_govrh2->mmio;
+	regs->cur_color_key.b.invert = 1;
+#else
+	struct govrh_cursor_mod_t *mod_p;
+	HW_REG struct govrh_regs *regs;
+
+	mod_p = (struct govrh_cursor_mod_t *) base;
+	regs = (HW_REG struct govrh_regs *) mod_p->mmio;
+
+	regs->cur_color_key.b.invert = 1;
+#endif
+}
+#endif /* WMT_FTBLK_GOVRH_CURSOR */
+
+/*----------------------- GOVRH API --------------------------------------*/
+void govrh_vmode_to_timing(vpp_mod_t mod,
+				struct fb_videomode *vmode, vpp_clock_t *t)
+{
+	unsigned int pixel_clock;
+	int temp;
+
+	t->begin_pixel_of_active = vmode->hsync_len + vmode->left_margin;
+	t->end_pixel_of_active = t->begin_pixel_of_active + vmode->xres;
+	t->total_pixel_of_line = t->end_pixel_of_active + vmode->right_margin;
+	t->begin_line_of_active = vmode->vsync_len + vmode->upper_margin;
+	t->end_line_of_active = t->begin_line_of_active + vmode->yres;
+	t->total_line_of_frame = t->end_line_of_active + vmode->lower_margin;
+	t->line_number_between_VBIS_VBIE = vmode->vsync_len + 1;
+	temp = t->total_line_of_frame - t->end_line_of_active;
+	t->line_number_between_PVBI_VBIS = (temp > 2) ? (temp-1) : 1;
+	t->hsync = vmode->hsync_len;
+	t->vsync = vmode->vsync_len;
+
+	pixel_clock = PICOS2KHZ(vmode->pixclock) * 1000;
+	t->read_cycle = vpp_get_base_clock(mod) / pixel_clock;
+}
+
+void govrh_set_videomode(struct govrh_mod_t *base,
+					struct fb_videomode *p_vmode)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	struct fb_videomode vmode;
+	vpp_clock_t t1;
+	int tg_enable;
+
+	DBG_MSG("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	tg_enable = regs->tg_enable.b.enable;
+	regs->tg_enable.b.enable = 0;
+
+	vmode = *p_vmode;
+	if (vmode.vmode & FB_VMODE_DOUBLE) {
+		vmode.xres *= 2;
+		DBGMSG("[GOVRH] H scale up\n");
+	}
+
+	if (vmode.vmode & FB_VMODE_INTERLACED) {
+		vmode.vsync_len /= 2;
+		vmode.upper_margin /= 2;
+		vmode.yres /= 2;
+		vmode.lower_margin /= 2;
+	}
+
+	govrh_vmode_to_timing(base->mod, &vmode, &t1);
+	t1.read_cycle = govrh_set_clock(base, PICOS2KHZ(vmode.pixclock)*1000);
+	if (vmode.vmode & FB_VMODE_INTERLACED) {
+		t1.total_line_of_frame += 1;
+		t1.begin_line_of_active += 1;
+		t1.end_line_of_active += 1;
+		t1.vsync += 1;
+	}
+	govrh_set_tg1(base, &t1);
+
+	if (vmode.vmode & FB_VMODE_INTERLACED) {
+		vpp_clock_t t2;
+
+		vmode.upper_margin += 1;
+		/* 480i/576i repeat 2 pixel */
+		if (vmode.vmode & FB_VMODE_DOUBLE)
+			vmode.xres *= 2;
+		govrh_vmode_to_timing(base->mod, &vmode, &t2);
+		t2.total_line_of_frame -= 1;
+		t2.vsync += 1;
+		govrh_set_tg2(base, &t2);
+	}
+	govrh_set_output_format(base,
+		(vmode.vmode & FB_VMODE_INTERLACED) ? 1 : 0);
+	regs->hscale_up = (vmode.vmode & FB_VMODE_DOUBLE) ? 1 : 0;
+	regs->vsync_offset.val = (vmode.vmode & FB_VMODE_INTERLACED) ?
+		((regs->h_allpxl / 2) | BIT16) : 0;
+
+	regs->tg_enable.b.enable = tg_enable;
+}
+
+void govrh_get_videomode(struct govrh_mod_t *base,
+	struct fb_videomode *vmode)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	vpp_clock_t t;
+	int htotal, vtotal;
+	unsigned int pixel_clock;
+
+	vmode->flag = FB_MODE_IS_FROM_VAR;
+	vmode->name = 0;
+
+	govrh_get_tg(base, &t);
+	pixel_clock = vpp_get_base_clock(base->mod);
+	vmode->pixclock = KHZ2PICOS(pixel_clock/1000);
+
+	vmode->hsync_len = t.hsync;
+	vmode->left_margin = t.begin_pixel_of_active - t.hsync;
+	vmode->xres = t.end_pixel_of_active - t.begin_pixel_of_active;
+	vmode->right_margin = t.total_pixel_of_line - t.end_pixel_of_active;
+
+	vmode->vsync_len = t.vsync;
+	vmode->upper_margin = t.begin_line_of_active - t.vsync;
+	vmode->yres = t.end_line_of_active - t.begin_line_of_active;
+	vmode->lower_margin = t.total_line_of_frame - t.end_line_of_active;
+
+	htotal = vmode->xres + vmode->right_margin
+		+ vmode->hsync_len + vmode->left_margin;
+	vtotal = vmode->yres + vmode->lower_margin
+		+ vmode->vsync_len + vmode->upper_margin;
+	vmode->vmode = (regs->tg_enable.b.mode) ? FB_VMODE_INTERLACED : 0;
+	if (vmode->vmode & FB_VMODE_INTERLACED)
+		vtotal /= 2;
+	if (vmode->vmode & FB_VMODE_DOUBLE)
+		vtotal *= 2;
+
+	if (htotal && vtotal) {
+		unsigned int temp;
+		temp = (pixel_clock * 10)/(htotal * vtotal);
+		vmode->refresh = temp / 10;
+		if ((temp % 10) >= 5)
+			vmode->refresh += 1;
+	} else
+		vmode->refresh = 60;
+
+	{ /* get sync polar */
+		int hsync_hi, vsync_hi;
+		enum vout_inf_mode_t interface;
+
+		switch (base->mod) {
+		case VPP_MOD_GOVRH:
+			interface = VOUT_INF_HDMI;
+			break;
+		case VPP_MOD_GOVRH2:
+			interface = VOUT_INF_DVI;
+			if (lcd_get_type())
+				interface = VOUT_INF_LVDS;
+				break;
+		default:
+			interface = VOUT_INF_DVI;
+			break;
+		}
+
+		switch (interface) {
+		case VOUT_INF_DVI:
+			hsync_hi = (regs->dvo_set.b.hsync_polar) ? 0 : 1;
+			vsync_hi = (regs->dvo_set.b.vsync_polar) ? 0 : 1;
+			break;
+		case VOUT_INF_HDMI:
+			vo_hdmi_set_clock(1);
+			hdmi_get_sync_polar(&hsync_hi, &vsync_hi);
+			vo_hdmi_set_clock(0);
+			break;
+		case VOUT_INF_LVDS:
+			lvds_get_sync_polar(&hsync_hi, &vsync_hi);
+			break;
+		default:
+			hsync_hi = 0;
+			vsync_hi = 0;
+			break;
+		}
+		vmode->sync = (hsync_hi) ? FB_SYNC_HOR_HIGH_ACT : 0;
+		vmode->sync |= (vsync_hi) ? FB_SYNC_VERT_HIGH_ACT : 0;
+	}
+}
+
+void govrh_set_framebuffer(struct govrh_mod_t *base, vdo_framebuf_t *fb)
+{
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	govrh_set_fb_addr(base, fb->y_addr, fb->c_addr);
+	govrh_set_color_format(base, fb->col_fmt);
+	govrh_set_fb_info(base, fb->fb_w, fb->img_w, fb->h_crop, fb->v_crop);
+	govrh_set_source_format(base, vpp_get_fb_field(fb));
+	govrh_set_csc_mode(base, base->fb_p->csc_mode);
+}
+
+void govrh_get_framebuffer(struct govrh_mod_t *base, vdo_framebuf_t *fb)
+{
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+	vpp_clock_t clock;
+	int y_bpp, c_bpp;
+
+	DBG_DETAIL("(govr %d)\n", (base->mod == VPP_MOD_GOVRH) ? 1 : 2);
+
+	govrh_get_fb_addr(base, &fb->y_addr, &fb->c_addr);
+	fb->col_fmt = govrh_get_color_format(base);
+	govrh_get_fb_info(base, &fb->fb_w,
+		&fb->img_w, &fb->h_crop, &fb->v_crop);
+	govrh_get_tg(base, &clock);
+	fb->img_h = clock.end_line_of_active - clock.begin_line_of_active;
+	fb->fb_h = fb->img_h;
+	fb->flag = (regs->srcfmt) ? VDO_FLAG_INTERLACE : 0;
+	vpp_get_colfmt_bpp(fb->col_fmt, &y_bpp, &c_bpp);
+	fb->bpp = y_bpp + c_bpp;
+	fb->y_size = fb->fb_w * fb->fb_h * y_bpp / 8;
+	fb->c_size = fb->fb_w * fb->fb_h * c_bpp / 8;
+}
+
+/*----------------------- GOVRH MODULE API -----------------------------*/
+int govrh_suspend_yaddr;
+void govrh_suspend(struct govrh_mod_t *base, int sts)
+{
+#ifdef CONFIG_PM
+	HW_REG struct govrh_regs *regs =
+		(HW_REG struct govrh_regs *) base->mmio;
+
+	switch (sts) {
+	case 0:	/* disable module */
+		base->pm_enable = govrh_get_MIF_enable(base);
+		govrh_set_MIF_enable(base, 0);
+		break;
+	case 1: /* disable tg */
+		base->pm_tg = regs->tg_enable.b.enable;
+		govrh_set_tg_enable(base, 0);
+		break;
+	case 2:	/* backup register */
+		base->reg_bk = vpp_backup_reg((unsigned int)base->mmio,
+			(REG_GOVRH_BASE2_END-REG_GOVRH_BASE1_BEGIN));
+		if (base->vo_clock == 0)
+			base->vo_clock = vpp_get_base_clock(base->mod);
+		govrh_suspend_yaddr = 0;
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
+void govrh_resume(struct govrh_mod_t *base, int sts)
+{
+#ifdef CONFIG_PM
+	switch (sts) {
+	case 0:	/* restore register */
+		govrh_set_clock(base, base->vo_clock);
+		vpp_restore_reg((unsigned int)base->mmio,
+			(REG_GOVRH_BASE2_END-REG_GOVRH_BASE1_BEGIN),
+			base->reg_bk);
+		if (base == p_govrh && govrh_suspend_yaddr)
+			govrh_set_fb_addr(p_govrh, govrh_suspend_yaddr, 0);
+		base->reg_bk = 0;
+		break;
+	case 1:	/* enable module */
+		govrh_set_MIF_enable(base, base->pm_enable);
+		break;
+	case 2: /* enable tg */
+		govrh_set_tg_enable(base, base->pm_tg);
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
+void govrh_init(void *base)
+{
+	struct govrh_mod_t *mod_p;
+	HW_REG struct govrh_regs *regs;
+
+	mod_p = (struct govrh_mod_t *) base;
+	regs = (HW_REG struct govrh_regs *) mod_p->mmio;
+
+	govrh_set_reg_level(base, VPP_REG_LEVEL_1);
+	govrh_set_colorbar(base, VPP_FLAG_DISABLE, 1, 0);
+	govrh_set_tg_enable(base, VPP_FLAG_ENABLE);
+	govrh_set_dvo_color_format(base, VDO_COL_FMT_ARGB);
+	govrh_set_dvo_enable(base, VPP_FLAG_DISABLE);
+
+	govrh_set_framebuffer(base, &mod_p->fb_p->fb);
+	govrh_set_fifo_index(base, 0xf);
+	govrh_set_csc_mode(base, mod_p->fb_p->csc_mode);
+
+	govrh_set_reg_update(base, VPP_FLAG_ENABLE);
+	govrh_set_tg_enable(base, VPP_FLAG_ENABLE);
+/*	govrh_set_MIF_enable(base, VPP_FLAG_ENABLE); */
+	govrh_set_int_enable(base, VPP_FLAG_ENABLE, mod_p->int_catch);
+}
+
+void govrh_mod_dump_reg(void)
+{
+	govrh_reg_dump((void *)p_govrh);
+}
+
+void govrh_mod_set_enable(vpp_flag_t enable)
+{
+	govrh_set_MIF_enable(p_govrh, enable);
+}
+
+void govrh_mod_set_colorbar(vpp_flag_t enable, int mode, int inv)
+{
+	govrh_set_colorbar(p_govrh, enable, mode, inv);
+}
+
+void govrh_mod_set_tg(vpp_clock_t *tmr, unsigned int pixel_clock)
+{
+	govrh_set_tg(p_govrh, tmr, pixel_clock);
+}
+
+void govrh_mod_get_tg(vpp_clock_t *tmr)
+{
+	govrh_get_tg(p_govrh, tmr);
+}
+
+unsigned int govrh_mod_get_sts(void)
+{
+	return govrh_get_int_status(p_govrh);
+}
+
+void govrh_mod_clr_sts(unsigned int sts)
+{
+	govrh_clean_int_status(p_govrh, sts);
+}
+
+void govrh_mod_suspend(int sts)
+{
+	govrh_suspend(p_govrh, sts);
+}
+
+void govrh_mod_resume(int sts)
+{
+	govrh_resume(p_govrh, sts);
+}
+
+void govrh_mod_set_framebuf(vdo_framebuf_t *fb)
+{
+	govrh_set_framebuffer(p_govrh, fb);
+}
+void govrh_mod_set_addr(unsigned int yaddr, unsigned int caddr)
+{
+	govrh_set_fb_addr(p_govrh, yaddr, caddr);
+}
+void govrh_mod_get_addr(unsigned int *yaddr, unsigned int *caddr)
+{
+	govrh_get_fb_addr(p_govrh, yaddr, caddr);
+}
+void govrh_mod_set_csc(vpp_csc_t mode)
+{
+	govrh_set_csc_mode(p_govrh, mode);
+}
+vdo_color_fmt govrh_mod_get_color_fmt(void)
+{
+	return govrh_get_color_format(p_govrh);
+}
+void govrh_mod_set_color_fmt(vdo_color_fmt colfmt)
+{
+	govrh_set_color_format(p_govrh, colfmt);
+}
+
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+void cursor_mod_set_enable(vpp_flag_t enable)
+{
+	govrh_CUR_set_enable(p_cursor, enable);
+}
+
+void cursor_mod_set_framebuf(vdo_framebuf_t *fb)
+{
+	govrh_CUR_set_framebuffer(p_cursor, fb);
+}
+
+void cursor_mod_set_addr(unsigned int yaddr, unsigned int caddr)
+{
+	govrh_CUR_set_fb_addr(p_cursor, yaddr, caddr);
+}
+
+void cursor_mod_get_addr(unsigned int *yaddr, unsigned int *caddr)
+{
+	govrh_CUR_get_fb_addr(p_cursor, yaddr, caddr);
+}
+
+void cursor_mod_fn_view(int read, vdo_view_t *view)
+{
+	govrh_CUR_proc_view(p_cursor, read, view);
+}
+#endif
+
+#ifdef WMT_FTBLK_GOVRH2
+void govrh2_mod_dump_reg(void)
+{
+	govrh_reg_dump((void *)p_govrh2);
+}
+
+void govrh2_mod_set_enable(vpp_flag_t enable)
+{
+	govrh_set_MIF_enable(p_govrh2, enable);
+}
+
+void govrh2_mod_set_colorbar(vpp_flag_t enable, int mode, int inv)
+{
+	govrh_set_colorbar(p_govrh2, enable, mode, inv);
+}
+
+void govrh2_mod_set_tg(vpp_clock_t *tmr, unsigned int pixel_clock)
+{
+	govrh_set_tg(p_govrh2, tmr, pixel_clock);
+}
+
+void govrh2_mod_get_tg(vpp_clock_t *tmr)
+{
+	govrh_get_tg(p_govrh2, tmr);
+}
+
+unsigned int govrh2_mod_get_sts(void)
+{
+	return govrh_get_int_status(p_govrh2);
+}
+
+void govrh2_mod_clr_sts(unsigned int sts)
+{
+	govrh_clean_int_status(p_govrh2, sts);
+}
+
+void govrh2_mod_suspend(int sts)
+{
+	govrh_suspend(p_govrh2, sts);
+}
+
+void govrh2_mod_resume(int sts)
+{
+	govrh_resume(p_govrh2, sts);
+}
+
+void govrh2_mod_set_framebuf(vdo_framebuf_t *fb)
+{
+	govrh_set_framebuffer(p_govrh2, fb);
+}
+void govrh2_mod_set_addr(unsigned int yaddr, unsigned int caddr)
+{
+	govrh_set_fb_addr(p_govrh2, yaddr, caddr);
+}
+void govrh2_mod_get_addr(unsigned int *yaddr, unsigned int *caddr)
+{
+	govrh_get_fb_addr(p_govrh2, yaddr, caddr);
+}
+void govrh2_mod_set_csc(vpp_csc_t mode)
+{
+	govrh_set_csc_mode(p_govrh2, mode);
+}
+vdo_color_fmt govrh2_mod_get_color_fmt(void)
+{
+	return govrh_get_color_format(p_govrh2);
+}
+void govrh2_mod_set_color_fmt(vdo_color_fmt colfmt)
+{
+	govrh_set_color_format(p_govrh2, colfmt);
+}
+
+#endif
+int govrh_mod_init(void)
+{
+	struct govrh_mod_t *mod_p;
+	struct vpp_fb_base_t *mod_fb_p;
+	vdo_framebuf_t *fb_p;
+
+	mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_GOVRH,
+				sizeof(struct govrh_mod_t),
+				VPP_MOD_FLAG_FRAMEBUF);
+	if (!mod_p) {
+		DPRINT("*E* GOVRH module register fail\n");
+		return -1;
+	}
+
+	/* module member variable */
+	mod_p->mmio = (void *)REG_GOVRH_BASE1_BEGIN;
+	mod_p->int_catch = VPP_INT_NULL; /* VPP_INT_ERR_GOVRH_MIF; */
+
+	/* module member function */
+	mod_p->init = govrh_init;
+	mod_p->dump_reg = govrh_mod_dump_reg;
+	mod_p->set_enable = govrh_mod_set_enable;
+	mod_p->set_colorbar = govrh_mod_set_colorbar;
+	mod_p->set_tg = govrh_mod_set_tg;
+	mod_p->get_tg = govrh_mod_get_tg;
+	mod_p->get_sts = govrh_mod_get_sts;
+	mod_p->clr_sts = govrh_mod_clr_sts;
+	mod_p->suspend = govrh_mod_suspend;
+	mod_p->resume = govrh_mod_resume;
+
+	/* module frame buffer */
+	mod_fb_p = mod_p->fb_p;
+	mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_JFIF_0_255;
+	mod_fb_p->framerate = VPP_HD_DISP_FPS;
+	mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG;
+	mod_fb_p->wait_ready = 0;
+	mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420)
+			| BIT(VDO_COL_FMT_YUV422H)
+			| BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB)
+			| BIT(VDO_COL_FMT_RGB_1555) | BIT(VDO_COL_FMT_RGB_565)
+			| VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA
+			| VPP_FB_FLAG_FIELD;
+
+	/* module frame buffer member function */
+	mod_fb_p->set_framebuf = govrh_mod_set_framebuf;
+	mod_fb_p->set_addr = govrh_mod_set_addr;
+	mod_fb_p->get_addr = govrh_mod_get_addr;
+	mod_fb_p->set_csc = govrh_mod_set_csc;
+	mod_fb_p->get_color_fmt = govrh_mod_get_color_fmt;
+	mod_fb_p->set_color_fmt = govrh_mod_set_color_fmt;
+
+	fb_p = &mod_p->fb_p->fb;
+	fb_p->y_addr = 0;
+	fb_p->c_addr = 0;
+	fb_p->col_fmt = VPP_UBOOT_COLFMT;
+	fb_p->img_w = VPP_HD_DISP_RESX;
+	fb_p->img_h = VPP_HD_DISP_RESY;
+	fb_p->fb_w = VPP_HD_MAX_RESX;
+	fb_p->fb_h = VPP_HD_MAX_RESY;
+	fb_p->h_crop = 0;
+	fb_p->v_crop = 0;
+	fb_p->flag = 0;
+
+	p_govrh = mod_p;
+
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+	mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_CURSOR,
+			sizeof(struct govrh_cursor_mod_t),
+			VPP_MOD_FLAG_FRAMEBUF);
+	if (!mod_p) {
+		DPRINT("*E* CURSOR module register fail\n");
+		return -1;
+	}
+
+	/* module member function */
+	mod_p->init = govrh_CUR_init;
+	mod_p->set_enable = cursor_mod_set_enable;
+	mod_p->mmio = (void *)REG_GOVRH_BASE1_BEGIN;
+
+	/* module frame buffer */
+	mod_fb_p = mod_p->fb_p;
+	mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255;
+	mod_fb_p->framerate = VPP_HD_DISP_FPS;
+	mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG;
+	mod_fb_p->wait_ready = 0;
+	mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420)
+			| BIT(VDO_COL_FMT_YUV422H)
+			| BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB)
+			| VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA
+			| VPP_FB_FLAG_FIELD;
+
+	/* module frame buffer member function */
+	mod_fb_p->set_framebuf = cursor_mod_set_framebuf;
+	mod_fb_p->set_addr = cursor_mod_set_addr;
+	mod_fb_p->get_addr = cursor_mod_get_addr;
+	mod_fb_p->fn_view = cursor_mod_fn_view;
+
+	fb_p = &mod_p->fb_p->fb;
+	fb_p->y_addr = 0;
+	fb_p->c_addr = 0;
+	fb_p->col_fmt = VDO_COL_FMT_YUV444;
+	fb_p->img_w = VPP_HD_DISP_RESX;
+	fb_p->img_h = VPP_HD_DISP_RESY;
+	fb_p->fb_w = VPP_HD_MAX_RESX;
+	fb_p->fb_h = VPP_HD_MAX_RESY;
+	fb_p->h_crop = 0;
+	fb_p->v_crop = 0;
+	fb_p->flag = 0;
+
+	p_cursor = (struct govrh_cursor_mod_t *) mod_p;
+#endif
+
+#ifdef WMT_FTBLK_GOVRH2
+	mod_p = (struct govrh_mod_t *) vpp_mod_register(VPP_MOD_GOVRH2,
+				sizeof(struct govrh_mod_t),
+				VPP_MOD_FLAG_FRAMEBUF);
+	if (!mod_p) {
+		DPRINT("*E* GOVRH module register fail\n");
+		return -1;
+	}
+
+	/* module member variable */
+	mod_p->mmio = (void *)REG_GOVRH2_BASE1_BEGIN;
+	mod_p->int_catch = VPP_INT_NULL; /* VPP_INT_ERR_GOVRH_MIF; */
+
+	/* module member function */
+	mod_p->init = govrh_init;
+	mod_p->dump_reg = govrh2_mod_dump_reg;
+	mod_p->set_enable = govrh2_mod_set_enable;
+	mod_p->set_colorbar = govrh2_mod_set_colorbar;
+	mod_p->set_tg = govrh2_mod_set_tg;
+	mod_p->get_tg = govrh2_mod_get_tg;
+	mod_p->get_sts = govrh2_mod_get_sts;
+	mod_p->clr_sts = govrh2_mod_clr_sts;
+	mod_p->suspend = govrh2_mod_suspend;
+	mod_p->resume = govrh2_mod_resume;
+
+	/* module frame buffer */
+	mod_fb_p = mod_p->fb_p;
+	mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_JFIF_0_255;
+	mod_fb_p->framerate = VPP_HD_DISP_FPS;
+	mod_fb_p->media_fmt = VPP_MEDIA_FMT_MPEG;
+	mod_fb_p->wait_ready = 0;
+	mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420)
+		| BIT(VDO_COL_FMT_YUV422H)
+		| BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB)
+		| BIT(VDO_COL_FMT_RGB_1555) | BIT(VDO_COL_FMT_RGB_565)
+		| VPP_FB_FLAG_CSC | VPP_FB_FLAG_MEDIA | VPP_FB_FLAG_FIELD;
+
+	/* module frame buffer member function */
+	mod_fb_p->set_framebuf = govrh2_mod_set_framebuf;
+	mod_fb_p->set_addr = govrh2_mod_set_addr;
+	mod_fb_p->get_addr = govrh2_mod_get_addr;
+	mod_fb_p->set_csc = govrh2_mod_set_csc;
+	mod_fb_p->get_color_fmt = govrh2_mod_get_color_fmt;
+	mod_fb_p->set_color_fmt = govrh2_mod_set_color_fmt;
+
+	fb_p = &mod_p->fb_p->fb;
+	fb_p->y_addr = 0;
+	fb_p->c_addr = 0;
+	fb_p->col_fmt = VPP_UBOOT_COLFMT;
+	fb_p->img_w = VPP_HD_DISP_RESX;
+	fb_p->img_h = VPP_HD_DISP_RESY;
+	fb_p->fb_w = VPP_HD_MAX_RESX;
+	fb_p->fb_h = VPP_HD_MAX_RESY;
+	fb_p->h_crop = 0;
+	fb_p->v_crop = 0;
+	fb_p->flag = 0;
+
+	p_govrh2 = mod_p;
+#endif
+	return 0;
+}
+module_init(govrh_mod_init);
+#endif /* WMT_FTBLK_GOVRH */
diff --git a/drivers/video/wmt/govrh.h b/drivers/video/wmt/govrh.h
new file mode 100755
index 00000000..a7dc0625
--- /dev/null
+++ b/drivers/video/wmt/govrh.h
@@ -0,0 +1,184 @@
+/*++
+ * linux/drivers/video/wmt/govrh.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp.h"
+
+#ifdef WMT_FTBLK_GOVRH
+
+#ifndef GOVRH_H
+#define GOVRH_H
+
+struct govrh_mod_t {
+	VPP_MOD_BASE;
+
+	unsigned int *reg_bk2;
+	unsigned int pm_enable;
+	unsigned int pm_tg;
+	unsigned int vo_clock;
+	unsigned int underrun_cnt;
+	unsigned int csc_mode_force;
+};
+
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+#define GOVRH_CURSOR_HIDE_TIME	15
+struct govrh_cursor_mod_t {
+	VPP_MOD_BASE;
+
+	unsigned int posx;
+	unsigned int posy;
+	unsigned int hotspot_x;
+	unsigned int hotspot_y;
+	int chg_flag;
+	vdo_color_fmt colfmt;
+	unsigned int cursor_addr1;
+	unsigned int cursor_addr2;
+	int enable;
+	int hide_cnt;
+};
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef GOVRH_C
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+EXTERN struct govrh_mod_t *p_govrh;
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+EXTERN struct govrh_cursor_mod_t *p_cursor;
+#endif
+#ifdef WMT_FTBLK_GOVRH2
+EXTERN struct govrh_mod_t *p_govrh2;
+#endif
+
+EXTERN void govrh_set_tg_enable(struct govrh_mod_t *base,
+					vpp_flag_t enable);
+EXTERN int govrh_get_tg_mode(struct govrh_mod_t *base);
+EXTERN int govrh_get_hscale_up(struct govrh_mod_t *base);
+EXTERN void govrh_set_direct_path(struct govrh_mod_t *base, int enable);
+EXTERN int govrh_get_dvo_enable(struct govrh_mod_t *base);
+EXTERN void govrh_set_dvo_enable(struct govrh_mod_t *base,
+	vpp_flag_t enable);
+EXTERN void govrh_set_dvo_sync_polar(struct govrh_mod_t *base,
+	vpp_flag_t hsync, vpp_flag_t vsync);
+EXTERN void govrh_set_dvo_outdatw(struct govrh_mod_t *base,
+	vpp_datawidht_t width);
+EXTERN void govrh_set_dvo_clock_delay(struct govrh_mod_t *base,
+	int inverse, int delay);
+EXTERN void govrh_set_colorbar(struct govrh_mod_t *base,
+	vpp_flag_t enable, int mode, int inv);
+EXTERN void govrh_set_contrast(struct govrh_mod_t *base,
+	unsigned int value);
+EXTERN unsigned int govrh_get_contrast(struct govrh_mod_t *base);
+EXTERN void govrh_set_brightness(struct govrh_mod_t *base,
+	unsigned int value);
+EXTERN unsigned int govrh_get_brightness(struct govrh_mod_t *base);
+EXTERN void govrh_set_saturation(struct govrh_mod_t *base, unsigned int value);
+EXTERN unsigned int govrh_get_saturation(struct govrh_mod_t *base);
+EXTERN void govrh_set_MIF_enable(struct govrh_mod_t *base, vpp_flag_t enable);
+EXTERN int govrh_get_MIF_enable(struct govrh_mod_t *base);
+EXTERN void govrh_set_color_format(struct govrh_mod_t *base,
+	vdo_color_fmt format);
+EXTERN vdo_color_fmt govrh_get_color_format(struct govrh_mod_t *base);
+EXTERN void govrh_set_source_format(struct govrh_mod_t *base,
+	vpp_display_format_t format);
+EXTERN void govrh_set_output_format(struct govrh_mod_t *base,
+	vpp_display_format_t field);
+EXTERN void govrh_set_fb_addr(struct govrh_mod_t *base,
+	unsigned int y_addr, unsigned int c_addr);
+EXTERN void govrh_get_fb_addr(struct govrh_mod_t *base,
+	unsigned int *y_addr, unsigned int *c_addr);
+EXTERN void govrh_set_fb_width(struct govrh_mod_t *base,
+	unsigned int width);
+EXTERN void govrh_set_fb_info(struct govrh_mod_t *base,
+	unsigned int width, unsigned int act_width,
+	unsigned int x_offset, unsigned int y_offset);
+EXTERN void govrh_get_fb_info(struct govrh_mod_t *base,
+	unsigned int *width, unsigned int *act_width,
+	unsigned int *x_offset, unsigned int *y_offset);
+EXTERN void govrh_set_fifo_index(struct govrh_mod_t *base,
+	unsigned int index);
+EXTERN void govrh_set_reg_level(struct govrh_mod_t *base,
+	vpp_reglevel_t level);
+EXTERN void govrh_set_reg_update(struct govrh_mod_t *base,
+	vpp_flag_t enable);
+EXTERN void govrh_set_csc_mode(struct govrh_mod_t *base,
+	vpp_csc_t mode);
+EXTERN void govrh_set_framebuffer(struct govrh_mod_t *base,
+	vdo_framebuf_t *inbuf);
+EXTERN void govrh_get_framebuffer(struct govrh_mod_t *base,
+	vdo_framebuf_t *fb);
+EXTERN vdo_color_fmt govrh_get_dvo_color_format(
+	struct govrh_mod_t *base);
+EXTERN void govrh_set_dvo_color_format(struct govrh_mod_t *base,
+	vdo_color_fmt fmt);
+EXTERN enum vpp_int_err_t govrh_get_int_status(struct govrh_mod_t *base);
+EXTERN void govrh_clean_int_status(struct govrh_mod_t *base,
+	enum vpp_int_err_t int_sts);
+EXTERN unsigned int govrh_set_clock(struct govrh_mod_t *base,
+	unsigned int pixel_clock);
+EXTERN void govrh_set_videomode(struct govrh_mod_t *base,
+	struct fb_videomode *vmode);
+EXTERN void govrh_get_tg(struct govrh_mod_t *base, vpp_clock_t *tmr);
+EXTERN void govrh_get_videomode(struct govrh_mod_t *base,
+	struct fb_videomode *vmode);
+EXTERN void govrh_HDMI_set_blank_value(struct govrh_mod_t *base,
+	unsigned int val);
+EXTERN void govrh_HDMI_set_3D_mode(struct govrh_mod_t *base,
+	int mode);
+EXTERN int govrh_is_top_field(struct govrh_mod_t *base);
+EXTERN void govrh_IGS_set_mode(struct govrh_mod_t *base,
+	int no, int mode_18bit, int msb);
+EXTERN void govrh_IGS_set_RGB_swap(struct govrh_mod_t *base,
+	int mode);
+EXTERN int govrh_mod_init(void);
+
+#ifdef WMT_FTBLK_GOVRH_CURSOR
+EXTERN void govrh_CUR_set_enable(struct govrh_cursor_mod_t *base,
+	vpp_flag_t enable);
+EXTERN void govrh_CUR_set_framebuffer(struct govrh_cursor_mod_t *base,
+	vdo_framebuf_t *fb);
+EXTERN void govrh_CUR_set_coordinate(struct govrh_cursor_mod_t *base,
+	unsigned int x1, unsigned int y1, unsigned int x2, unsigned int y2);
+EXTERN void govrh_CUR_set_position(struct govrh_cursor_mod_t *base,
+	unsigned int x, unsigned int y);
+EXTERN void govrh_CUR_set_color_key_mode(struct govrh_cursor_mod_t *base,
+	int alpha, int enable, int mode);
+EXTERN void govrh_CUR_set_color_key(struct govrh_cursor_mod_t *base,
+	int enable, int alpha, unsigned int colkey);
+EXTERN void govrh_CUR_set_colfmt(struct govrh_cursor_mod_t *base,
+	vdo_color_fmt colfmt);
+EXTERN void govrh_CUR_irqproc(int arg);
+#endif
+
+#undef EXTERN
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* GOVRH_H */
+#endif /* WMT_FTBLK_GOVRH */
diff --git a/drivers/video/wmt/hdmi.c b/drivers/video/wmt/hdmi.c
new file mode 100755
index 00000000..c181d757
--- /dev/null
+++ b/drivers/video/wmt/hdmi.c
@@ -0,0 +1,1457 @@
+/*++
+ * linux/drivers/video/wmt/hdmi.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define HDMI_C
+#undef DEBUG
+/* #define DEBUG */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "hdmi.h"
+#include "vout.h"
+#ifdef __KERNEL__
+#include <asm/div64.h>
+#endif
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define HDMI_XXXX    1     *//*Example*/
+/* #define CONFIG_HDMI_INFOFRAME_DISABLE */
+/* #define CONFIG_HDMI_EDID_DISABLE */
+
+#define HDMI_I2C_FREQ	80000
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx hdmi_xxx_t; *//*Example*/
+enum hdmi_fifo_slot_t {
+	HDMI_FIFO_SLOT_AVI = 0,
+	HDMI_FIFO_SLOT_VENDOR = 1,
+	HDMI_FIFO_SLOT_AUDIO = 2,
+	HDMI_FIFO_SLOT_CONTROL = 3,
+	HDMI_FIFO_SLOT_MAX = 15
+};
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in hdmi.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  hdmi_xxx;        *//*Example*/
+
+HW_REG struct hdmi_base1_regs *hdmi_regs1 = (void *) (HDMI_BASE_ADDR + 0x100);
+HW_REG struct hdmi_base2_regs *hdmi_regs2 = (void *) HDMI_BASE2_ADDR;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void hdmi_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+/*---------------------------- HDMI COMMON API -------------------------------*/
+unsigned char hdmi_ecc(unsigned char *buf, int bit_cnt)
+{
+	#define HDMI_CRC_LEN	9
+
+	int crc[HDMI_CRC_LEN], crc_o[HDMI_CRC_LEN];
+	int i, j;
+	int input, result, result_rev = 0;
+
+	for (i = 0; i < HDMI_CRC_LEN; i++)
+		crc[i] = 0;
+
+	for (i = 0; i < bit_cnt; i++) {
+		for (j = 0; j < HDMI_CRC_LEN; j++)
+			crc_o[j] = crc[j];
+		input = (buf[i/8] & (1<<(i%8))) ? 1 : 0;
+		crc[0] = crc_o[7] ^ input;
+		crc[1] = crc_o[0];
+		crc[2] = crc_o[1];
+		crc[3] = crc_o[2];
+		crc[4] = crc_o[3];
+		crc[5] = crc_o[4];
+		crc[6] = crc_o[5] ^ crc_o[7] ^ input;
+		crc[7] = crc_o[6] ^ crc_o[7] ^ input;
+		crc[8] = crc_o[7];
+
+		result     = 0;
+		result_rev = 0;
+		for (j = 0; j < HDMI_CRC_LEN - 1; j++) {
+			result     += (crc[j] << j);
+			result_rev += (crc[j] << (HDMI_CRC_LEN - 2 - j));
+		}
+	}
+
+/*	DPRINT("[HDMI] crc 0x%x, %x %x %x %x %x %x %x\n",result_rev,
+			buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6]); */
+	return result_rev;
+}
+
+unsigned char hdmi_checksum(unsigned char *header,
+					unsigned char *buf, int cnt)
+{
+	unsigned char sum;
+	int i;
+
+	for (i = 0, sum = 0; i < cnt; i++)
+		sum += buf[i];
+	for (i = 0; i < 3; i++)
+		sum += header[i];
+	return 0 - sum;
+}
+
+#ifdef WMT_FTBLK_HDMI
+/*---------------------------- HDMI HAL --------------------------------------*/
+void hdmi_set_power_down(int pwrdn)
+{
+	DBG_DETAIL("(%d)\n", pwrdn);
+
+	if ((hdmi_regs2->test.b.pd == 0) && (pwrdn == 0))
+		return; /* avoid HDMI reset */
+
+	hdmi_regs2->status.b.internal_ldo = (pwrdn) ? 0 : 1;
+	hdmi_regs2->test.b.pd = pwrdn;
+	if (!pwrdn) {
+		hdmi_regs2->dftset2.b.reset_pll = 1;
+		mdelay(1);
+		hdmi_regs2->dftset2.b.reset_pll = 0;
+	}
+	mdelay(1);
+	hdmi_regs2->test2.b.pd_l2ha = pwrdn;
+}
+
+int hdmi_get_power_down(void)
+{
+	return hdmi_regs2->test.b.pd;
+}
+
+void hdmi_set_enable(vpp_flag_t enable)
+{
+	hdmi_regs1->general_ctrl.b.enable = enable;
+	hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */
+	hdmi_regs2->test2.b.mode = (enable) ? 0 : 1;
+}
+
+void hdmi_set_avmute(vpp_flag_t mute)
+{
+	hdmi_regs1->aud_insert_ctrl.b.avmute_set_enable = mute;
+}
+
+void hdmi_set_dvi_enable(vpp_flag_t enable)
+{
+	hdmi_regs1->general_ctrl.b.dvi_mode_enable = enable;
+	hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */
+}
+
+void hdmi_set_sync_low_active(vpp_flag_t hsync, vpp_flag_t vsync)
+{
+	hdmi_regs1->general_ctrl.b.hsync_low_active = hsync;
+	hdmi_regs1->general_ctrl.b.vsync_low_active = vsync;
+	hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */
+}
+
+void hdmi_get_sync_polar(int *hsync_hi, int *vsync_hi)
+{
+	*hsync_hi = (hdmi_regs1->general_ctrl.b.hsync_low_active) ? 0 : 1;
+	*vsync_hi = (hdmi_regs1->general_ctrl.b.vsync_low_active) ? 0 : 1;
+}
+
+void hdmi_set_output_colfmt(vdo_color_fmt colfmt)
+{
+	unsigned int val;
+
+	switch (colfmt) {
+	default:
+	case VDO_COL_FMT_ARGB:
+		val = 0;
+		break;
+	case VDO_COL_FMT_YUV444:
+		val = 1;
+		break;
+	case VDO_COL_FMT_YUV422H:
+	case VDO_COL_FMT_YUV422V:
+		val = 2;
+		break;
+	}
+	hdmi_regs1->general_ctrl.b.convert_yuv422 = (val == 2) ? 1 : 0;
+	hdmi_regs1->general_ctrl.b.output_format = val;
+	hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */
+}
+
+vdo_color_fmt hdmi_get_output_colfmt(void)
+{
+	unsigned int val;
+
+	val = hdmi_regs1->general_ctrl.b.output_format;
+	switch (val) {
+	default:
+	case 0:
+		return VDO_COL_FMT_ARGB;
+	case 1:
+		return VDO_COL_FMT_YUV444;
+	case 2:
+		return VDO_COL_FMT_YUV422H;
+	}
+	return VDO_COL_FMT_ARGB;
+}
+
+int hdmi_get_plugin(void)
+{
+	int plugin;
+
+	if (hdmi_regs1->hotplug_detect.b.in_enable) {
+		plugin = hdmi_regs1->hotplug_detect.b.sts;
+	} else {
+		int tre_en;
+
+		tre_en = hdmi_regs2->test.b.tre_en;
+		hdmi_regs2->test.b.tre_en = 0;
+		plugin = hdmi_regs2->detect.b.rsen;
+		hdmi_regs2->test.b.tre_en = tre_en;
+	}
+	return plugin;
+}
+
+int hdmi_get_plug_status(void)
+{
+	int reg;
+
+	reg = hdmi_regs1->hotplug_detect.val;
+	return reg & 0x3000000;
+}
+
+void hdmi_clear_plug_status(void)
+{
+	hdmi_regs1->hotplug_detect.b.in_sts = 1;
+	hdmi_regs1->hotplug_detect.b.out_sts = 1;
+}
+
+void hdmi_enable_plugin(int enable)
+{
+	hdmi_regs1->hotplug_detect.b.out_enable = enable;
+	hdmi_regs1->hotplug_detect.b.in_enable = enable;
+}
+
+void hdmi_write_fifo(enum hdmi_fifo_slot_t no, unsigned int *buf, int cnt)
+{
+	int i;
+
+	if (no > HDMI_FIFO_SLOT_MAX)
+		return;
+#ifdef DEBUG
+{
+	char *ptr;
+
+	DPRINT("[HDMI] wr fifo %d,cnt %d", no, cnt);
+	ptr = (char *) buf;
+	for (i = 0; i < cnt; i++) {
+		if ((i % 4) == 0)
+			DPRINT("\n %02d :", i);
+		DPRINT(" 0x%02x", ptr[i]);
+	}
+	DPRINT("\n[HDMI] AVI info package end\n");
+}
+#endif
+	hdmi_regs1->fifo_ctrl.val = (no << 8);
+	cnt = (cnt + 3) / 4;
+	for (i = 0; i < cnt; i++)
+		hdmi_regs1->wr_fifo_addr[i] = buf[i];
+	hdmi_regs1->fifo_ctrl.b.wr_strobe = 1;
+}
+
+void hdmi_read_fifo(enum hdmi_fifo_slot_t no, unsigned int *buf, int cnt)
+{
+	int i;
+	int rdy;
+
+	if (no > HDMI_FIFO_SLOT_MAX)
+		return;
+
+	rdy = hdmi_regs1->infoframe_ctrl.b.fifo1_rdy;
+	hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0;
+
+	no = no - 1;
+	hdmi_regs1->fifo_ctrl.val = (no << 8);
+	hdmi_regs1->fifo_ctrl.b.rd_strobe = 1;
+	cnt = (cnt + 3) / 4;
+	for (i = 0; i < cnt; i++)
+		buf[i] = hdmi_regs1->rd_fifo_addr[i];
+	hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = rdy;
+#ifdef DEBUG
+{
+	char *ptr;
+
+	cnt *= 4;
+	DPRINT("[HDMI] rd fifo %d,cnt %d", no, cnt);
+	ptr = (char *) buf;
+	for (i = 0; i < cnt; i++) {
+		if ((i % 4) == 0)
+			DPRINT("\n %02d :", i);
+		DPRINT(" 0x%02x", ptr[i]);
+	}
+	DPRINT("\n[HDMI] AVI info package end\n");
+}
+#endif
+}
+
+#if 1
+int hdmi_ddc_delay_us = 5;
+int hdmi_ddc_ctrl_delay_us = 5;
+
+#define HDMI_DDC_OUT
+#define HDMI_DDC_DELAY		hdmi_ddc_delay_us
+#define HDMI_DDC_CHK_DELAY	1
+#define HDMI_DDC_CTRL_DELAY	hdmi_ddc_ctrl_delay_us
+#else
+#define HDMI_DDC_OUT
+#define HDMI_DDC_DELAY		1
+#define HDMI_DDC_CHK_DELAY	1
+#define HDMI_DDC_CTRL_DELAY	1
+#endif
+
+#define HDMI_STATUS_START	BIT16
+#define HDMI_STATUS_STOP	BIT17
+#define HDMI_STATUS_WR_AVAIL	BIT18
+#define HDMI_STATUS_CP_USE	BIT19
+#define HDMI_STATUS_SW_READ	BIT25
+int hdmi_DDC_check_status(unsigned int checkbits, int condition)
+{
+	int status = 1;
+	unsigned int i = 0, maxloop;
+
+	maxloop = 500 / HDMI_DDC_CHK_DELAY;
+	udelay(HDMI_DDC_DELAY);
+
+	if (condition) { /* wait 1 --> 0 */
+		while ((hdmi_regs1->i2c_ctrl2.val & checkbits)
+			&& (i < maxloop)) {
+			udelay(HDMI_DDC_CHK_DELAY);
+			if (++i == maxloop)
+				status = 0;
+		}
+	} else { /* wait 0 --> 1 */
+		while (!(hdmi_regs1->i2c_ctrl2.val & checkbits)
+			&& (i < maxloop)) {
+			udelay(HDMI_DDC_CHK_DELAY);
+			if (++i == maxloop)
+				status = 0;
+		}
+	}
+
+	if ((status == 0) && (checkbits != HDMI_STATUS_SW_READ)) {
+		unsigned int reg;
+
+		reg = hdmi_regs1->i2c_ctrl2.val;
+		DBG_DETAIL("[HDMI] status timeout check 0x%x,wait to %s\n",
+			checkbits, (condition) ? "0" : "1");
+		DBG_DETAIL("[HDMI] 0x%x,sta %d,stop %d,wr %d,rd %d,cp %d\n",
+			reg, (reg & HDMI_STATUS_START) ? 1 : 0,
+			(reg & HDMI_STATUS_STOP) ? 1 : 0,
+			(reg & HDMI_STATUS_WR_AVAIL) ? 1 : 0,
+			(reg & HDMI_STATUS_SW_READ) ? 1 : 0,
+			(reg & HDMI_STATUS_CP_USE) ? 1 : 0);
+	}
+	return status;
+}
+
+void hdmi_DDC_set_freq(unsigned int hz)
+{
+	unsigned int clock;
+	unsigned int div;
+
+	clock = 25000000*15/100;	/* RTC clock source */
+	div = clock / hz;
+
+	hdmi_regs1->i2c_ctrl.b.i2c_clk_divider = div;
+	DBG_DETAIL("[HDMI] set freq(%d,clk %d,div %d)\n", hz, clock, div);
+}
+
+void hdmi_DDC_reset(void)
+{
+	hdmi_regs1->i2c_ctrl.b.i2c_sw_reset = 1;
+	udelay(1);
+	hdmi_regs1->i2c_ctrl.b.i2c_sw_reset = 0;
+}
+
+int hdmi_DDC_read_func(char addr, int index, char *buf, int length)
+{
+	int status = 1;
+	unsigned int i = 0;
+	int err_cnt = 0;
+
+	DBG_DETAIL("[HDMI] read DDC(index 0x%x,len %d),reg 0x%x\n",
+		index, length, hdmi_regs1->i2c_ctrl2.val);
+
+#ifdef CONFIG_HDMI_EDID_DISABLE
+	return status;
+#endif
+
+	hdmi_DDC_set_freq(g_vpp.hdmi_i2c_freq);
+	/* enhanced DDC read */
+	if (index >= 256) {
+		/* sw start, write data avail */
+		vppif_reg32_write((unsigned int) &hdmi_regs1->i2c_ctrl2,
+					BIT18 + BIT16, 16, 0x5);
+		udelay(HDMI_DDC_CTRL_DELAY);
+		/* wait start & wr data avail */
+		status = hdmi_DDC_check_status(HDMI_STATUS_START +
+					HDMI_STATUS_WR_AVAIL, 1);
+		if (status == 0) {
+			DBGMSG("[HDMI] *E* start\n");
+			err_cnt++;
+			goto ddc_read_fail;
+		}
+
+		/* Slave address */
+		hdmi_regs1->i2c_ctrl2.b.wr_data = 0x60;
+		hdmi_regs1->i2c_ctrl2.b.wr_data_avail = 1;
+		udelay(HDMI_DDC_CTRL_DELAY);
+		/* wait wr data avail */
+		status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+		if (status == 0) {
+			DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr);
+			err_cnt++;
+			goto ddc_read_fail;
+		}
+
+		/* Offset */
+		hdmi_regs1->i2c_ctrl2.b.wr_data = 0x1;
+		hdmi_regs1->i2c_ctrl2.b.wr_data_avail = 1;
+		udelay(HDMI_DDC_CTRL_DELAY);
+		/* wait wr data avail */
+		status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+		if (status == 0) {
+			DBGMSG("[HDMI] *E* index 0x%x\n", index);
+			err_cnt++;
+			goto ddc_read_fail;
+		}
+		index -= 256;
+	}
+
+	/* START */
+	hdmi_regs1->i2c_ctrl2.val = 0x50000; /* start & data avail */
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait start & wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_START +
+					HDMI_STATUS_WR_AVAIL, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* start\n");
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+
+	/* Slave address */
+	hdmi_regs1->i2c_ctrl2.val = 0x400A0; /* addr & data avail */
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr);
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+
+	/* Offset */
+	hdmi_regs1->i2c_ctrl2.val = (0x40000 + index); /* index & data avail */
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* index 0x%x\n", index);
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+
+	/* START */
+	hdmi_regs1->i2c_ctrl2.val = 0x50000; /* start & data avail */
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait start & wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_START +
+					HDMI_STATUS_WR_AVAIL, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* restart\n");
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+
+	/* Slave Address + 1 */
+	hdmi_regs1->i2c_ctrl2.val = 0x400A1; /* addr(rd) & data avail */
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* slave addr 0x%x\n", addr + 1);
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+
+	/* Read Data */
+	for (i = 0; i < length; i++) {
+		hdmi_regs1->i2c_ctrl2.val = 0x40000; /* data avail */
+		udelay(HDMI_DDC_CTRL_DELAY);
+		/* wait wr data avail */
+		status = hdmi_DDC_check_status(HDMI_STATUS_WR_AVAIL, 1);
+		if (status == 0) {
+			DBGMSG("[HDMI] *E* wr ACK(%d)\n", i);
+			err_cnt++;
+			goto ddc_read_fail;
+			/* break; */
+		}
+
+		/* wait sw read not set */
+		status = hdmi_DDC_check_status(HDMI_STATUS_SW_READ, 0);
+		if (status == 0) {
+			DBGMSG("[HDMI] *E* read avail(%d)\n", i);
+			if (i == 0) {
+				err_cnt++;
+				/* goto ddc_read_fail; */
+			} else {
+				/* g_vpp.dbg_hdmi_ddc_read_err++; */
+			}
+			goto ddc_read_fail;
+			/* break; */
+		}
+
+		*buf++ = hdmi_regs1->i2c_ctrl2.b.rd_data;
+		udelay(HDMI_DDC_DELAY);
+		hdmi_regs1->i2c_ctrl2.val = 0x2000000; /* clr sw read */
+		udelay(HDMI_DDC_DELAY);
+	}
+
+	/* STOP */
+	/* sw stop, write data avail */
+	vppif_reg32_write((unsigned int) &hdmi_regs1->i2c_ctrl2.val,
+					BIT18 + BIT17, 17, 3);
+	udelay(HDMI_DDC_CTRL_DELAY);
+	/* wait start & wr data avail */
+	status = hdmi_DDC_check_status(HDMI_STATUS_STOP +
+				HDMI_STATUS_WR_AVAIL + HDMI_STATUS_CP_USE, 1);
+	if (status == 0) {
+		DBGMSG("[HDMI] *E* stop\n");
+		err_cnt++;
+		goto ddc_read_fail;
+	}
+	udelay(HDMI_DDC_DELAY);
+
+ddc_read_fail:
+	if (err_cnt)
+		DBGMSG("[HDMI] *E* read DDC %d\n", err_cnt);
+	return (err_cnt) ? 1 : 0;
+}
+
+int hdmi_DDC_read(char addr, int index, char *buf, int length)
+{
+	int retry = 3;
+	int ret;
+
+	DBG_MSG("(0x%x,0x%x,%d)\n", addr, index, length);
+
+	do {
+		ret = hdmi_DDC_read_func(addr, index, buf, length);
+		if (ret == 0)
+			break;
+		hdmi_DDC_reset();
+		DPRINT("[HDMI] *W* DDC reset %d\n", ret);
+		retry--;
+	} while (retry);
+
+	return (retry == 0) ? 1 : 0;
+}
+
+void hdmi_audio_enable(vpp_flag_t enable)
+{
+	if (hdmi_regs1->aud_enable != enable) {
+		if (!enable) {
+#ifdef CONFIG_KERNEL
+			msleep(5);
+#endif
+			if (g_vpp.hdmi_ch_change)
+				REG32_VAL(I2S_BASE_ADDR + 0x188) = 0;
+		}
+		hdmi_regs1->aud_enable = (enable) ? 1 : 0;
+	}
+}
+
+void hdmi_audio_mute(vpp_flag_t enable)
+{
+	hdmi_regs1->aud_ratio.b.mute = enable;
+}
+
+/*----------------------- HDMI API --------------------------------------*/
+void hdmi_write_packet(unsigned int header, unsigned char *packet,
+				int cnt)
+{
+	unsigned char buf[36];
+	int i;
+	enum hdmi_fifo_slot_t no;
+
+#ifdef CONFIG_HDMI_INFOFRAME_DISABLE
+	return;
+#endif
+	memcpy(&buf[0], &header, 3);
+	buf[3] = hdmi_ecc((unsigned char *)&header, 24);
+	for (i = 0; i < cnt / 7; i++) {
+		memcpy(&buf[4+8*i], &packet[7*i], 7);
+		buf[11+8*i] = hdmi_ecc(&packet[7*i], 56);
+	}
+
+	switch (header & 0xFF) {
+	case HDMI_PACKET_INFOFRAME_AVI:
+		no = HDMI_FIFO_SLOT_AVI;
+		break;
+	case HDMI_PACKET_INFOFRAME_AUDIO:
+		no = HDMI_FIFO_SLOT_AUDIO;
+		break;
+	case HDMI_PACKET_INFOFRAME_VENDOR:
+		no = HDMI_FIFO_SLOT_VENDOR;
+		break;
+	default:
+		no = HDMI_FIFO_SLOT_CONTROL;
+		break;
+	}
+	hdmi_write_fifo(no, (unsigned int *)buf, (4 + 8 * (cnt / 7)));
+}
+
+void hdmi_tx_null_packet(void)
+{
+	hdmi_write_packet(HDMI_PACKET_NULL, 0, 0);
+}
+
+void hdmi_tx_general_control_packet(int mute)
+{
+	unsigned char buf[7];
+	memset(buf, 0x0, 7);
+	buf[0] = (mute) ? 0x01 : 0x10;
+	buf[1] = HDMI_COLOR_DEPTH_24 | (HDMI_PHASE_4 << 4);
+	hdmi_write_packet(HDMI_PACKET_GENERAL_CTRL, buf, 7);
+}
+
+int hdmi_get_pic_aspect(enum hdmi_video_code_t vic)
+{
+	switch (vic) {
+	case HDMI_640x480p60_4x3:
+	case HDMI_720x480p60_4x3:
+	case HDMI_1440x480i60_4x3:
+	case HDMI_1440x240p60_4x3:
+	case HDMI_2880x480i60_4x3:
+	case HDMI_2880x240p60_4x3:
+	case HDMI_1440x480p60_4x3:
+	case HDMI_720x576p50_4x3:
+	case HDMI_1440x576i50_4x3:
+	case HDMI_1440x288p50_4x3:
+	case HDMI_2880x576i50_4x3:
+	case HDMI_2880x288p50_4x3:
+	case HDMI_1440x576p50_4x3:
+		return HDMI_PIC_ASPECT_4_3;
+	default:
+		break;
+	}
+	return HDMI_PIC_ASPECT_16_9;
+}
+
+int hdmi_get_vic(int resx, int resy, int fps, int interlace)
+{
+	struct hdmi_vic_t info;
+	int i;
+
+	info.resx = resx;
+	info.resy = resy;
+	info.freq = fps;
+	info.option = (interlace) ? HDMI_VIC_INTERLACE : HDMI_VIC_PROGRESS;
+	info.option |= (vout_check_ratio_16_9(resx, resy)) ?
+				HDMI_VIC_16x9 : HDMI_VIC_4x3;
+	for (i = 0; i < HDMI_VIDEO_CODE_MAX; i++) {
+		if (memcmp(&hdmi_vic_info[i], &info,
+			sizeof(struct hdmi_vic_t)) == 0)
+			return i;
+	}
+	return HDMI_UNKNOW;
+}
+
+void hdmi_tx_avi_infoframe_packet(vdo_color_fmt colfmt,
+						enum hdmi_video_code_t vic)
+{
+	unsigned int header;
+	unsigned char buf[28];
+	unsigned char temp;
+
+	memset(buf, 0x0, 28);
+	header = HDMI_PACKET_INFOFRAME_AVI + (0x2 << 8) + (0x0d << 16);
+	buf[1] = HDMI_SI_NO_DATA + (HDMI_BI_V_H_VALID << 2) +
+				(HDMI_AF_INFO_NO_DATA << 4);
+	switch (colfmt) {
+	case VDO_COL_FMT_YUV422H:
+	case VDO_COL_FMT_YUV422V:
+		temp = HDMI_OUTPUT_YUV422;
+		break;
+	case VDO_COL_FMT_YUV444:
+		temp = HDMI_OUTPUT_YUV444;
+		break;
+	case VDO_COL_FMT_ARGB:
+	default:
+		temp = HDMI_OUTPUT_RGB;
+		break;
+	}
+	buf[1] += (temp << 5);
+	buf[2] = HDMI_ASPECT_RATIO_PIC + (hdmi_get_pic_aspect(vic) << 4) +
+		(HDMI_COLORIMETRY_ITU709 << 6);
+	buf[3] = 0x84;
+	buf[4] = vic;
+	switch (vic) {
+	case HDMI_1440x480i60_16x9:
+	case HDMI_1440x576i50_16x9:
+		buf[5] = HDMI_PIXEL_REP_2;
+		break;
+	default:
+		buf[5] = HDMI_PIXEL_REP_NO;
+		break;
+	}
+	buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28);
+	hdmi_write_packet(header, buf, 28);
+}
+
+void hdmi_tx_audio_infoframe_packet(int channel, int freq)
+{
+	unsigned int header;
+	unsigned char buf[28];
+
+	memset(buf, 0x0, 28);
+	header = HDMI_PACKET_INFOFRAME_AUDIO + (0x1 << 8) + (0x0a << 16);
+	buf[1] = (channel - 1) + (HDMI_AUD_TYPE_REF_STM << 4);
+	buf[2] = 0x0; /* HDMI_AUD_SAMPLE_24 + (freq << 2); */
+	buf[3] = 0x00;
+	/* 0x13: RRC RLC RR RL FC LFE FR FL
+	    0x1F: FRC FLC RR RL FC LFE FR FL */
+	buf[4] = (channel == 8) ? 0x13 : 0;
+	buf[5] = 0x0; /* 0 db */
+	buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28);
+	hdmi_write_packet(header, buf, 28);
+}
+
+void hdmi_tx_vendor_specific_infoframe_packet(void)
+{
+	unsigned int header;
+	unsigned char buf[28];
+	unsigned char structure_3d, meta_present;
+	unsigned char hdmi_video_format;
+
+	/* 0-No,1-1 byte param,2-3D format */
+	hdmi_video_format = (g_vpp.hdmi_3d_type) ? 2 : 0;
+	/* HDMI_3D_STRUCTURE_XXX; */
+	structure_3d = (g_vpp.hdmi_3d_type == 1) ? 0 : g_vpp.hdmi_3d_type;
+	meta_present = 0;
+
+	memset(buf, 0x0, 28);
+	header = HDMI_PACKET_INFOFRAME_VENDOR + (0x1 << 8) + (0xa << 16);
+	buf[1] = 0x3;
+	buf[2] = 0xC;
+	buf[3] = 0x0;
+	buf[4] = (hdmi_video_format << 5);
+	buf[5] = (structure_3d << 4) + ((meta_present) ? 0x8 : 0x0);
+	buf[6] = 0x0;	/* 3D_Ext_Data */
+#if 0	/* metadata present */
+	buf[7] = 0x0;	/* 3D_Metadata_type,3D_Metadata_Length(N) */
+	buf[8] = 0x0;	/* 3D Metadata 1_N */
+#endif
+	buf[0] = hdmi_checksum((unsigned char *)&header, buf, 28);
+	hdmi_write_packet(header, buf, 28);
+}
+
+#define HDMI_N_CTS_USE_TABLE
+#ifdef HDMI_N_CTS_USE_TABLE
+struct hdmi_n_cts_s {
+	unsigned int n;
+	unsigned int cts;
+};
+
+struct hdmi_n_cts_s hdmi_n_cts_table[7][11] = {
+	/* 32kHz */
+	{{ 9152, 84375 }, {4096, 37800}, {4096, 40500}, {8192, 81081},
+	{ 4096, 81000 }, {4096, 81081}, {11648, 316406}, {4096, 111375},
+	{ 11648, 632812}, {4096, 222750}, {4096, 0}},
+	/* 44.1kHz */
+	{{7007, 46875}, {6272, 42000}, {6272, 45000}, {6272, 45045},
+	{6272, 90000}, {6272, 90090}, {17836, 351562}, {6272, 123750},
+	{17836, 703125}, {6272, 247500}, {6272, 0}},
+	/* 88.2kHz */
+	{{14014, 46875}, {12544, 42000}, {12544, 45000}, {12544, 45045},
+	{12544, 90000}, {12544, 90090}, {35672, 351562}, {12544, 123750},
+	{35672, 703125}, {12544, 247500}, {12544, 0}},
+	/* 176.4kHz */
+	{{28028, 46875}, {25088, 42000}, {25088, 45000}, {25088, 45045},
+	{25088, 90000}, {25088, 90090}, {71344, 351562}, {25088, 123750},
+	{71344, 703125}, {25088, 247500}, {25088, 0}},
+	/* 48kHz */
+	{{9152, 56250}, {6144, 37800}, {6144, 40500}, {8192, 54054},
+	{6144, 81000}, {6144, 81081}, {11648, 210937}, {6144, 111375},
+	{11648, 421875}, {6144, 222750}, {6144, 0}},
+	/* 96kHz */
+	{{18304, 56250}, {12288, 37800}, {12288, 40500}, {16384, 54054},
+	{12288, 81000}, {12288,81081}, {23296, 210937}, {12288, 111375},
+	{23296, 421875}, {12288, 222750}, {12288, 0}},
+	/* 192kHz */
+	{{36608, 56250}, {24576, 37800}, {24576, 40500}, {32768, 54054},
+	{24576, 81000}, {24576, 81081}, {46592, 210937}, {24576, 111375},
+	{46592, 421875}, {24576, 222750}, {24576, 0}}
+};
+
+struct hdmi_n_cts_s *hdmi_get_n_cts(unsigned int tmds_clk,
+					unsigned int freq)
+{
+	int i, j;
+
+	switch (freq) {
+	case 32000:
+		i = 0;
+		break;
+	case 44100:
+		i = 1;
+		break;
+	case 88200:
+		i = 2;
+		break;
+	case 176400:
+		i = 3;
+		break;
+	case 48000:
+		i = 4;
+		break;
+	case 96000:
+		i = 5;
+		break;
+	case 192000:
+		i = 6;
+		break;
+	default:
+		return 0;
+	}
+
+	switch (tmds_clk) {
+	case 25174825:
+		j = 0;
+		break;
+	case 25200000:
+		j = 1;
+		break;
+	case 27000000:
+		j = 2;
+		break;
+	case 27027000:
+		j = 3;
+		break;
+	case 54000000:
+		j = 4;
+		break;
+	case 54054000:
+		j = 5;
+		break;
+	case 74175824:
+		j = 6;
+		break;
+	case 74250000:
+		j = 7;
+		break;
+	case 148351648:
+		j = 8;
+		break;
+	case 148500000:
+		j = 9;
+		break;
+	default:
+		j = 10;
+		break;
+	}
+	return &hdmi_n_cts_table[i][j];
+}
+#endif
+
+void hdmi_set_audio_n_cts(unsigned int freq)
+{
+	unsigned int n = 0, cts = 0;
+
+#ifdef HDMI_N_CTS_USE_TABLE
+	struct hdmi_n_cts_s *p;
+
+	p = hdmi_get_n_cts(g_vpp.hdmi_pixel_clock, freq);
+	if (p) {
+		n = p->n;
+		cts = p->cts;
+		MSG("[HDMI] use table n %d, cts %d\n", n, cts);
+	}
+#endif
+
+	if (n == 0)
+		n = 128 * freq / 1000;
+
+	if (cts == 0) {
+#ifdef __KERNEL__
+		unsigned int tmp;
+		unsigned int pll_clk;
+
+		pll_clk = auto_pll_divisor(DEV_I2S, GET_FREQ, 0, 0);
+		tmp = (inl(AUDREGF_BASE_ADDR + 0x70) & 0xF);
+
+		switch (tmp) {
+		case 0 ... 4:
+			tmp = 0x01 << tmp;
+			break;
+		case 9 ... 12:
+			tmp = 3 * (0x1 << (tmp-9));
+			break;
+		default:
+			tmp = 1;
+			break;
+		}
+		{
+		unsigned long long tmp2;
+		unsigned long long div2;
+		unsigned long mod;
+
+		tmp2 = g_vpp.hdmi_pixel_clock;
+		tmp2 = tmp2 * n * tmp;
+		div2 = pll_clk;
+		mod = do_div(tmp2, div2);
+		cts = tmp2;
+		}
+		DBGMSG("[HDMI] i2s %d,cts %d,reg 0x%x\n", pll_clk, cts,
+			vppif_reg32_in(AUDREGF_BASE_ADDR + 0x70));
+#else
+		cts = (g_vpp.hdmi_pixel_clock / 1000) - 1;
+#endif
+	}
+	hdmi_regs1->aud_sample_rate1.b.n_20bits = n;
+	hdmi_regs1->aud_ratio.b.acr_ratio = cts - 1;
+	hdmi_regs1->aud_sample_rate2.b.cts_select = 0;
+	cts = 0;
+	hdmi_regs1->aud_sample_rate1.b.cts_low_12bits = cts & 0xFFF;
+	hdmi_regs1->aud_sample_rate2.b.cts_hi_8bits = (cts & 0xFF000) >> 12;
+	DBGMSG("[HDMI] set audio freq %d,n %d,cts %d,tmds %d\n",
+				freq, n, cts, g_vpp.hdmi_pixel_clock);
+}
+
+void hdmi_config_audio(struct vout_audio_t *info)
+{
+	unsigned int freq;
+
+	g_vpp.hdmi_audio_channel = info->channel;
+	g_vpp.hdmi_audio_freq = info->sample_rate;
+
+	/* enable ARF & ARFP clock */
+	REG32_VAL(PM_CTRL_BASE_ADDR + 0x254) |= (BIT4 | BIT3);
+	hdmi_tx_audio_infoframe_packet(info->channel, info->sample_rate);
+	hdmi_audio_enable(VPP_FLAG_DISABLE);
+	hdmi_regs1->aud_mode.b.layout = (info->channel > 2) ? 1 : 0;
+	hdmi_regs1->aud_mode.b._2ch_eco = (info->channel > 2) ? 0 : 1;
+	switch (info->sample_rate) {
+	case 32000:
+		freq = 0x3;
+		break;
+	case 44100:
+		freq = 0x0;
+		break;
+	case 88200:
+		freq = 0x8;
+		break;
+	case 176400:
+		freq = 0xC;
+		break;
+	default:
+	case 48000:
+		freq = 0x2;
+		break;
+	case 96000:
+		freq = 0xA;
+		break;
+	case 192000:
+		freq = 0xE;
+		break;
+	case 768000:
+		freq = 0x9;
+		break;
+	}
+	hdmi_regs1->aud_chan_status0 = (freq << 24) + 0x4;
+	hdmi_regs1->aud_chan_status1 = 0x0;
+	hdmi_regs1->aud_chan_status2 = 0xb;
+	hdmi_regs1->aud_chan_status3 = 0x0;
+	hdmi_regs1->aud_chan_status4 = 0x0;
+	hdmi_regs1->aud_chan_status5 = 0x0;
+
+	hdmi_set_audio_n_cts(info->sample_rate);
+	hdmi_regs1->aud_ratio.b.acr_enable = 1;
+	hdmi_regs1->aud_sample_rate2.b.aipclk_rate = 0;
+	hdmi_audio_enable(VPP_FLAG_ENABLE);
+}
+
+void hdmi_config_video(struct hdmi_info_t *info)
+{
+	hdmi_set_output_colfmt(info->outfmt);
+	hdmi_tx_avi_infoframe_packet(info->outfmt, info->vic);
+	hdmi_tx_vendor_specific_infoframe_packet();
+}
+
+void hdmi_set_option(unsigned int option)
+{
+	vdo_color_fmt colfmt;
+	int temp;
+
+	hdmi_set_dvi_enable((option & EDID_OPT_HDMI) ?
+		VPP_FLAG_DISABLE : VPP_FLAG_ENABLE);
+	hdmi_audio_enable((option & EDID_OPT_AUDIO) ?
+		VPP_FLAG_ENABLE : VPP_FLAG_DISABLE);
+
+	colfmt = hdmi_get_output_colfmt();
+	switch (colfmt) {
+	case VDO_COL_FMT_YUV422H:
+		temp = option & EDID_OPT_YUV422;
+		break;
+	case VDO_COL_FMT_YUV444:
+		temp = option & EDID_OPT_YUV444;
+		break;
+	default:
+		temp = 1;
+		break;
+	}
+	if (temp == 0) {
+		hdmi_set_output_colfmt(VDO_COL_FMT_ARGB);
+		DBG_MSG("[HDMI] TV not support %s,use default RGB\n",
+			vpp_colfmt_str[colfmt]);
+	}
+	DBG_MSG("[HDMI] set option(8-HDMI,6-AUDIO) 0x%x\n", option);
+}
+
+void hdmi_config(struct hdmi_info_t *info)
+{
+	struct vout_audio_t audio_info;
+	int h_porch;
+	int delay_cfg;
+	vpp_clock_t clock;
+
+	hdmi_regs1->ctrl.b.hden = 0;
+	hdmi_regs1->infoframe_ctrl.b.select = 0;
+	hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0;
+	hdmi_config_video(info);
+
+	govrh_get_tg(p_govrh, &clock);
+	h_porch = clock.total_pixel_of_line - clock.end_pixel_of_active; /*fp*/
+	delay_cfg = 47 - h_porch;
+	if (delay_cfg <= 0)
+		delay_cfg = 1;
+	h_porch = clock.begin_pixel_of_active;	/* bp */
+	h_porch = (h_porch - (delay_cfg + 1) - 26) / 32;
+	if (h_porch <= 0)
+		h_porch = 1;
+	if (h_porch >= 8)
+		h_porch = 0;
+
+	hdmi_regs1->general_ctrl.b.cp_delay = delay_cfg;
+	hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for write only */
+	hdmi_regs1->infoframe_ctrl.b.horiz_blank_max_pck = h_porch;
+	DBGMSG("[HDMI] H blank max pck %d,delay %d\n", h_porch, delay_cfg);
+
+	audio_info.fmt = 16;
+	audio_info.channel = info->channel;
+	audio_info.sample_rate = info->freq;
+	hdmi_config_audio(&audio_info);
+
+	hdmi_regs1->infoframe_ctrl.b.fifo1_addr = 0;
+	hdmi_regs1->infoframe_ctrl.b.fifo1_len = 2;
+	hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 1;
+	hdmi_set_option(info->option);
+	hdmi_regs2->test.b.tre_en =
+		(g_vpp.hdmi_pixel_clock < 40000000) ? 3 : 2;
+}
+
+/*----------------------- Module API --------------------------------------*/
+void hdmi_set_cp_enable(vpp_flag_t enable)
+{
+	if (!g_vpp.hdmi_cp_enable)
+		enable = 0;
+
+	if (hdmi_cp)
+		hdmi_cp->enable(enable);
+
+#ifdef __KERNEL__
+	if (hdmi_cp && hdmi_cp->poll) {
+		vpp_irqproc_del_work(VPP_INT_GOVRH_VBIS, (void *)hdmi_cp->poll);
+		if (enable)
+			vpp_irqproc_work(VPP_INT_GOVRH_VBIS,
+				(void *)hdmi_cp->poll, 0, 0, 0);
+	}
+#endif
+}
+
+int hdmi_check_cp_int(void)
+{
+	int ret = 0;
+
+	if (hdmi_cp)
+		ret = hdmi_cp->interrupt();
+	return ret;
+}
+
+void hdmi_get_bksv(unsigned int *bksv)
+{
+	if (hdmi_cp)
+		hdmi_cp->get_bksv(bksv);
+}
+
+#ifdef __KERNEL__
+void hdmi_hotplug_notify(int plug_status)
+{
+	if (g_vpp.hdmi_disable)
+		return;
+	vpp_netlink_notify_plug(VPP_VOUT_NUM_HDMI, plug_status);
+}
+#else
+#define hdmi_hotplug_notify
+#endif
+
+int hdmi_check_plugin(int hotplug)
+{
+	static int last_plugin = -1;
+	int plugin;
+	int flag;
+
+	if (g_vpp.hdmi_disable)
+		return 0;
+
+	plugin = hdmi_get_plugin();
+	hdmi_clear_plug_status();
+#ifdef __KERNEL__
+	/* disable HDMI before change clock */
+	if (plugin == 0) {
+		hdmi_set_enable(0);
+		hdmi_set_power_down(1);
+	}
+	vpp_set_clock_enable(DEV_HDMII2C, plugin, 1);
+	vpp_set_clock_enable(DEV_HDCE, plugin, 1);
+
+	/* slow down clock for plugout */
+	flag = (auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0)
+			== 8000000) ? 0 : 1;
+	if ((plugin != flag) && !g_vpp.virtual_display) {
+		int pixclk;
+
+		pixclk = (plugin) ? g_vpp.hdmi_pixel_clock : 8000000;
+		auto_pll_divisor(DEV_HDMILVDS, SET_PLLDIV, 0, pixclk);
+	}
+#endif
+	if (last_plugin != plugin) {
+		DPRINT("[HDMI] HDMI plug%s,hotplug %d\n", (plugin) ?
+						"in" : "out", hotplug);
+		last_plugin = plugin;
+	}
+#if 0	/* Denzel test */
+	if (plugin == 0)
+		hdmi_set_dvi_enable(VPP_FLAG_ENABLE);
+#endif
+	return plugin;
+}
+
+void hdmi_reg_dump(void)
+{
+	DPRINT("========== HDMI register dump ==========\n");
+	vpp_reg_dump(REG_HDMI_BEGIN, REG_HDMI_END - REG_HDMI_BEGIN);
+	vpp_reg_dump(REG_HDMI2_BEGIN, REG_HDMI2_END - REG_HDMI2_BEGIN);
+
+	DPRINT("---------- HDMI common ----------\n");
+	DPRINT("enable %d,hden %d,reset %d,dvi %d\n",
+		hdmi_regs1->general_ctrl.b.enable,
+		hdmi_regs1->ctrl.b.hden,
+		hdmi_regs1->general_ctrl.b.reset,
+		hdmi_regs1->general_ctrl.b.dvi_mode_enable);
+	DPRINT("colfmt %d,conv 422 %d,hsync low %d,vsync low %d\n",
+		hdmi_regs1->general_ctrl.b.output_format,
+		hdmi_regs1->general_ctrl.b.convert_yuv422,
+		hdmi_regs1->general_ctrl.b.hsync_low_active,
+		hdmi_regs1->general_ctrl.b.vsync_low_active);
+	DPRINT("dbg bus sel %d,state mach %d\n",
+		hdmi_regs1->general_ctrl.b.dbg_bus_select,
+		hdmi_regs1->general_ctrl.b.state_machine_status);
+	DPRINT("eep reset %d,encode %d,eess %d\n",
+		hdmi_regs1->ctrl.b.eeprom_reset,
+		hdmi_regs1->ctrl.b.encode_enable,
+		hdmi_regs1->ctrl.b.eess_enable);
+	DPRINT("verify pj %d,auth test %d,cipher %d\n",
+		hdmi_regs1->ctrl.b.verify_pj_enable,
+		hdmi_regs1->ctrl.b.auth_test_key,
+		hdmi_regs1->ctrl.b.cipher_1_1);
+	DPRINT("preamble %d\n", hdmi_regs1->ctrl.b.preamble);
+
+	DPRINT("---------- HDMI hotplug ----------\n");
+	DPRINT("plug %s\n", (hdmi_regs1->hotplug_detect.b.sts) ? "in" : "out");
+	DPRINT("plug in enable %d, status %d\n",
+		hdmi_regs1->hotplug_detect.b.in_enable,
+		hdmi_regs1->hotplug_detect.b.in_sts);
+	DPRINT("plug out enable %d, status %d\n",
+		hdmi_regs1->hotplug_detect.b.out_enable,
+		hdmi_regs1->hotplug_detect.b.out_sts);
+	DPRINT("debounce detect %d,sample %d\n",
+		hdmi_regs1->hotplug_debounce.b.detect,
+		hdmi_regs1->hotplug_debounce.b.sample);
+
+	DPRINT("---------- I2C ----------\n");
+	DPRINT("enable %d,exit FSM %d,key read %d\n",
+		hdmi_regs1->ctrl.b.i2c_enable,
+		hdmi_regs1->i2c_ctrl.b.force_exit_fsm,
+		hdmi_regs1->i2c_ctrl.b.key_read_word);
+	DPRINT("clk divid %d,rd data 0x%x,wr data 0x%x\n",
+		hdmi_regs1->i2c_ctrl.b.i2c_clk_divider,
+		hdmi_regs1->i2c_ctrl2.b.rd_data,
+		hdmi_regs1->i2c_ctrl2.b.wr_data);
+	DPRINT("start %d,stop %d,wr avail %d\n",
+		hdmi_regs1->i2c_ctrl2.b.sw_start_req,
+		hdmi_regs1->i2c_ctrl2.b.sw_stop_req,
+		hdmi_regs1->i2c_ctrl2.b.wr_data_avail);
+	DPRINT("status %d,sw read %d,sw i2c req %d\n",
+		hdmi_regs1->i2c_ctrl2.b.i2c_status,
+		hdmi_regs1->i2c_ctrl2.b.sw_read,
+		hdmi_regs1->i2c_ctrl2.b.sw_i2c_req);
+
+	DPRINT("---------- AUDIO ----------\n");
+	DPRINT("enable %d,sub pck %d,spflat %d\n",
+		hdmi_regs1->aud_enable,
+		hdmi_regs1->aud_mode.b.sub_packet,
+		hdmi_regs1->aud_mode.b.spflat);
+	DPRINT("aud pck insert reset %d,enable %d,delay %d\n",
+		hdmi_regs1->aud_insert_ctrl.b.pck_insert_reset,
+		hdmi_regs1->aud_insert_ctrl.b.pck_insert_enable,
+		hdmi_regs1->aud_insert_ctrl.b.insert_delay);
+	DPRINT("avmute set %d,clr %d,pixel repete %d\n",
+		hdmi_regs1->aud_insert_ctrl.b.avmute_set_enable,
+		hdmi_regs1->aud_insert_ctrl.b.avmute_clr_enable,
+		hdmi_regs1->aud_insert_ctrl.b.pixel_repetition);
+	DPRINT("acr ratio %d,acr enable %d,mute %d\n",
+		hdmi_regs1->aud_ratio.b.acr_ratio,
+		hdmi_regs1->aud_ratio.b.acr_enable,
+		hdmi_regs1->aud_ratio.b.mute);
+	DPRINT("layout %d,pwr save %d,n 20bits %d\n",
+		hdmi_regs1->aud_mode.b.layout,
+		hdmi_regs1->aud_mode.b.pwr_saving,
+		hdmi_regs1->aud_sample_rate1.b.n_20bits);
+	DPRINT("cts low 12 %d,hi 8 %d,cts sel %d\n",
+		hdmi_regs1->aud_sample_rate1.b.cts_low_12bits,
+		hdmi_regs1->aud_sample_rate2.b.cts_hi_8bits,
+		hdmi_regs1->aud_sample_rate2.b.cts_select);
+	DPRINT("aipclk rate %d\n", hdmi_regs1->aud_sample_rate2.b.aipclk_rate);
+
+	DPRINT("---------- INFOFRAME ----------\n");
+	DPRINT("sel %d,hor blank pck %d\n",
+		hdmi_regs1->infoframe_ctrl.b.select,
+		hdmi_regs1->infoframe_ctrl.b.horiz_blank_max_pck);
+	DPRINT("fifo1 ready %d,addr 0x%x,len %d\n",
+		hdmi_regs1->infoframe_ctrl.b.fifo1_rdy,
+		hdmi_regs1->infoframe_ctrl.b.fifo1_addr,
+		hdmi_regs1->infoframe_ctrl.b.fifo1_len);
+	DPRINT("fifo2 ready %d,addr 0x%x,len %d\n",
+		hdmi_regs1->infoframe_ctrl.b.fifo2_rdy,
+		hdmi_regs1->infoframe_ctrl.b.fifo2_addr,
+		hdmi_regs1->infoframe_ctrl.b.fifo2_len);
+	DPRINT("wr strobe %d,rd strobe %d,fifo addr %d\n",
+		hdmi_regs1->fifo_ctrl.b.wr_strobe,
+		hdmi_regs1->fifo_ctrl.b.rd_strobe,
+		hdmi_regs1->fifo_ctrl.b.addr);
+
+	{
+	int i;
+	unsigned int buf[32];
+
+	for (i = 0; i <= hdmi_regs1->infoframe_ctrl.b.fifo1_len; i++) {
+		DPRINT("----- infoframe %d -----\n", i);
+		hdmi_read_fifo(i, buf, 32);
+		vpp_reg_dump((unsigned int) buf, 32);
+	}
+	}
+
+	DPRINT("---------- HDMI test ----------\n");
+	DPRINT("ch0 enable %d, data 0x%x\n",
+		hdmi_regs1->channel_test.b.ch0_enable,
+		hdmi_regs1->channel_test.b.ch0_data);
+	DPRINT("ch1 enable %d, data 0x%x\n",
+		hdmi_regs1->channel_test.b.ch1_enable,
+		hdmi_regs1->channel_test.b.ch1_data);
+	DPRINT("ch2 enable %d, data 0x%x\n",
+		hdmi_regs1->hotplug_detect.b.ch2_enable,
+		hdmi_regs1->hotplug_detect.b.ch2_data);
+	if (hdmi_cp)
+		hdmi_cp->dump();
+}
+
+#ifdef CONFIG_PM
+static unsigned int *hdmi_pm_bk;
+static unsigned int *hdmi_pm_bk2;
+static unsigned int hdmi_pm_enable;
+static unsigned int hdmi_pm_enable2;
+static int hdmi_plug_enable = 0xFF;
+static int hdmi_resume_plug_cnt;
+#define HDMI_RESUME_PLUG_MS	50
+#define HDMI_RESUME_PLUG_CNT	20
+static void hdmi_do_resume_plug(struct work_struct *ptr)
+{
+	struct vout_t *vo;
+	int plugin;
+	struct delayed_work *dwork = to_delayed_work(ptr);
+
+	plugin = hdmi_check_plugin(0);
+	vo = vout_get_entry(VPP_VOUT_NUM_HDMI);
+	vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin);
+	if (plugin)
+		hdmi_hotplug_notify(1);
+	hdmi_resume_plug_cnt--;
+	if (hdmi_resume_plug_cnt && (vpp_sdev.state == 0))
+		schedule_delayed_work(dwork,
+			msecs_to_jiffies(HDMI_RESUME_PLUG_MS));
+}
+
+DECLARE_DELAYED_WORK(hdmi_resume_work, hdmi_do_resume_plug);
+
+void hdmi_suspend(int sts)
+{
+	vo_hdmi_set_clock(1);
+	switch (sts) {
+	case 0:	/* disable module */
+		cancel_delayed_work_sync(&hdmi_resume_work);
+		hdmi_pm_enable = hdmi_regs1->general_ctrl.b.enable;
+		hdmi_regs1->general_ctrl.b.enable = 0;
+		hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for wr only */
+		hdmi_pm_enable2 = hdmi_regs1->ctrl.b.hden;
+		hdmi_regs1->ctrl.b.hden = 0;
+		if (hdmi_plug_enable == 0xFF)
+			hdmi_plug_enable =
+				hdmi_regs1->hotplug_detect.b.out_enable;
+		hdmi_enable_plugin(0);
+		break;
+	case 1: /* disable tg */
+		break;
+	case 2:	/* backup register */
+		hdmi_pm_bk = vpp_backup_reg(REG_HDMI_BEGIN,
+			(REG_HDMI_END - REG_HDMI_BEGIN));
+		hdmi_pm_bk2 = vpp_backup_reg(REG_HDMI2_BEGIN,
+			(REG_HDMI2_END - REG_HDMI2_BEGIN));
+		hdmi_resume_plug_cnt = 20;
+		break;
+	default:
+		break;
+	}
+	vo_hdmi_set_clock(0);
+}
+
+void hdmi_resume(int sts)
+{
+	vo_hdmi_set_clock(1);
+	switch (sts) {
+	case 0:	/* restore register */
+		switch_set_state(&vpp_sdev, 0);		
+		vpp_restore_reg(REG_HDMI_BEGIN,
+			(REG_HDMI_END - REG_HDMI_BEGIN), hdmi_pm_bk);
+		vpp_restore_reg(REG_HDMI2_BEGIN,
+			(REG_HDMI2_END - REG_HDMI2_BEGIN), hdmi_pm_bk2);
+		hdmi_pm_bk = 0;
+		hdmi_pm_bk2 = 0;
+		hdmi_config(&hdmi_info); /* re-config HDMI info frame */
+		if (g_vpp.hdmi_cp_p && hdmi_cp)
+			hdmi_cp->init();
+		break;
+	case 1:	/* enable module */
+		hdmi_regs1->general_ctrl.b.enable = hdmi_pm_enable;
+		hdmi_regs1->general_ctrl.b.vsync_enable = 1; /* for wr only */
+		hdmi_regs1->ctrl.b.hden = hdmi_pm_enable2;
+		break;
+	case 2: /* enable tg */
+		hdmi_check_plugin(0);
+		hdmi_clear_plug_status();
+		hdmi_enable_plugin(hdmi_plug_enable);
+		hdmi_plug_enable = 0xFF;
+		if (vpp_sdev.state == 0) {
+			hdmi_resume_plug_cnt = HDMI_RESUME_PLUG_CNT;
+			schedule_delayed_work(&hdmi_resume_work,
+				msecs_to_jiffies(HDMI_RESUME_PLUG_MS));
+		}
+		break;
+	default:
+		break;
+	}
+	vo_hdmi_set_clock(0);
+}
+#else
+#define hdmi_suspend NULL
+#define hdmi_resume NULL
+#endif
+
+void hdmi_init(void)
+{
+	struct fb_videomode vmode;
+
+	g_vpp.hdmi_pixel_clock = vpp_get_base_clock(VPP_MOD_GOVRH);
+	g_vpp.hdmi_i2c_freq = HDMI_I2C_FREQ;
+	g_vpp.hdmi_i2c_udelay = 0;
+	g_vpp.hdmi_ctrl = 0x1000000;
+	g_vpp.hdmi_audio_pb4 = 0x0;
+	g_vpp.hdmi_audio_pb1 = 0x0;
+
+	hdmi_info.outfmt = hdmi_get_output_colfmt();
+	govrh_get_videomode(p_govrh, &vmode);
+	hdmi_info.vic = hdmi_get_vic(vmode.xres, vmode.yres, vmode.refresh,
+		(vmode.vmode & FB_VMODE_INTERLACED) ? 1 : 0);
+	hdmi_info.channel = 2;
+	hdmi_info.freq = 48000;
+	hdmi_info.option = EDID_OPT_AUDIO + EDID_OPT_HDMI;
+
+	hdmi_enable_plugin(0);
+
+	if (g_vpp.govrh_preinit) {
+		DBGMSG("[HDMI] hdmi_init for uboot logo\n");
+	} else {
+		/* bit8-HDMI SDA,bit9-HDMI SCL,bit10-Hotplug,bit26-CEC */
+		/* GPIO disable GPIO function */
+		vppif_reg32_write(GPIO_BASE_ADDR+0x54, 0x4000700, 0, 0);
+		/* GPIO4 disable GPIO out */
+		vppif_reg32_write(GPIO_BASE_ADDR+0x494, 0x4000700, 0, 0);
+#if 0
+		/* Suspend GPIO output enable */
+		vppif_reg32_write(GPIO_BASE_ADDR+0x80, BIT23, 23, 1);
+		/* Suspend GPIO output high */
+		vppif_reg32_write(GPIO_BASE_ADDR+0xC0, BIT23, 23, 1);
+		/* Wake3 disable pull ctrl */
+		vppif_reg32_write(GPIO_BASE_ADDR+0x480, BIT19, 19, 0);
+#endif
+		hdmi_regs2->level.b.level = 1;
+		hdmi_regs2->level.b.update = 1;
+		hdmi_regs2->igs.b.ldi_shift_left = 1;
+		hdmi_regs2->status.val = 0x0008c000;
+		hdmi_regs2->test.val = 0x00450409;
+		hdmi_regs2->test2.val = 0x00005022;
+		hdmi_regs2->test3 = (g_vpp.hdmi_sp_mode) ?
+					0x00010100 : 0x00000100;
+		hdmi_set_enable(VPP_FLAG_DISABLE);
+		hdmi_set_dvi_enable(VPP_FLAG_DISABLE);
+		hdmi_regs1->ctrl.b.cipher_1_1 = 0;
+
+		hdmi_regs1->tmds_ctrl.b.infoframe_sram_enable = 1;
+		hdmi_regs1->infoframe_ctrl.b.select = 0;
+		hdmi_regs1->infoframe_ctrl.b.fifo1_rdy = 0;
+
+		hdmi_regs1->hotplug_detect.val = 0x0;
+		hdmi_regs1->channel_test.val = 0x1;
+
+		hdmi_DDC_reset();
+		hdmi_DDC_set_freq(g_vpp.hdmi_i2c_freq);
+		hdmi_regs1->ctrl.b.i2c_enable = 1;
+	}
+	g_vpp.hdmi_init = 1;
+	if (hdmi_cp)
+		hdmi_cp->init();
+}
+#endif /* WMT_FTBLK_HDMI */
diff --git a/drivers/video/wmt/hdmi.h b/drivers/video/wmt/hdmi.h
new file mode 100755
index 00000000..13c80940
--- /dev/null
+++ b/drivers/video/wmt/hdmi.h
@@ -0,0 +1,352 @@
+/*++
+ * linux/drivers/video/wmt/hdmi.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef HDMI_H
+/* To assert that only one occurrence is included */
+#define HDMI_H
+/*-------------------- MODULE DEPENDENCY -------------------------------------*/
+#include "vpp.h"
+
+/*	following is the C++ header	*/
+#ifdef	__cplusplus
+extern	"C" {
+#endif
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+/* #define  HDMI_XXXX  1    *//*Example*/
+#define CONFIG_HDMI_INTERRUPT
+#define HDMI_PLUG_DELAY	        300	/* plug stable delay ms */
+#define HDMI_CP_TIME		3	/* should more than 2 seconds */
+
+enum hdmi_packet_type_t {
+	HDMI_PACKET_NULL = 0x0,
+	HDMI_PACKET_AUD_CLOCK_REGEN = 0x1,
+	HDMI_PACKET_AUD_SAMPLE = 0x2,
+	HDMI_PACKET_GENERAL_CTRL = 0x3,
+	HDMI_PACKET_ACP = 0x4,
+	HDMI_PACKET_ISRC1 = 0x5,
+	HDMI_PACKET_ISRC2 = 0x6,
+	HDMI_PACKET_AUD_ONE_BIT_SAMPLE = 0x7,
+	HDMI_PACKET_AUD_DST = 0x8,
+	HDMI_PACKET_AUD_HBR = 0x9,
+	HDMI_PACKET_GAMUT_METADATA = 0xA,
+	HDMI_PACKET_INFOFRAME_VENDOR = 0x81,
+	HDMI_PACKET_INFOFRAME_AVI = 0x82,
+	HDMI_PACKET_INFOFRAME_SRC_PRODUCT_DESC = 0x83,
+	HDMI_PACKET_INFOFRAME_AUDIO = 0x84,
+	HDMI_PACKET_INFOFRAME_MPEG_SOURCE = 0x85
+};
+
+/* color depth (CD field) */
+#define HDMI_COLOR_DEPTH_24	0x4
+#define HDMI_COLOR_DEPTH_30	0x5
+#define HDMI_COLOR_DEPTH_36	0x6
+#define HDMI_COLOR_DEPTH_48	0x7
+
+/* pixel packing phase (PP field) */
+#define HDMI_PHASE_4		0x0
+#define HDMI_PHASE_1		0x1
+#define HDMI_PHASE_2		0x2
+#define HDMI_PHASE_3		0x3
+
+/* Scan Information (AVI InfoFrame S0/S1) */
+#define HDMI_SI_NO_DATA		0x0
+#define HDMI_SI_OVERSCAN	0x1
+#define HDMI_SI_UNDERSCAN	0x2
+
+/* Bar Info (AVI InfoFrame B0/B1) */
+#define HDMI_BI_DATA_NOT_VALID	0x0
+#define HDMI_BI_VERT_VALID	0x1
+#define HDMI_BI_HORIZ_VALID	0x2
+#define HDMI_BI_V_H_VALID	0x3
+
+/* Active Format Information Present (AVI InfoFrame A0) */
+#define HDMI_AF_INFO_NO_DATA	0x0
+#define HDMI_AF_INFO_PRESENT	0x1
+
+/* RGB or YCbCr (AVI InfoFrame Y0/Y1) */
+#define HDMI_OUTPUT_RGB		0x0
+#define HDMI_OUTPUT_YUV422	0x1
+#define HDMI_OUTPUT_YUV444	0x2
+
+/* Aspect Ratio (AVI InfoFrame R0/R1/R2/R3) */
+#define HDMI_ASPECT_RATIO_PIC	0x8
+#define HDMI_ASPECT_RATIO_4_3	0x9
+#define HDMI_ASPECT_RATIO_16_9	0xA
+#define HDMI_ASPECT_RATIO_14_9	0xB
+
+/* Picture Aspect Ratio (AVI InfoFrame M0/M1) */
+#define HDMI_PIC_ASPECT_NO_DATA	0x0
+#define HDMI_PIC_ASPECT_4_3	0x1
+#define HDMI_PIC_ASPECT_16_9	0x2
+
+/* Colorimetry (AVI InfoFrame C0/C1) */
+#define HDMI_COLORIMETRY_NO	0x0
+#define HDMI_COLORIMETRY_ITU601	0x1
+#define HDMI_COLORIMETRY_ITU709	0x2
+
+/* Non-uniform Picture Scaling (AVI InfoFrame SC0/SC1) */
+#define HDMI_NUSCALE_NO		0x0
+#define HDMI_NUSCALE_HOR	0x1
+#define HDMI_NUSCALE_VERT	0x2
+#define HDMI_NUSCALE_HOR_VERT	0x3
+
+/* Pixel Repetition (AVI InfoFrame PR0/PR1/PR2/PR3) */
+#define HDMI_PIXEL_REP_NO	0x0
+#define HDMI_PIXEL_REP_2	0x1
+#define HDMI_PIXEL_REP_3	0x2
+#define HDMI_PIXEL_REP_4	0x3
+#define HDMI_PIXEL_REP_5	0x4
+#define HDMI_PIXEL_REP_6	0x5
+#define HDMI_PIXEL_REP_7	0x6
+#define HDMI_PIXEL_REP_8	0x7
+#define HDMI_PIXEL_REP_9	0x8
+#define HDMI_PIXEL_REP_10	0x9
+
+/* Video Code */
+enum hdmi_video_code_t {
+	HDMI_UNKNOW = 0,
+	HDMI_640x480p60_4x3,
+	HDMI_720x480p60_4x3,
+	HDMI_720x480p60_16x9,
+	HDMI_1280x720p60_16x9,
+	HDMI_1920x1080i60_16x9,
+	HDMI_1440x480i60_4x3,
+	HDMI_1440x480i60_16x9,
+	HDMI_1440x240p60_4x3,
+	HDMI_1440x240p60_16x9,
+	HDMI_2880x480i60_4x3,	/* 10 */
+	HDMI_2880x480i60_16x9,
+	HDMI_2880x240p60_4x3,
+	HDMI_2880x240p60_16x9,
+	HDMI_1440x480p60_4x3,
+	HDMI_1440x480p60_16x9,
+	HDMI_1920x1080p60_16x9,
+	HDMI_720x576p50_4x3,
+	HDMI_720x576p50_16x9,
+	HDMI_1280x720p50_16x9,
+	HDMI_1920x1080i50_16x9,	/* 20 */
+	HDMI_1440x576i50_4x3,
+	HDMI_1440x576i50_16x9,
+	HDMI_1440x288p50_4x3,
+	HDMI_1440x288p50_16x9,
+	HDMI_2880x576i50_4x3,
+	HDMI_2880x576i50_16x9,
+	HDMI_2880x288p50_4x3,
+	HDMI_2880x288p50_16x9,
+	HDMI_1440x576p50_4x3,
+	HDMI_1440x576p50_16x9,	/* 30 */
+	HDMI_1920x1080p50_16x9,
+	HDMI_1920x1080p24_16x9,
+	HDMI_1920x1080p25_16x9,
+	HDMI_1920x1080p30_16x9,
+	HDMI_VIDEO_CODE_MAX
+};
+
+/* Audio Channel Count (Audio InfoFrame CC0/CC1/CC2) */
+enum hdmi_audio_channel_count_t {
+	HDMI_AUD_CHAN_REF_STM = 0,
+	HDMI_AUD_CHAN_2CH,
+	HDMI_AUD_CHAN_3CH,
+	HDMI_AUD_CHAN_4CH,
+	HDMI_AUD_CHAN_5CH,
+	HDMI_AUD_CHAN_6CH,
+	HDMI_AUD_CHAN_7CH,
+	HDMI_AUD_CHAN_8CH
+};
+
+/* Audio Coding type (Audio InfoFrame CT0/CT1/CT2/CT3) */
+#define HDMI_AUD_TYPE_REF_STM		0x0
+#define HDMI_AUD_TYPE_PCM		0x1
+#define HDMI_AUD_TYPE_AC3		0x2
+#define HDMI_AUD_TYPE_MPEG1		0x3
+#define HDMI_AUD_TYPE_MP3		0x4
+#define HDMI_AUD_TYPE_MPEG2		0x5
+#define HDMI_AUD_TYPE_AAC		0x6
+#define HDMI_AUD_TYPE_DTS		0x7
+#define HDMI_AUD_TYPE_ATRAC		0x8
+
+/* Audio Sample size (Audio InfoFrame SS0/SS1) */
+#define HDMI_AUD_SAMPLE_REF_STM		0x0
+#define HDMI_AUD_SAMPLE_16		0x1
+#define HDMI_AUD_SAMPLE_20		0x2
+#define HDMI_AUD_SAMPLE_24		0x3
+
+/* Audio Sample frequency (Audio InfoFrame SF0/SF1/SF2) */
+#define HDMI_AUD_FREQ_REF_STM		0x0
+#define HDMI_AUD_FREQ_32K		0x1
+#define HDMI_AUD_FREQ_44_1K		0x2
+#define HDMI_AUD_FREQ_48K		0x3
+#define HDMI_AUD_FREQ_88_2K		0x4
+#define HDMI_AUD_FREQ_96K		0x5
+#define HDMI_AUD_FREQ_176_4K		0x6
+#define HDMI_AUD_FREQ_192K		0x7
+
+/* 3D_Structure */
+#define HDMI_3D_STRUCTURE_FRAME_PACKING		0x0
+#define HDMI_3D_STRUCTURE_FIELD_ALTERNATIVE	0x1
+#define HDMI_3D_STRUCTURE_LINE_ALTERNATIVE	0x2
+#define HDMI_3D_STRUCTURE_SIDE_BY_SIDE_FULL	0x3
+#define HDMI_3D_STRUCTURE_L_DEPTH		0x4
+#define HDMI_3D_STRUCTURE_L_DEP_GRA_GDEP	0x5
+#define HDMI_3D_STRUCTURE_TOP_AND_BOTTOM	0x6
+#define HDMI_3D_STRUCTURE_SIZE_BY_SIZE_HALF	0x8
+
+/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/
+/* typedef  void  hdmi_xxx_t;  *//*Example*/
+struct hdmi_info_t {
+	/* video */
+	vdo_color_fmt outfmt;
+	int vic;
+
+	/* audio */
+	int channel;
+	int freq;
+
+	/* option */
+	int option;
+
+};
+
+#define HDMI_VIC_INTERLACE	BIT(0)
+#define HDMI_VIC_PROGRESS	0
+#define HDMI_VIC_4x3		BIT(1)
+#define HDMI_VIC_16x9		0
+
+struct hdmi_vic_t {
+	unsigned short resx;
+	unsigned short resy;
+	char freq;
+	char option;
+};
+
+struct hdmi_cp_t {
+	void (*init)(void);
+	void (*enable)(int on);
+	int (*poll)(void);
+	void (*dump)(void);
+	int (*interrupt)(void);
+	void (*get_bksv)(unsigned int *bksv);
+};
+
+/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/
+#ifdef VPP_C
+#define EXTERN
+
+const struct hdmi_vic_t hdmi_vic_info[HDMI_VIDEO_CODE_MAX] = {
+	{ 0, 0, 0, 0 },	/* HDMI_UNKNOW = 0 */
+	{ 640, 480, 60, HDMI_VIC_4x3 },	/* HDMI_640x480p60_4x3 */
+	{ 720, 480, 60, HDMI_VIC_4x3 },	/* HDMI_720x480p60_4x3 */
+	{ 720, 480, 60, 0 }, /* HDMI_720x480p60_16x9 */
+	{ 1280, 720, 60, 0 }, /* HDMI_1280x720p60_16x9 */
+	{ 1920, 1080, 60, HDMI_VIC_INTERLACE }, /* HDMI_1920x1080i60_16x9 */
+	{ 720, 480, 60, HDMI_VIC_4x3 | HDMI_VIC_INTERLACE }, /*1440x480i60_4x3*/
+	{ 720, 480, 60, HDMI_VIC_INTERLACE }, /* HDMI_1440x480i60_16x9 */
+	{ 720, 240, 60, HDMI_VIC_4x3 }, /* HDMI_1440x240p60_4x3 */
+	{ 720, 240, 60, 0 }, /* HDMI_1440x240p60_16x9 */
+	{ 2880, 480, 60, HDMI_VIC_4x3 | HDMI_VIC_INTERLACE },/*2880x480i60_4x3*/
+	{ 2880, 480, 60, HDMI_VIC_INTERLACE }, /* HDMI_2880x480i60_16x9 */
+	{ 2880, 240, 60, HDMI_VIC_4x3 }, /* HDMI_2880x240p60_4x3 */
+	{ 2880, 240, 60, 0 }, /* HDMI_2880x240p60_16x9 */
+	{ 1440, 480, 60, HDMI_VIC_4x3 }, /* HDMI_1440x480p60_4x3 */
+	{ 1440, 480, 60, 0 }, /* HDMI_1440x480p60_16x9 */
+	{ 1920, 1080, 60, 0 }, /* HDMI_1920x1080p60_16x9 */
+	{ 720, 576, 50, HDMI_VIC_4x3 }, /* HDMI_720x576p50_4x3 */
+	{ 720, 576, 50, 0 }, /* HDMI_720x576p50_16x9 */
+	{ 1280, 720, 50, 0 }, /* HDMI_1280x720p50_16x9 */
+	{ 1920, 1080, 50, HDMI_VIC_INTERLACE }, /* HDMI_1920x1080i50_16x9, 20 */
+	{ 720, 576, 50, HDMI_VIC_INTERLACE | HDMI_VIC_4x3 }, /*1440x576i50_4x3*/
+	{ 720, 576, 50, HDMI_VIC_INTERLACE }, /* HDMI_1440x576i50_16x9 */
+	{ 720, 288, 50, HDMI_VIC_4x3 }, /* HDMI_1440x288p50_4x3 */
+	{ 720, 288, 50, 0 }, /* HDMI_1440x288p50_16x9 */
+	{ 2880, 576, 50, HDMI_VIC_INTERLACE | HDMI_VIC_4x3}, /*2880x576i50_4x3*/
+	{ 2880, 576, 50, HDMI_VIC_INTERLACE }, /* HDMI_2880x576i50_16x9 */
+	{ 2880, 288, 50, HDMI_VIC_4x3 }, /* HDMI_2880x288p50_4x3 */
+	{ 2880, 288, 50, 0 }, /* HDMI_2880x288p50_16x9 */
+	{ 1440, 576, 50, HDMI_VIC_4x3 }, /* HDMI_1440x576p50_4x3 */
+	{ 1440, 576, 50, 0 }, /* HDMI_1440x576p50_16x9,	// 30 */
+	{ 1920, 1080, 50, 0 }, /* HDMI_1920x1080p50_16x9 */
+	{ 1920, 1080, 24, 0 }, /* HDMI_1920x1080p24_16x9 */
+	{ 1920, 1080, 25, 0 }, /* HDMI_1920x1080p25_16x9 */
+	{ 1920, 1080, 30, 0 } /* HDMI_1920x1080p30_16x9 */
+};
+#else
+#define EXTERN   extern
+
+EXTERN const struct hdmi_vic_t hdmi_vic_info[HDMI_VIDEO_CODE_MAX];
+#endif /* ifdef HDMI_C */
+
+EXTERN struct hdmi_cp_t *hdmi_cp;
+EXTERN int hdmi_ri_tm_cnt;
+EXTERN struct hdmi_info_t hdmi_info;
+
+#ifdef VPP_C
+EXPORT_SYMBOL(hdmi_cp);
+EXPORT_SYMBOL(hdmi_ri_tm_cnt);
+EXPORT_SYMBOL(hdmi_regs1);
+EXPORT_SYMBOL(hdmi_regs2);
+#endif
+
+/* EXTERN int      hdmi_xxx; *//*Example*/
+#undef EXTERN
+
+/*--------------------- EXPORTED PRIVATE MACROS -----------------------------*/
+/* #define HDMI_XXX_YYY   xxxx *//*Example*/
+/*--------------------- EXPORTED PRIVATE FUNCTIONS  -------------------------*/
+/* extern void  hdmi_xxx(void); *//*Example*/
+
+void hdmi_init(void);
+void hdmi_reg_dump(void);
+void hdmi_audio_enable(vpp_flag_t enable);
+void hdmi_audio_mute(vpp_flag_t enable);
+void hdmi_set_enable(vpp_flag_t enable);
+void hdmi_set_avmute(vpp_flag_t mute);
+void hdmi_set_dvi_enable(vpp_flag_t enable);
+void hdmi_set_cp_enable(vpp_flag_t enable);
+int hdmi_check_cp_int(void);
+void hdmi_config(struct hdmi_info_t *info);
+int hdmi_DDC_read(char addr, int index, char *buf, int length);
+int hdmi_get_plugin(void);
+int hdmi_get_plug_status(void);
+void hdmi_clear_plug_status(void);
+void hdmi_suspend(int sts);
+void hdmi_resume(int sts);
+void hdmi_set_power_down(int pwrdn);
+void hdmi_enable_plugin(int enable);
+vdo_color_fmt hdmi_get_output_colfmt(void);
+void hdmi_set_sync_low_active(vpp_flag_t hsync, vpp_flag_t vsync);
+void hdmi_get_sync_polar(int *hsync_hi, int *vsync_hi);
+int hdmi_check_plugin(int hotplug);
+void hdmi_set_cypher(int func);
+void hdmi_set_option(unsigned int option);
+void hdmi_get_bksv(unsigned int *bksv);
+int hdmi_check_cp_dev_cnt(void);
+void hdmi_hotplug_notify(int plug_status);
+void hdmi_tx_vendor_specific_infoframe_packet(void);
+int hdmi_get_vic(int resx, int resy, int fps, int interlace);
+
+#ifdef	__cplusplus
+}
+#endif
+#endif /* ifndef HDMI_H */
+
diff --git a/drivers/video/wmt/hw/wmt-cec-reg.h b/drivers/video/wmt/hw/wmt-cec-reg.h
new file mode 100755
index 00000000..17e7275c
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-cec-reg.h
@@ -0,0 +1,220 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-cec-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_CEC_REG_H
+#define WMT_CEC_REG_H
+
+#define WMT_FTBLK_CEC
+
+#define CEC_BASE_ADDR			(LVDS_BASE_ADDR + 0x100)
+#define CEC_BASE2_ADDR			(LVDS_BASE_ADDR + 0x200)
+struct cec_base_regs {
+	union {
+		unsigned int val;
+		struct {
+			unsigned int wr_start:1;
+		} b;
+	} enable; /* 0x0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int wr_num:8;
+		} b;
+	} encode_number; /* 0x04 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int wr_data_ack:1;
+			unsigned int wr_data_eom:1;
+			unsigned int _02_03:2;
+			unsigned int wr_data:8;
+		} b;
+	} encode_data[16]; /* 0x08 header,0x0c - 0x44 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int finish_reset:1;
+		} b;
+	} decode_reset; /* 0x48 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int rd_start:1;
+			unsigned int rd_all_ack:1;
+			unsigned int rd_finish:1;
+		} b;
+	} decode_start; /* 0x4c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int rd_data_ack:1;
+			unsigned int rd_data_eom:1;
+			unsigned int _02_03:2;
+			unsigned int rd_data:8;
+		} b;
+	} decode_data[16]; /* 0x50 header, 0x54 - 0x8c */
+
+	unsigned int wr_start_set0; /* 0x90 */
+	unsigned int wr_start_set1; /* 0x94 */
+	unsigned int wr_logic0_set0; /* 0x98 */
+	unsigned int wr_logic0_set1; /* 0x9c */
+	unsigned int wr_logic1_set0; /* 0xa0 */
+	unsigned int wr_logic1_set1; /* 0xa4 */
+	unsigned int rd_start_l_set0; /* 0xa8 */
+	unsigned int rd_start_r_set0; /* 0xac */
+	unsigned int rd_start_l_set1; /* 0xb0 */
+	unsigned int rd_start_r_set1; /* 0xb4 */
+	unsigned int rd_logic0_l_set0; /* 0xb8 */
+	unsigned int rd_logic0_r_set0; /* 0xbc */
+	unsigned int rd_logic0_l_set1; /* 0xc0 */
+	unsigned int rd_logic0_r_set1; /* 0xc4 */
+	unsigned int rd_logic1_l_set0; /* 0xc8 */
+	unsigned int rd_logic1_r_set0; /* 0xcc */
+	unsigned int rd_logic1_l_set1; /* 0xd0 */
+	unsigned int rd_logic1_r_set1; /* 0xd4 */
+	unsigned int physical_addr; /* 0xd8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int addr1:4;
+			unsigned int addr2:4;
+			unsigned int addr3:4;
+			unsigned int addr4:4;
+			unsigned int addr5:4;
+			unsigned int _20_23:4;
+			unsigned int valid1:1;
+			unsigned int valid2:1;
+			unsigned int valid3:1;
+			unsigned int valid4:1;
+			unsigned int valid5:1;
+		} b;
+	} logical_addr; /* 0xdc */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int retry:4;
+		} b;
+	} wr_retry; /* 0xe0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int free_3x:4;
+			unsigned int _04_07:4;
+			unsigned int free_5x:4;
+			unsigned int _12_15:4;
+			unsigned int free_7x:4;
+		} b;
+	} free_3x; /* 0xe4 */
+
+	unsigned int wr_set0_error; /* 0xe8 */
+	unsigned int wr_set1_error; /* 0xec */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int next_decode:1; /*read enable*/
+		} b;
+	} reject; /* 0xf0 */
+
+	unsigned int rd_l_set0_error; /* 0xf4 */
+	unsigned int rd_r_set1_error; /* 0xf8 */
+	unsigned int rd_l_error; /* 0xfc */
+
+	unsigned int rx_trig_range; /* 0x100 */
+	unsigned int rx_sample_l_range; /* 0x104 */
+	unsigned int rx_sample_r_range; /* 0x108 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int disable:1;
+		} b;
+	} comp; /* 0x10c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int err:1;
+			unsigned int no_ack:1;
+		} b;
+	} handle_disable; /* 0x110 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int r1_encode_ok:1; /* write finish */
+			unsigned int r1_decode_ok:1; /* read finish */
+			unsigned int r1_error:1; /* read error */
+			unsigned int r1_arb_fail:1; /* wr arb fail */
+			unsigned int r1_no_ack:1; /* wr no ack */
+		} b;
+	} status; /* 0x114 */
+
+	unsigned int int_enable; /* 0x118 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int disable:1;
+		} b;
+	} decode_full; /* 0x11c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int start:1;
+			unsigned int logic0:1;
+			unsigned int logic1:1;
+		} b;
+	} status4_disable; /* 0x120 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1; /*1:rd self wr & all dest data */
+		} b;
+	} rd_encode; /* 0x124 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int disable:1; /* 1 : disable arb check */
+		} b;
+	} arb_check; /* 0x128 */
+};
+
+#define REG_CEC_BEGIN	(CEC_BASE_ADDR + 0x0)
+#define REG_CEC_END	(CEC_BASE2_ADDR + 0x28)
+#ifndef CEC_C
+extern struct cec_base_regs *cec_regs;
+#endif
+#endif /* WMT_CEC_REG_H */
+
diff --git a/drivers/video/wmt/hw/wmt-govrh-reg.h b/drivers/video/wmt/hw/wmt-govrh-reg.h
new file mode 100755
index 00000000..ecdeb4f2
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-govrh-reg.h
@@ -0,0 +1,366 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-govrh-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_GOVRH_REG_H
+#define WMT_GOVRH_REG_H
+
+/* feature */
+#define WMT_FTBLK_GOVRH
+#ifndef CONFIG_UBOOT
+#define WMT_FTBLK_GOVRH_CURSOR
+#endif
+#define WMT_FTBLK_GOVRH2
+
+#define GOVRH_FRAMEBUF_ALIGN	128
+
+struct govrh_regs {
+	/* base1 */
+	unsigned int cur_addr; /* 0x00 */
+	unsigned int cur_width;
+	unsigned int cur_fb_width;
+	unsigned int cur_vcrop;
+	unsigned int cur_hcrop; /* 0x10 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int start:11;
+			unsigned int reserved:5;
+			unsigned int end:11;
+		} b;
+	} cur_hcoord; /* 0x14 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int start:11;
+			unsigned int reserved:5;
+			unsigned int end:11;
+		} b;
+	} cur_vcoord; /* 0x18 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int reserved:7;
+			unsigned int out_field:1;	/* 0:frame,1-field */
+		} b;
+	} cur_status; /* 0x1C */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int colkey:24;
+			unsigned int enable:1;
+			unsigned int invert:1;
+			unsigned int reserved:2;
+			unsigned int alpha:1;
+		} b;
+	} cur_color_key; /* 0x20 */
+
+	unsigned int reserved[3];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int rgb:1;
+			unsigned int yuv422:1;
+		} b;
+	} dvo_pix; /* 0x30 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int delay:14;
+			unsigned int inv:1;
+		} b;
+	} dvo_dly_sel; /* 0x34 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int cur_enable:1;
+			unsigned int mem_enable:1;
+			unsigned int reserved:7;
+			unsigned int err_sts:1;
+			unsigned int reserved2:6;
+			unsigned int cur_sts:1;
+			unsigned int mem_sts:1;
+		} b;
+	} interrupt; /* 0x38 */
+
+	unsigned int dvo_blank_data;
+	unsigned int dirpath; /* 0x40 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int v:8;
+			unsigned int u:8;
+			unsigned int y:8;
+		} b;
+	} saturation; /* 0x44 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int format:1; /* 0:YCbCr, 1:RGB */
+		} b;
+	} saturation_enable; /* 0x48 */
+
+	unsigned int reserved2[13];
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int reserved:7;
+			unsigned int h264:1;
+		} b;
+	} mif; /* 0x80 */
+
+	unsigned int colfmt; /* 0x84, 0:422,1:420 */
+	unsigned int srcfmt; /* 0x88, 0:frame,1:field */
+	unsigned int dstfmt; /* 0x8C, 0:frame,1:field */
+	unsigned int ysa;	/* 0x90 */
+	unsigned int csa;
+	unsigned int pixwid;
+	unsigned int bufwid;
+	unsigned int vcrop;	/* 0xA0 */
+	unsigned int hcrop;
+	unsigned int fhi;
+	unsigned int colfmt2;	/* 0xAC, 1-444,other refer 0x84 */
+	unsigned int ysa2;	/* 0xB0 */
+	unsigned int csa2;
+	union {
+		unsigned int val;
+		struct {
+			unsigned int req_num:8;	/* Y & RGB */
+			unsigned int req_num_c:8;	/* C */
+			unsigned int frame_enable:1;
+		} b;
+	} mif_frame_mode; /* 0xB8 */
+
+	unsigned int reserved3[10];
+	union {
+		unsigned int val;
+		struct {
+			unsigned int update:1;
+			unsigned int reserved:7;
+			unsigned int level:1;	/* 0:level 1, 1:level2 */
+		} b;
+	} sts; /* 0xE4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int fixed:1;	/* 0-top, 1-bottom */
+			unsigned int enable:1;
+		} b;
+	} swfld; /* 0xE8 */
+
+	unsigned int reserved4[5];
+	/* base2 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int reserved:7;
+			unsigned int mode:1; /* 0-frame,1-field */
+		} b;
+	} tg_enable; /* 0x100 */
+
+	unsigned int read_cyc;
+	unsigned int h_allpxl;
+	unsigned int v_allln;
+	unsigned int actln_bg; /* 0x110 */
+	unsigned int actln_end;
+	unsigned int actpx_bg;
+	unsigned int actpx_end;
+	unsigned int vbie_line; /* 0x120 */
+	unsigned int pvbi_line;
+	unsigned int hdmi_vbisw;
+	unsigned int hdmi_hsynw;
+	union {
+		unsigned int val;
+		struct {
+			unsigned int offset:12;
+			unsigned int reserved:4;
+			unsigned int field_invert:1;
+		} b;
+	} vsync_offset; /* 0x130 */
+
+	unsigned int field_status; /* 0x134, 1-BOTTOM,0-TOP */
+	unsigned int reserved5[1]; /* 0x138 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:3; /* 011-frame packing progressive
+				format,111-frame packing interlace format */
+			unsigned int inv_filed_polar:1;
+			unsigned int blank_value:16;
+			unsigned int reserved:11;
+			unsigned int addr_sel:1; /* in frame packing
+							interlace mode */
+		} b;
+	} hdmi_3d; /* 0x13C */
+
+	unsigned int reserved5_2[2];
+	union {
+		unsigned int val;
+		struct {
+			unsigned int outwidth:1; /* 0-24bit,1-12bit */
+			unsigned int hsync_polar:1; /* 0-act high,1-act low */
+			unsigned int enable:1;
+			unsigned int vsync_polar:1; /* 0-act high,1-act low */
+			unsigned int reserved:4;
+			unsigned int rgb_swap:2; /* 0-RGB[7:0],1-RGB[0:7],
+							2-BGR[7:0],3-BGR[0:7] */
+			unsigned int reserved2:6;
+			unsigned int blk_dis:1;	/* 0-Blank Data,
+						1-Embeded sync CCIR656 */
+		} b;
+	} dvo_set; /* 0x148 */
+
+	unsigned int reserved6;
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int reserved1:7;
+			unsigned int mode:1;
+			unsigned int reserved2:7;
+			unsigned int inversion:1;
+		} b;
+	} cb_enable; /* 0x150 */
+
+	unsigned int reserved7;
+	unsigned int h_allpxl2;
+	unsigned int v_allln2;
+	unsigned int actln_bg2;	/* 0x160 */
+	unsigned int actln_end2;
+	unsigned int actpx_bg2;
+	unsigned int actpx_end2;
+	unsigned int vbie_line2; /* 0x170 */
+	unsigned int pvbi_line2;
+	unsigned int hdmi_vbisw2;
+	unsigned int hdmi_hsynw2;
+	union {
+		unsigned int val;
+		struct {
+			unsigned int outwidth:1; /* 0-24bit,1-12bit */
+			unsigned int hsync_polar:1; /* 0-act high,1-act low */
+			unsigned int enable:1;
+			unsigned int vsync_polar:1; /* 0-act high,1-act low */
+		} b;
+	} lvds_ctrl; /* 0x180 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pix:2; /* 0-YUV444,1-RGB,2-YUV422,3-RGB */
+		} b;
+	} lvds_ctrl2; /* 0x184 */
+
+	unsigned int reserved_dac[12];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int praf:8;
+			unsigned int pbaf:8;
+			unsigned int yaf:8;
+		} b;
+	} contrast; /* 0x1B8 */
+
+	unsigned int brightness;
+	unsigned int dmacsc_coef0; /* 0x1C0 */
+	unsigned int dmacsc_coef1;
+	unsigned int dmacsc_coef2;
+	unsigned int dmacsc_coef3;
+	unsigned int dmacsc_coef4; /* 0x1D0 */
+	unsigned int reserved8;
+	unsigned int dmacsc_coef5;
+	unsigned int dmacsc_coef6;
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:1;	/* 1: YUV2RGB, 0: RGB2YUV */
+			unsigned int clamp:1;	/* 0:Y,1:Y-16 */
+		} b;
+	} csc_mode; /* 0x1E0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int dvo:1;
+			unsigned int vga:1;
+			unsigned int reserved1:1;
+			unsigned int dac_clkinv:1;
+			unsigned int blank_zero:1;
+			unsigned int disp:1;
+			unsigned int lvds:1;
+			unsigned int hdmi:1;
+			unsigned int rgb_mode:2; /*0-YUV,1-RGB24,2-1555,3-565*/
+		} b;
+	} yuv2rgb; /* 0x1E4 */
+
+	unsigned int h264_input_en;	/* 0x1E8 */
+	unsigned int reserved9;
+	unsigned int lvds_clkinv;	/* 0x1F0 */
+	unsigned int hscale_up;		/* 0x1F4 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:3; /* 0:888,1:555,2:666,3:565,4:ori */
+			unsigned int reserved:5;
+			unsigned int ldi:1; /* 0:shift right,1:shift left */
+		} b;
+	} igs_mode; /* 0x1F8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:3; /* 0:888,1:555,2:666,3:565,4:ori */
+			unsigned int reserved:5;
+			unsigned int ldi:1; /* 0:shift right,1:shift left */
+		} b;
+	} igs_mode2; /* 0x1FC */
+};
+
+/* GOVRH */
+#define REG_GOVRH_BASE1_BEGIN		(GOVRH_BASE1_ADDR+0x00)
+#define REG_GOVRH_YSA			(GOVRH_BASE1_ADDR+0x90)
+#define REG_GOVRH_CSA			(GOVRH_BASE1_ADDR+0x94)
+#define REG_GOVRH_BASE1_END		(GOVRH_BASE1_ADDR+0xe8)
+#define REG_GOVRH_BASE2_BEGIN		(GOVRH_BASE2_ADDR+0x00)
+#define REG_GOVRH_BASE2_END		(GOVRH_BASE2_ADDR+0xFC)
+
+/* GOVRH2 */
+#define REG_GOVRH2_BASE1_BEGIN		(GOVRH2_BASE1_ADDR+0x00)
+#define REG_GOVRH2_YSA			(GOVRH2_BASE1_ADDR+0x90)
+#define REG_GOVRH2_CSA			(GOVRH2_BASE1_ADDR+0x94)
+#define REG_GOVRH2_BASE1_END		(GOVRH2_BASE1_ADDR+0xe8)
+#define REG_GOVRH2_BASE2_BEGIN		(GOVRH2_BASE2_ADDR+0x00)
+#define REG_GOVRH2_BASE2_END		(GOVRH2_BASE2_ADDR+0xFC)
+
+#endif /* WMT_GOVRH_REG_H */
diff --git a/drivers/video/wmt/hw/wmt-hdmi-reg.h b/drivers/video/wmt/hw/wmt-hdmi-reg.h
new file mode 100755
index 00000000..c0650555
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-hdmi-reg.h
@@ -0,0 +1,379 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-hdmi-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_HDMI_REG_H
+#define WMT_HDMI_REG_H
+
+#define WMT_FTBLK_HDMI
+
+#define HDMI_BASE_ADDR	(HDMI_TRANSMITTE_BASE_ADDR + 0xC000)
+
+struct hdmi_base1_regs {
+	unsigned int _100_11c[8];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int eeprom_reset:1;
+			unsigned int encode_enable:1;
+			unsigned int hden:1;
+			unsigned int eess_enable:1;
+			unsigned int verify_pj_enable:1;
+			unsigned int i2c_enable:1;
+			unsigned int auth_test_key:1;
+			unsigned int _7:1;
+			unsigned int cipher_1_1:1;
+			unsigned int _9_11:3;
+			unsigned int preamble:4;
+			unsigned int _16_19:4;
+			unsigned int encode_window:3;
+		} b;
+	} ctrl; /* 0x120 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int _0_6:7;
+			unsigned int force_exit_fsm:1;
+			unsigned int key_read_word:7;
+			unsigned int i2c_sw_reset:1;
+			unsigned int i2c_clk_divider:16;
+		} b;
+	} i2c_ctrl; /* 0x124 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int wr_data:8;
+			unsigned int rd_data:8;
+			unsigned int sw_start_req:1;
+			unsigned int sw_stop_req:1;
+			unsigned int wr_data_avail:1;
+			unsigned int i2c_status:1; /* 0-not using,1-in using */
+			unsigned int cp_key_req:1;
+			unsigned int cp_key_read:1;
+			unsigned int cp_key_last:1;
+			unsigned int _23:1;
+			unsigned int cp_src_sel:1;
+			unsigned int sw_read:1;
+			unsigned int sw_i2c_req:1;
+			unsigned int ksv_list_avail:1;
+			unsigned int ksv_verify_done:1;
+		} b;
+	} i2c_ctrl2; /* 0x128 */
+
+	unsigned int _12c_27c[85];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int reset:1;
+			unsigned int enable:1;
+			unsigned int _2_5:4;
+			unsigned int dvi_mode_enable:1;
+			unsigned int output_format:2; /* 0-RGB,
+							1-YUV444,2-YUV422 */
+			unsigned int convert_yuv422:1;
+			unsigned int hsync_low_active:1; /* 0-active hi,1-lo */
+			unsigned int dbg_bus_select:1; /* 0-before,1-after */
+			unsigned int _12:1;
+			unsigned int vsync_low_active:1; /* 0-active hi,1-lo */
+			unsigned int _14_15:2;
+			unsigned int cp_delay:7;
+			unsigned int _23:1;
+			unsigned int vsync_enable:3; /* write only */
+			unsigned int state_machine_status:5;
+		} b;
+	} general_ctrl; /* 0x280 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int select:1; /* 0-fifo1,1-fifo2 */
+			unsigned int fifo1_rdy:1; /* Info frame FIFO 1 ready */
+			unsigned int fifo2_rdy:1; /* Info frame FIFO 2 ready */
+			unsigned int _3:1;
+			unsigned int fifo1_addr:4; /* FIFO 1 start address */
+			unsigned int fifo1_len:5; /* FIFO 1 length */
+			unsigned int _13_15:3;
+			unsigned int fifo2_addr:4; /* FIFO 2 start address */
+			unsigned int fifo2_len:5; /* FIFO 2 length */
+			unsigned int _25_27:3;
+			unsigned int horiz_blank_max_pck:3; /* Max packets
+						that insert during HSYNC */
+		} b;
+	} infoframe_ctrl; /* 0x284 */
+	unsigned int _288_290[3];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pck_insert_reset:1;
+			unsigned int pck_insert_enable:1;
+			unsigned int avmute_set_enable:1;
+			unsigned int avmute_clr_enable:1;
+			unsigned int insert_delay:12;
+			unsigned int _16_29:14;
+			unsigned int pixel_repetition:2; /* 0-none,1-2x,2-4x */
+		} b;
+	} aud_insert_ctrl; /* 0x294 */
+
+	unsigned int _298;
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int _0_7:8;
+			unsigned int acr_ratio:20;
+			unsigned int acr_enable:1;
+			unsigned int mute:1;
+		} b;
+	} aud_ratio; /* 0x29c */
+
+	unsigned int aud_enable; /* 0x2a0 */
+	unsigned int _2a4_2a8[2];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int sub_packet:4;
+			unsigned int spflat:4;
+			unsigned int _2ch_eco:1;
+			unsigned int _9:1;
+			unsigned int layout:1; /* 0-2 channel,1-8 channel */
+			unsigned int pwr_saving:1; /* 0-normal,1-power saving */
+		} b;
+	} aud_mode; /* 0x2ac */
+
+	unsigned int _2b0_38c[56];
+	unsigned int aud_chan_status0; /* 0x390 */
+	unsigned int aud_chan_status1; /* 0x394 */
+	unsigned int aud_chan_status2; /* 0x398 */
+	unsigned int aud_chan_status3; /* 0x39c */
+	unsigned int aud_chan_status4; /* 0x3a0 */
+	unsigned int aud_chan_status5; /* 0x3a4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int n_20bits:20;
+			unsigned int cts_low_12bits:12;
+		} b;
+	} aud_sample_rate1; /* 0x3a8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int cts_hi_8bits:8;
+			unsigned int _8_27:20;
+			unsigned int aipclk_rate:2; /* 0-N/2,1-N,2-N/4,3-N*2 */
+			unsigned int cts_select:1; /* 0-auto,1-fixed from reg */
+		} b;
+	} aud_sample_rate2; /* 0x3ac */
+
+	unsigned int _3b0_3bc[4];
+	unsigned int wr_fifo_addr[9]; /* 0x3c0 - 0x3e0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int wr_strobe:1;
+			unsigned int rd_strobe:1;
+			unsigned int _2_7:6;
+			unsigned int addr:8;
+		} b;
+	} fifo_ctrl; /* 0x3e4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int ch0_data:10;
+			unsigned int ch0_enable:1;
+			unsigned int _11_15:5;
+			unsigned int ch1_data:10;
+			unsigned int ch1_enable:1;
+		} b;
+	} channel_test; /* 0x3e8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int ch2_data:10;
+			unsigned int ch2_enable:1;
+			unsigned int _11_15:5;
+			unsigned int in_enable:1;
+			unsigned int out_enable:1;
+			unsigned int _18_23:6;
+			unsigned int in_sts:1;
+			unsigned int out_sts:1;
+			unsigned int _26_30:5;
+			unsigned int sts:1; /* 0-plug out,1-plug in */
+		} b;
+	} hotplug_detect; /* 0x3ec */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int sample:8;
+			unsigned int _8_15:8;
+			unsigned int detect:9;
+		} b;
+	} hotplug_debounce; /* 0x3f0 */
+
+	unsigned int _3f4;
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int test_enable:1;
+			unsigned int test_format:1;
+			unsigned int _2_9:8;
+			unsigned int infoframe_sram_enable:1;
+			unsigned int _11_15:5;
+			unsigned int clock_select:1; /* 0-clk 1x, 1-clk 2x */
+		} b;
+	} tmds_ctrl; /* 0x3f8 */
+
+	unsigned int _3fc;
+	unsigned int rd_fifo_addr[9]; /* 0x400 - 0x420 */
+};
+
+struct hdmi_base2_regs {
+	union {
+		unsigned int val;
+		struct {
+			unsigned int inv_clk:1;
+			unsigned int _1_3:3;
+			unsigned int dual_channel:1;
+			unsigned int _5_7:3;
+			unsigned int test:4;
+			unsigned int _12_18:7;
+			unsigned int internal_ldo:1;
+		} b;
+	} status; /* 0x00 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int drv_pdmode:1;
+			unsigned int _1:1;
+			unsigned int vbg_sel:2;
+			unsigned int _4_7:4;
+			unsigned int pd:1;
+			unsigned int tre_en:2;
+			unsigned int _11:1;
+			unsigned int pllck_dly:3;
+			unsigned int _15:1;
+			unsigned int pll_cpset:2;
+			unsigned int pll_r_f:1;
+		} b;
+	} test; /* 0x04 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int update:1;
+			unsigned int _1_7:7;
+			unsigned int level:1;
+		} b;
+	} level; /* 0x08 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int bpp_type:3; /* 0-888,1-555,2-666,3-565 */
+			unsigned int _3_7:5;
+			unsigned int ldi_shift_left:1; /* 0-right,1-left */
+		} b;
+	} igs; /* 0x0c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int out_data_12:1; /* 0-24bit,1-12bit */
+			unsigned int hsync_polar_lo:1; /* 0-act hi,1-act low */
+			unsigned int dvo_enable:1;
+			unsigned int vsync_polar_lo:1; /* 0-act hi,1-act low */
+		} b;
+	} set; /* 0x10 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int colfmt_rgb:1;/* 0-RGB or YUV444,1-YUV422 */
+			unsigned int colfmt_yuv422:1;
+		} b;
+	} set2; /* 0x14 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pll_ready:1;
+			unsigned int _1_7:7;
+			unsigned int rsen:1;
+		} b;
+	} detect; /* 0x18 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pll_tsync:1;
+			unsigned int tp2s_type:1;
+			unsigned int div_sel:2;
+			unsigned int pd_v2i:1;
+			unsigned int vco_sx:1;
+			unsigned int vco_mode:1;
+			unsigned int _7:1;
+			unsigned int vsref_sel:2;
+			unsigned int mode:1;
+			unsigned int pd_l2ha:1;
+			unsigned int pd_l2hb:1;
+			unsigned int l2ha_hsen:1;
+			unsigned int resa_en:1;
+			unsigned int resa_s:1;
+			unsigned int pll_lpfs:2;
+		} b;
+	} test2; /* 0x1c */
+
+	unsigned int test3; /* 0x20 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int _0_15:16;
+			unsigned int reset_pll:1;
+		} b;
+	} dftset2; /* 0x24 */
+};
+
+#define REG_HDMI_BEGIN	(HDMI_BASE_ADDR + 0x100)
+#define REG_HDMI_END	(HDMI_BASE_ADDR + 0x420)
+#define REG_HDMI2_BEGIN	(HDMI_BASE2_ADDR + 0x00)
+#define REG_HDMI2_END	(HDMI_BASE2_ADDR + 0x28)
+
+#ifndef HDMI_C
+extern HW_REG struct hdmi_base1_regs *hdmi_regs1;
+extern HW_REG struct hdmi_base2_regs *hdmi_regs2;
+#endif
+#endif /* WMT_HDMI_REG_H */
+
diff --git a/drivers/video/wmt/hw/wmt-lvds-reg.h b/drivers/video/wmt/hw/wmt-lvds-reg.h
new file mode 100755
index 00000000..0a6e616c
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-lvds-reg.h
@@ -0,0 +1,129 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-lvds-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_LVDS_REG_H
+#define WMT_LVDS_REG_H
+
+#define WMT_FTBLK_LVDS
+
+struct lvds_base_regs {
+	union {
+		unsigned int val;
+		struct {
+			unsigned int inv_clk:1;
+			unsigned int _01_03:3;
+			unsigned int dual_channel:1;
+			unsigned int _05_07:3;
+			unsigned int test:4;
+		} b;
+	} status; /* 0x00 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int drv_pdmode:1;
+			unsigned int _01:1;
+			unsigned int vbg_sel:2;
+			unsigned int _04_07:4;
+			unsigned int pd:1;
+			unsigned int tre_en:2;
+			unsigned int _11:1;
+			unsigned int pllck_dly:3;
+			unsigned int _15:1;
+			unsigned int pll_cpset:2;
+			unsigned int pll_r_f:1;
+		} b;
+	} test; /* 0x04 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int update:1;
+			unsigned int _01_07:7;
+			unsigned int level:1;
+		} b;
+	} level; /* 0x08 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int bpp_type:3; /* 0-888,1-555,2-666,3-565 */
+			unsigned int _03_07:5;
+			unsigned int ldi_shift_left:1; /* 0-shift right,1-left*/
+		} b;
+	} igs; /* 0x0c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int out_data_12:1; /* 0-24bit,1-12bit */
+			unsigned int hsync_polar_lo:1; /* 0-active hi,1-low */
+			unsigned int dvo_enable:1;
+			unsigned int vsync_polar_lo:1; /* 0-active hi,1-low */
+		} b;
+	} set; /* 0x10 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int colfmt:2; /* 0-YUV444,1/3-RGB,2-YUV422 */
+		} b;
+	} set2; /* 0x14 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pll_ready:1;
+			unsigned int _01_07:7;
+			unsigned int rsen:1;
+		} b;
+	} detect; /* 0x18 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int pll_tsync:1;
+			unsigned int tp2s_type:1;
+			unsigned int div_sel:2;
+			unsigned int pd_v2i:1;
+			unsigned int vco_sx:1;
+			unsigned int vco_mode:1;
+			unsigned int _07:1;
+			unsigned int vsref_sel:2;
+			unsigned int mode:1;
+			unsigned int pd_l2ha:1;
+			unsigned int pd_l2hb:1;
+			unsigned int l2ha_hsen:1;
+			unsigned int resa_en:1;
+			unsigned int resa_s:1;
+			unsigned int pll_lpfs:2;
+		} b;
+	} test2; /* 0x1c */
+};
+
+#define REG_LVDS_BEGIN	(LVDS_BASE_ADDR + 0x00)
+#define REG_LVDS_END	(LVDS_BASE_ADDR + 0x1C)
+#ifndef LVDS_C
+extern struct lvds_base_regs *lvds_regs;
+#endif
+#endif /* WMT_LVDS_REG_H */
diff --git a/drivers/video/wmt/hw/wmt-scl-reg.h b/drivers/video/wmt/hw/wmt-scl-reg.h
new file mode 100755
index 00000000..773fad96
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-scl-reg.h
@@ -0,0 +1,543 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-scl-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_SCL_REG_H
+#define WMT_SCL_REG_H
+
+/* feature */
+#define WMT_FTBLK_SCL
+
+/* constant */
+#define WMT_SCL_RCYC_MIN	0	/* 1T */
+#define WMT_SCL_H_DIV_MAX	8192
+#define WMT_SCL_V_DIV_MAX	8192
+#define WMT_SCL_FB_WIDTH_MAX	8192
+
+#define WMT_SCL_SCALE_DST_H_MAX	1920	/* bypass no limit */
+
+struct scl_base1_regs {
+	union {
+		unsigned int val;
+		struct {
+			unsigned int alu_enable:1;
+		} b;
+	} en; /* 0x0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int reg_update:1;
+		} b;
+	} upd; /* 0x04 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int reg_level:1;
+		} b;
+	} sel; /* 0x08 */
+
+	unsigned int _0c_38[12];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int hxwidth:13;
+		} b;
+	} hxwidth; /* 0x3c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mif_en:1;
+			unsigned int _01_03:3;
+			unsigned int rgb_mode:2; /* 0-YUV,1-RGB565,3-RGB32 */
+			unsigned int _06_07:2;
+			unsigned int _420c_fmt:1; /* 0-frame,1-field */
+			unsigned int vfmt:3; /* 0-YUV422,1-YUV420,
+							2-YUV444,4-RGB32 */
+			unsigned int h264_fmt:1; /* 0-MPEG,1-H264 */
+			unsigned int _13_15:3;
+			unsigned int iofmt:1; /* 0-frame,1-field */
+			unsigned int _17_23:7;
+			unsigned int color_en:1; /* 0-disable,1-enable */
+			unsigned int color_wide:1; /* 0-Normal,1-Wider */
+			unsigned int color_inv:1; /* 0-Normal,1-Opposite color*/
+		} b;
+	} r2_ctl; /* 0x40 */
+
+	unsigned int r2_ysa; /* 0x44 */
+	unsigned int r2_csa; /* 0x48 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int fbw:13; /* frame buffer width pixel */
+			unsigned int _13_15:3;
+			unsigned int lnsize:13; /* line width pixel */
+		} b;
+	} r2_h_size; /* 0x4c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int hcrop:13;
+			unsigned int _13_15:3;
+			unsigned int vcrop:13;
+		} b;
+	} r2_crop; /* 0x50 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int src:2; /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */
+			unsigned int _02_07:6;
+			unsigned int dst:2; /* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */
+			unsigned int _09_15:6;
+			unsigned int swap:1; /* 0-(alpha,1-a),1:(1-a,alpha) */
+		} b;
+	} alpha_md; /* 0x54 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int src_fixed:8;
+			unsigned int dst_fixed:8;
+		} b;
+	} alpha_fxd; /* 0x58 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int _01_07:7;
+			unsigned int from:1; /* 0-RMIF1,1-RMIF2 */
+			unsigned int _09_15:7;
+			unsigned int comp:2; /* 0-888,1-777,2-666,3-555 */
+			unsigned int _17_23:7;
+			unsigned int mode:3; /* (Non-Hit,Hit):0/1-(alpha,alpha),
+				2-(alpha,pix1),3-(pix1,alpha),4-(alpha,pix2),
+				5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */
+		} b;
+	} alpha_colorkey; /* 0x5c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int r:8;
+			unsigned int g:8;
+			unsigned int b:8;
+		} b;
+	} alpha_colorkey_rgb; /* 0x60 */
+
+	unsigned int _64_6c[3];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int vxwidth:13;
+			unsigned int _13_15:3;
+			unsigned int dst_vxwidth:13;
+		} b;
+	} vxwidth; /* 0x70 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int h:1;
+			unsigned int _01_15:15;
+			unsigned int v:1;
+		} b;
+	} sclup_en; /* 0x74 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int thr:13;
+			unsigned int _13_15:3;
+			unsigned int substep:13;
+		} b;
+	} vscale1; /* 0x78 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int substepcnt:13;
+			unsigned int _13_15:3;
+			unsigned int step:13;
+		} b;
+	} vscale2; /* 0x7c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int stepcnt:17;
+		} b;
+	} vscale3; /* 0x80 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int thr:13;
+			unsigned int _13_15:3;
+			unsigned int substep:13;
+		} b;
+	} hscale1; /* 0x84 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int substepcnt:13;
+			unsigned int _13_15:3;
+			unsigned int step:13;
+		} b;
+	} hscale2; /* 0x88 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int stepcnt:17;
+		} b;
+	} hscale3; /* 0x8c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int y_req_num:8;
+			unsigned int c_req_num:8;
+		} b;
+	} r_req_num; /* 0x90 */
+
+	unsigned int scldw; /* 0x94 */ /* (VPU path, scale dn)
+					0 - bilinear mode, quality better */
+	unsigned int sw_426; /* 0x98 */ /* 1-follow 426, 0-437 */
+	unsigned int vbypass; /* 0x9c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int _1_3:3;
+			unsigned int err_off:1; /*disable TG_EN in tg timeout*/
+			unsigned int _5_7:3;
+			unsigned int watchdog_enable:1;
+			unsigned int _9_15:7;
+			unsigned int rdcyc:8;
+			unsigned int oneshot:1; /* sacling complete will set
+							SCL tg enable to 0 */
+		} b;
+	} tg_ctl; /* 0xa0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int h_allpixel:13;
+			unsigned int _13_15:3;
+			unsigned int v_allline:13;
+		} b;
+	} tg_total; /* 0xa4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int v_actbg:8;
+			unsigned int _8_15:8;
+			unsigned int v_actend:13;
+		} b;
+	} tg_v_active; /* 0xa8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int h_actbg:10;
+			unsigned int _10_15:6;
+			unsigned int h_actend:13;
+		} b;
+	} tg_h_active; /* 0xac */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int vbie:7;
+			unsigned int _7:1;
+			unsigned int pvbi:5;
+		} b;
+	} tg_vbi; /* 0xb0 */
+
+	unsigned int tg_watchdog; /* 0xb4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int tgerr:1;
+		} b;
+	} tg_sts; /* 0xb8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+		} b;
+	} tg_govw; /* 0xbc */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mif_enable:1; /*0:Disable, 1:Enable */
+			unsigned int _1_3:3;
+			unsigned int rgb_mode:2; /*0:YC,1:RGB565,3:RGB32 */
+			unsigned int _6_7:2;
+			unsigned int src_disp_fmt:1; /*420C 0:Frame, 1:Field */
+			unsigned int yuv:2; /*0:422,1:420,2:444*/
+			unsigned int rgb:1; /*0:YCbCr, 1:RGB32 */
+			unsigned int h264:1; /*0:MPEG, 1:H264 */
+			unsigned int _13_15:3;
+			unsigned int field:1; /*0:Frame, 1:Field */
+			unsigned int _17_23:7;
+			unsigned int colorbar_enable:1;
+			unsigned int colorbar_mode:1;
+			unsigned int colorbar_inv:1;
+		} b;
+	} r_ctl; /* 0xc0 */
+
+	unsigned int r_ysa; /* 0xc4 */
+	unsigned int r_csa; /* 0xc8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int fb_w:13;
+			unsigned int _13_15:3;
+			unsigned int pix_w:13;
+		} b;
+	} r_h_size; /* 0xcc */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int hcrop:13;
+			unsigned int _13_15:3;
+			unsigned int vcrop:13;
+		} b;
+	} r_crop; /* 0xd0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int thr:4;
+			unsigned int _4_7:4;
+			unsigned int r1_mif_err:1;
+			unsigned int r2_mif_err:1;
+		} b;
+	} r_fifo_ctl; /* 0xd4 */
+
+	unsigned int _d8_dc[2];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mif_enable:1;
+			unsigned int _1_7:7;
+			unsigned int yuv:1; /* 0-444,1-422 */
+			unsigned int rgb:1; /* 0-YC,1-RGB32 */
+		} b;
+	} w_ctl; /* 0xe0 */
+
+	unsigned int w_ysa; /* 0xe4 */
+	unsigned int w_csa; /* 0xe8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int fb_w:13;
+			unsigned int _13_15:3;
+			unsigned int pxl_w:13;
+		} b;
+	} w_y_time; /* 0xec */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int fb_w:13;
+			unsigned int _13_15:3;
+			unsigned int pxl_w:12;
+		} b;
+	} w_c_time; /* 0xf0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mif_c_err:1;
+			unsigned int _1_7:7;
+			unsigned int mif_y_err:1;
+			unsigned int _9_15:7;
+			unsigned int mif_rgb_err:1;
+		} b;
+	} w_ff_ctl; /* 0xf4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mif_c_err:1;
+			unsigned int mif_y_err:1;
+			unsigned int mif_rgb_err:1;
+			unsigned int _3_7:5;
+			unsigned int r2_mif_enable:1;
+			unsigned int r1_mif_enable:1;
+			unsigned int _10_15:6;
+			unsigned int tg_err:1;
+		} b;
+	} w_int_en; /* 0xf8 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int h:1;
+			unsigned int _1_7:7;
+			unsigned int v:1;
+		} b;
+	} true_bilinear; /* 0xfc */
+};
+
+struct scl_base2_regs {
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:1; /* 0-RGB2YC,1-YC2RGB */
+			unsigned int _01_07:7;
+			unsigned int clamp_enable:1; /* clamp to 16-235 */
+			unsigned int _09_15:7;
+			unsigned int enable:1;
+		} b;
+	} csc_ctl; /* 0x0 */
+
+	unsigned int csc1; /* 0x4 */
+	unsigned int csc2; /* 0x8 */
+	unsigned int csc3; /* 0xc */
+	unsigned int csc4; /* 0x10 */
+	unsigned int csc5; /* 0x14 */
+	unsigned int csc6; /* 0x18 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int enable:1;
+			unsigned int _01_07:7;
+			unsigned int data:8;
+		} b;
+	} argb_alpha; /* 0x1c */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:2; /* 0-888,1-555,2-666,3-565 */
+		} b;
+	} igs; /* 0x20 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int mode:1; /* 0-CCIR/ITU-601 */
+			unsigned int _01_07:7;
+			unsigned int clamp:1; /* 0-direct,1-16-235 */
+			unsigned int _09_15:7;
+			unsigned int enable:1;
+		} b;
+	} r2_csc; /* 0x24 */
+
+	unsigned int r2_csc1; /* 0x28 */
+	unsigned int r2_csc2; /* 0x2c */
+	unsigned int r2_csc3; /* 0x30 */
+	unsigned int r2_csc4; /* 0x34 */
+	unsigned int r2_csc5; /* 0x38 */
+	unsigned int r2_csc6; /* 0x3c */
+	unsigned int _40_9c[24];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int h:1;
+			unsigned int _01_07:7;
+			unsigned int v:1;
+		} b;
+	} recursive_mode; /* 0xa0 */
+
+	unsigned int _a4_bc[7];
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int deblock:1;
+			unsigned int field_deflicker:1;
+			unsigned int frame_deflicker:1;
+		} b;
+	} field_mode; /* 0xc0 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int layer1_boundary:8;
+			unsigned int layer2_boundary:8;
+		} b;
+	} dblk_threshold; /* 0xc4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int condition:1; /* 0-up or down,1-up & down */
+			unsigned int _01_07:7;
+			unsigned int y_thd:8;
+			unsigned int c_thd:8;
+		} b;
+	} field_flicker; /* 0xc8 */
+	union {
+		unsigned int val;
+		struct {
+			unsigned int rgb:1; /* 0-Y,1-RGB */
+			unsigned int _01_07:7;
+			unsigned int sampler:5; /* 2^x */
+			unsigned int _13_15:3;
+			unsigned int scene_chg_thd:8;
+		} b;
+	} frame_flicker; /* 0xcc */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int rdcyc_1t:1;
+		} b;
+	} readcyc_1t; /* 0xd0 */
+
+	unsigned int _d4_e0[4];
+};
+
+#define REG_SCL_BASE1_BEGIN	(SCL_BASE_ADDR + 0x00)
+#define REG_SCL_BASE1_END	(SCL_BASE_ADDR + 0xFC)
+#define REG_SCL_BASE2_BEGIN	(SCL_BASE2_ADDR + 0x00)
+#define REG_SCL_BASE2_END	(SCL_BASE2_ADDR + 0xE0)
+
+#ifndef SCL_C
+extern HW_REG struct scl_base1_regs *scl_regs1;
+extern HW_REG struct scl_base2_regs *scl_regs2;
+#endif
+#endif /* WMT_SCL_REG_H */
diff --git a/drivers/video/wmt/hw/wmt-vpp-hw.h b/drivers/video/wmt/hw/wmt-vpp-hw.h
new file mode 100755
index 00000000..599ebe03
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-vpp-hw.h
@@ -0,0 +1,137 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-vpp-hw.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_VPP_HW_H
+#define WMT_VPP_HW_H
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+/*
+* Product ID / Project ID
+* 84xx series: 8420/3300, 8430/3357, 8435/3437
+* 85xx series: 8500/3400, 8510/3426, 8520/3429
+*/
+/* 84xx series, (1-100) with VDU & DSP */
+#define VIA_PID_8420	10	/* 3300 */
+#define VIA_PID_8430	12	/* 3357 */
+#define WMT_PID_8435	14	/* 3437 */
+#define WMT_PID_8440	16	/* 3451 */
+#define WMT_PID_8425	18	/* 3429 */
+#define WMT_PID_8710	20	/* 3445 */
+#define WMT_PID_8950	22	/* 3481 */
+#define WMT_PID_8980	24	/* 3498 */
+
+/* 85xx series, (101-200) */
+#define VIA_PID_8500	110	/* 3400 */
+#define WMT_PID_8505	111
+#define WMT_PID_8510	112	/* 3426* */
+
+#define WMT_PID_8950_A	1
+
+/* current pid */
+#define WMT_CUR_PID	WMT_PID_8980
+#define WMT_SUB_PID	0
+
+/* #define WMT_SUB_PID	WMT_PID_8505 */
+#ifndef WMT_SUB_PID
+	#define WMT_SUB_PID	0
+#endif
+
+/* VPP interrupt map to irq */
+#define VPP_IRQ_SCL_FINISH	IRQ_VPP_IRQ0
+#define VPP_IRQ_SCL		IRQ_VPP_IRQ1
+#define VPP_IRQ_SCL444_TG	IRQ_VPP_IRQ2
+#define VPP_IRQ_VPPM		IRQ_VPP_IRQ3
+#define VPP_IRQ_GOVW_TG		IRQ_VPP_IRQ4
+#define VPP_IRQ_GOVW		IRQ_VPP_IRQ5
+#define VPP_IRQ_GOVM		IRQ_VPP_IRQ6
+#define VPP_IRQ_GE		IRQ_VPP_IRQ7
+#define VPP_IRQ_GOVRH_TG	IRQ_VPP_IRQ8	/* PVBI or VBIS or VBIE */
+#define VPP_IRQ_DVO		IRQ_VPP_IRQ9
+#define VPP_IRQ_VID		IRQ_VPP_IRQ10
+#define VPP_IRQ_GOVR		IRQ_VPP_IRQ11	/* underrun & mif */
+#define VPP_IRQ_GOVRSD_TG	IRQ_VPP_IRQ12
+#define VPP_IRQ_VPU		IRQ_VPP_IRQ13
+#define VPP_IRQ_VPU_TG		IRQ_VPP_IRQ14
+#define VPP_IRQ_HDMI_CP		IRQ_VPP_IRQ15
+#define VPP_IRQ_HDMI_HPDH	IRQ_VPP_IRQ16
+#define VPP_IRQ_HDMI_HPDL	IRQ_VPP_IRQ17
+#define VPP_IRQ_GOVR_0		IRQ_VPP_IRQ18
+#define VPP_IRQ_GOVR_2		IRQ_VPP_IRQ19
+#define VPP_IRQ_CEC		IRQ_VPP_IRQ20
+#define VPP_IRQ_GOVR2_0		IRQ_VPP_IRQ21
+#define VPP_IRQ_GOVR2		IRQ_VPP_IRQ22
+#define VPP_IRQ_GOVR2_2		IRQ_VPP_IRQ23
+#define VPP_IRQ_DVO2		IRQ_VPP_IRQ24
+#define VPP_IRQ_GOVR2_TG	IRQ_VPP_IRQ25
+
+/* DVI I2C */
+#define VPP_DVI_I2C_DEFAULT	1 /* default i2c bus */
+#define VPP_DVI_I2C_SW_BIT	0x10 /* hw or sw i2c */
+#define VPP_DVI_I2C_ID_MASK	0x1F
+#define VPP_DVI_I2C_ID		g_vpp.dvi_i2c_no
+#define VPP_DVI_EDID_ID		(VPP_DVI_I2C_SW_BIT + 0x1) /* DVO EDID use
+								sw i2c bus 1 */
+
+/* vout */
+#define VPP_VOUT_INFO_NUM	5 /* linux fb or govr number */
+
+#define VPP_VOUT_NUM		2
+#define VPP_VOUT_ALL		0xFFFFFFFF
+#define VPP_VOUT_NUM_HDMI	0
+#define VPP_VOUT_NUM_LVDS	1
+#define VPP_VOUT_NUM_DVI	1
+
+#define WMT_FTBLK_VOUT_DVI
+#define WMT_FTBLK_VOUT_HDMI
+#define WMT_FTBLK_VOUT_LVDS
+
+/* hw parameter */
+#define VPP_DVI_INT_DEFAULT	0 /* default interrupt gpio */
+#define VPP_VOINT_NO		g_vpp.dvi_int_no
+#define VPP_UBOOT_COLFMT	VDO_COL_FMT_RGB_565
+#define VPP_FB_ADDR_ALIGN	64
+#define VPP_FB_WIDTH_ALIGN	64 /* hw should 4 byte align,android
+	framework 8 byte align modify by aksenxu VPU need 64bytes alignment
+	you need modify FramebufferNativeWindow::FramebufferNativeWindow
+	in android framework together */
+#define VPP_GOVR_DVO_DELAY_24	0x4036
+#define VPP_GOVR_DVO_DELAY_12	0x120
+
+/*-------------------- DEPENDENCY -------------------------------------*/
+#ifdef __KERNEL__
+#ifndef CONFIG_WMT_HDMI
+#undef WMT_FTBLK_VOUT_HDMI
+#endif
+#endif
+
+#include "wmt-vpp-reg.h"
+#include "wmt-govrh-reg.h"
+#include "wmt-lvds-reg.h"
+#ifdef WMT_FTBLK_VOUT_HDMI
+#include "wmt-hdmi-reg.h"
+#endif
+#include "wmt-scl-reg.h"
+#ifndef CONFIG_UBOOT
+#include "wmt-cec-reg.h"
+#endif
+#endif /* WMT_VPP_HW_H */
diff --git a/drivers/video/wmt/hw/wmt-vpp-reg.h b/drivers/video/wmt/hw/wmt-vpp-reg.h
new file mode 100755
index 00000000..b96e64db
--- /dev/null
+++ b/drivers/video/wmt/hw/wmt-vpp-reg.h
@@ -0,0 +1,132 @@
+/*++
+ * linux/drivers/video/wmt/hw/wmt-vpp-reg.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef WMT_VPP_REG_H
+#define WMT_VPP_REG_H
+
+#define VPP_DAC_SEL_TV		1
+#define VPP_DAC_SEL_VGA		0
+
+struct vppm_base_regs {
+	unsigned int _00; /* 0x00 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int _0_7:8;
+			unsigned int govrh_pvbi:1;
+			unsigned int govrh_vbis:1;
+			unsigned int govrh_vbie:1;
+			unsigned int _11:1;
+			unsigned int govrh2_pvbi:1;
+			unsigned int govrh2_vbis:1;
+			unsigned int govrh2_vbie:1;
+			unsigned int _15:1;
+			unsigned int scl_pvbi:1;
+			unsigned int scl_vbis:1;
+			unsigned int scl_vbie:1;
+			unsigned int _19:1;
+			unsigned int ge_tg:1;
+		} b;
+	} int_sts; /* 0x4 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int _0_7:8;
+			unsigned int govrh_pvbi:1;
+			unsigned int govrh_vbis:1;
+			unsigned int govrh_vbie:1;
+			unsigned int _11:1;
+			unsigned int govrh2_pvbi:1;
+			unsigned int govrh2_vbis:1;
+			unsigned int govrh2_vbie:1;
+			unsigned int _15:1;
+			unsigned int scl_pvbi:1;
+			unsigned int scl_vbis:1;
+			unsigned int scl_vbie:1;
+			unsigned int _19:1;
+			unsigned int ge_tg:1;
+		} b;
+	} int_en; /* 0x8 */
+
+	unsigned int watch_sel; /* 0x0C */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int scl:1;
+			unsigned int _1_7:7;
+			unsigned int vid:1;
+			unsigned int _9_15:7;
+			unsigned int ge:1;
+		} b;
+	} sw_reset1; /* 0x10 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int govrh:1;
+			unsigned int _1_3:3;
+			unsigned int lvds:1;
+			unsigned int _5_7:3;
+			unsigned int dvo:1;
+			unsigned int dvo2:1;
+			unsigned int _10_11:2;
+			unsigned int cec:1;
+		} b;
+	} sw_reset2; /* 0x14 */
+
+	unsigned int dac_sel; /* 0x18 */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int hdmi:1;
+			unsigned int _1_7:7;
+			unsigned int ddc:1;
+			unsigned int _9_15:7;
+			unsigned int hdmi2:1;
+		} b;
+	} sw_reset3; /* 0x1C */
+
+	union {
+		unsigned int val;
+		struct {
+			unsigned int disable:1;
+			unsigned int _1_7:7;
+			unsigned int csi_act_lane_sel:1; /*0-lane 0/1,1-2/3*/
+		} b;
+	} sscg; /* 0x20 */
+};
+
+#define REG_VPP_BEGIN		(VPP_BASE_ADDR + 0x00)
+#define REG_VPP_END		(VPP_BASE_ADDR + 0x28)
+
+#ifndef VPPM_C
+extern HW_REG struct vppm_base_regs *vppm_regs;
+#endif
+
+
+#endif /* WMT_VPP_REG_H */
+
diff --git a/drivers/video/wmt/lcd.h b/drivers/video/wmt/lcd.h
new file mode 100755
index 00000000..46925e9f
--- /dev/null
+++ b/drivers/video/wmt/lcd.h
@@ -0,0 +1,105 @@
+/*++
+ * linux/drivers/video/wmt/lcd.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef LCD_H
+/* To assert that only one occurrence is included */
+#define LCD_H
+/*-------------------- MODULE DEPENDENCY -------------------------------------*/
+#include "vpp.h"
+
+/*	following is the C++ header	*/
+#ifdef	__cplusplus
+extern	"C" {
+#endif
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+/* #define  LCD_XXXX  1    *//*Example*/
+
+/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/
+/* typedef  void  lcd_xxx_t;  *//*Example*/
+enum lcd_panel_t {
+	LCD_WMT_OEM,
+	LCD_CHILIN_LW0700AT9003,
+	LCD_INNOLUX_AT070TN83,
+	LCD_AUO_A080SN01,
+	LCD_EKING_EK08009,
+	LCD_HANNSTAR_HSD101PFW2,
+	LCD_LVDS_1024x600,
+	LCD_GL5001W,
+	LCD_B079XAN01,
+	LCD_TPO_TJ015NC02AA,
+	LCD_PANEL_MAX
+};
+enum {
+	LCD_POWER_OFF = 0,
+	LCD_POWER_ON,
+};
+
+#define LCD_CAP_CLK_HI		BIT(0)
+#define LCD_CAP_HSYNC_HI	BIT(1)
+#define LCD_CAP_VSYNC_HI	BIT(2)
+#define LCD_CAP_DE_LO		BIT(3)
+struct lcd_parm_t {
+	int bits_per_pixel;
+	unsigned int capability;
+	struct fb_videomode vmode;
+	int width; /* width of picture in mm */
+	int height; /* height of picture in mm */
+
+	void (*initial)(void);
+	void (*uninitial)(void);
+};
+
+/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/
+#ifdef LCD_C /* allocate memory for variables only in vout.c */
+#define EXTERN
+#else
+#define EXTERN   extern
+#endif /* ifdef LCD_C */
+
+/* EXTERN int      lcd_xxx; *//*Example*/
+
+EXTERN struct lcd_parm_t *p_lcd;
+#undef EXTERN
+
+/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/
+/* #define LCD_XXX_YYY   xxxx *//*Example*/
+/*--------------------- EXPORTED PRIVATE FUNCTIONS  --------------------------*/
+/* extern void  lcd_xxx(void); *//*Example*/
+
+int lcd_panel_register(int no, void (*get_parm)(int mode));
+struct lcd_parm_t *lcd_get_parm(enum lcd_panel_t id, unsigned int arg);
+void lcd_set_parm(int id, int bpp);
+struct lcd_parm_t *lcd_get_oem_parm(int resx, int resy);
+void lcd_set_lvds_id(int id);
+int lcd_get_lvds_id(void);
+void lcd_set_type(int type);
+int lcd_get_type(void);
+void lcd_set_enable(int enable);
+void lcd_enable_signal(int enable);
+
+/* LCD back light */
+#ifdef	__cplusplus
+}
+#endif
+#endif /* ifndef LCD_H */
diff --git a/drivers/video/wmt/lvds.c b/drivers/video/wmt/lvds.c
new file mode 100755
index 00000000..2516d788
--- /dev/null
+++ b/drivers/video/wmt/lvds.c
@@ -0,0 +1,202 @@
+/*++
+ * linux/drivers/video/wmt/lvds.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define LVDS_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "lvds.h"
+
+#ifdef WMT_FTBLK_LVDS
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LVDS_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lvds_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lvds.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lvds_xxx;        *//*Example*/
+struct lvds_base_regs *lvds_regs = (void *) LVDS_BASE_ADDR;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lvds_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+void lvds_set_power_down(int pwrdn)
+{
+	DBG_DETAIL("(%d)\n", pwrdn);
+
+	lvds_regs->test.b.pd = pwrdn;
+	mdelay(1);
+	lvds_regs->test2.b.pd_l2ha = pwrdn;
+}
+
+void lvds_set_enable(vpp_flag_t enable)
+{
+	DBG_DETAIL("(%d)\n", enable);
+	lvds_regs->test.b.tre_en = (enable) ? 0 : 1;
+	lvds_regs->test2.b.mode = (enable) ? 1 : 0;
+	lvds_regs->test2.b.resa_en = (enable) ? 0 : 1;
+#ifdef CONFIG_UBOOT
+	if ((enable) && (lcd_get_lvds_id() == LCD_LVDS_1024x600)) {
+		/* GPIO10 VDD_EN->CLK delay 16->38ms */
+		outl(inl(GPIO_BASE_ADDR + 0x80) | BIT10, GPIO_BASE_ADDR + 0x80);
+		outl(inl(GPIO_BASE_ADDR + 0xC0) | BIT10, GPIO_BASE_ADDR + 0xC0);
+		mdelay(16);
+	}
+#endif
+}
+
+int lvds_get_enable(void)
+{
+	return lvds_regs->test2.b.mode;
+}
+
+void lvds_set_rgb_type(int bpp)
+{
+	int mode;
+	int mode_change = 0x2;
+
+	DBG_DETAIL("(%d)\n", bpp);
+
+	/* 0:888, 1-555, 2-666, 3-565 */
+	switch (bpp) {
+	case 15:
+		mode = 1;
+		break;
+	case 16:
+		mode = 3;
+		break;
+	case 18:
+		mode = 2;
+		break;
+	case 24:
+	default:
+		mode = 0;
+		mode_change = 0x0;
+		break;
+	}
+#if 1 /* IGS default */
+	mode = 4;
+#endif
+	lvds_regs->status.b.test = mode_change;
+	lvds_regs->igs.b.bpp_type = mode;
+}
+
+vdo_color_fmt lvds_get_colfmt(void)
+{
+	return VDO_COL_FMT_ARGB;
+}
+
+void lvds_set_sync_polar(int h_lo, int v_lo)
+{
+	DBG_DETAIL("(%d,%d)\n", h_lo, v_lo);
+	lvds_regs->set.b.hsync_polar_lo = h_lo;
+	lvds_regs->set.b.vsync_polar_lo = v_lo;
+}
+
+void lvds_get_sync_polar(int *hsync_hi, int *vsync_hi)
+{
+	*hsync_hi = (lvds_regs->set.b.hsync_polar_lo) ? 0 : 1;
+	*vsync_hi = (lvds_regs->set.b.vsync_polar_lo) ? 0 : 1;
+}
+
+/*----------------------- Module API --------------------------------------*/
+void lvds_reg_dump(void)
+{
+	DPRINT("========== LVDS register dump ==========\n");
+	vpp_reg_dump(REG_LVDS_BEGIN, REG_LVDS_END-REG_LVDS_BEGIN);
+
+	DPRINT("---------- LVDS common ----------\n");
+	DPRINT("test %d,dual chan %d,inv clk %d\n", lvds_regs->status.b.test,
+		lvds_regs->status.b.dual_channel, lvds_regs->status.b.inv_clk);
+	DPRINT("ldi shift left %d,IGS bpp type %d\n",
+		lvds_regs->igs.b.ldi_shift_left, lvds_regs->igs.b.bpp_type);
+	DPRINT("rsen %d,pll ready %d\n", lvds_regs->detect.b.rsen,
+		lvds_regs->detect.b.pll_ready);
+	DPRINT("pwr dn %d\n", lvds_regs->test.b.pd);
+}
+
+#ifdef CONFIG_PM
+static unsigned int *lvds_pm_bk;
+static unsigned int lvds_pd_bk;
+void lvds_suspend(int sts)
+{
+	switch (sts) {
+	case 0:	/* disable module */
+		break;
+	case 1: /* disable tg */
+		break;
+	case 2:	/* backup register */
+		lvds_pd_bk = lvds_regs->test.b.pd;
+		lvds_set_power_down(1);
+		lvds_pm_bk = vpp_backup_reg(REG_LVDS_BEGIN,
+			(REG_LVDS_END-REG_LVDS_BEGIN));
+		break;
+	default:
+		break;
+	}
+}
+
+void lvds_resume(int sts)
+{
+	switch (sts) {
+	case 0:	/* restore register */
+		vpp_restore_reg(REG_LVDS_BEGIN,
+			(REG_LVDS_END-REG_LVDS_BEGIN), lvds_pm_bk);
+		lvds_pm_bk = 0;
+		if (lcd_get_lvds_id() != LCD_LVDS_1024x600)
+			lvds_set_power_down(lvds_pd_bk);
+		break;
+	case 1:	/* enable module */
+		break;
+	case 2: /* enable tg */
+		break;
+	default:
+		break;
+	}
+}
+#else
+#define lvds_suspend NULL
+#define lvds_resume NULL
+#endif
+
+void lvds_init(void)
+{
+	lvds_regs->level.b.level = 1;
+	lvds_regs->level.b.update = 1;
+	lvds_regs->test.b.pll_r_f = 1;
+	lvds_regs->test.b.pll_cpset = 1;
+	lvds_regs->test.b.tre_en = 0;
+	lvds_regs->test.b.vbg_sel = 2;
+	lvds_regs->test.b.drv_pdmode = 0;
+	lvds_regs->igs.b.ldi_shift_left = 1;
+	lvds_regs->test2.val = 0x31432;
+}
+
+#endif /* WMT_FTBLK_LVDS */
+
diff --git a/drivers/video/wmt/lvds.h b/drivers/video/wmt/lvds.h
new file mode 100755
index 00000000..9821a667
--- /dev/null
+++ b/drivers/video/wmt/lvds.h
@@ -0,0 +1,73 @@
+/*++
+ * linux/drivers/video/wmt/lvds.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp.h"
+
+#ifndef LVDS_H
+/* To assert that only one occurrence is included */
+#define LVDS_H
+/*-------------------- MODULE DEPENDENCY -------------------------------------*/
+
+/*	following is the C++ header	*/
+#ifdef	__cplusplus
+extern	"C" {
+#endif
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+/* #define  LVDS_XXXX  1    *//*Example*/
+
+/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/
+/* typedef  void  lvds_xxx_t;  *//*Example*/
+
+/*-------------------- EXPORTED PRIVATE VARIABLES ----------------------------*/
+#ifdef LVDS_C
+#define EXTERN
+#else
+#define EXTERN   extern
+#endif /* ifdef LVDS_C */
+
+/* EXTERN int      lvds_xxx; *//*Example*/
+
+#undef EXTERN
+
+/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/
+/* #define LVDS_XXX_YYY   xxxx *//*Example*/
+/*--------------------- EXPORTED PRIVATE FUNCTIONS  --------------------------*/
+/* extern void  lvds_xxx(void); *//*Example*/
+void lvds_set_enable(vpp_flag_t enable);
+int lvds_get_enable(void);
+void lvds_set_rgb_type(int bpp);
+vdo_color_fmt lvds_get_colfmt(void);
+void lvds_reg_dump(void);
+void lvds_suspend(int sts);
+void lvds_resume(int sts);
+void lvds_init(void);
+void lvds_set_power_down(int pwrdn);
+void lvds_set_sync_polar(int h_lo, int v_lo);
+void lvds_get_sync_polar(int *hsync_hi, int *vsync_hi);
+
+#ifdef	__cplusplus
+}
+#endif
+#endif /* ifndef LVDS_H */
+
diff --git a/drivers/video/wmt/mali.c b/drivers/video/wmt/mali.c
new file mode 100755
index 00000000..14ccc2a5
--- /dev/null
+++ b/drivers/video/wmt/mali.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2008-2011 WonderMedia Technologies, Inc. All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+ */
+
+#include <asm/cacheflush.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include "mali.h"
+#include <mach/hardware.h>
+
+/* Mali-400 Power Management Kernel Driver */
+
+#define REG_MALI_BADDR (0xD8080000 + WMT_MMAP_OFFSET)
+/*
+#define MALI_PMU_CONTROL
+#define MALI_CLK_CONTROL
+#define USE_PMC_POWER_STATUS
+*/
+
+static spinlock_t mali_spinlock;
+
+static unsigned int mali_max_freq;
+static unsigned int mali_cur_freq;
+
+static int on = 1;
+static int off;
+static int acpi = 1;
+static int mem_size; /* 0 MiB */
+static int debug;
+
+#define MALI_POWER_MASK 0xf
+
+#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
+#define OPT_INTVAL(opt, name) kstrtoul(opt + strlen(name) + 1, 0, NULL)
+#define OPT_STRVAL(opt, name) (opt + strlen(name))
+
+static inline char *get_opt_string(const char *this_opt, const char *name)
+{
+	const char *p;
+	int i;
+	char *ret;
+
+	p = OPT_STRVAL(this_opt, name);
+	i = 0;
+	while (p[i] && p[i] != ' ' && p[i] != ',')
+		i++;
+	ret = kmalloc(i + 1, GFP_KERNEL);
+	if (ret) {
+		strncpy(ret, p, i);
+		ret[i] = '\0';
+	}
+	return ret;
+}
+
+static inline int get_opt_int(const char *this_opt, const char *name,
+				  int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (!OPT_EQUAL(this_opt, name))
+		return 0;
+
+	*ret = OPT_INTVAL(this_opt, name);
+
+	return 1;
+}
+
+static inline int get_opt_bool(const char *this_opt, const char *name,
+				   int *ret)
+{
+	if (!ret)
+		return 0;
+
+	if (OPT_EQUAL(this_opt, name)) {
+		if (this_opt[strlen(name)] == '=')
+			*ret = kstrtoul(this_opt + strlen(name) + 1,
+					      0, NULL);
+		else
+			*ret = 1;
+	} else {
+		if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
+			*ret = 0;
+		else
+			return 0;
+	}
+	return 1;
+}
+
+static int __init malipm_setup(char *options)
+{
+	char *this_opt;
+
+	if (!options || !*options)
+		return 0;
+
+	/* The syntax is:
+	 *     malipm=[<param>][,<param>=<val>] ...
+	 * e.g.,
+	 *     malipm=on:acpi
+	 */
+
+	while ((this_opt = strsep(&options, ",")) != NULL) {
+		if (!*this_opt)
+			continue;
+		if (get_opt_bool(this_opt, "on", &on))
+			;
+		else if (get_opt_bool(this_opt, "off", &off))
+			;
+		else if (get_opt_bool(this_opt, "acpi", &acpi))
+			;
+		else if (get_opt_int(this_opt, "mem_size", &mem_size))
+			;
+		else if (get_opt_bool(this_opt, "debug", &debug))
+			;
+	}
+
+	on = !off;
+	printk(KERN_DEBUG
+		"malipm: on %d, off %d, acpi %d, debug %d, %d MiB\n",
+		on, off, acpi, debug, mem_size >> 20);
+
+	return 0;
+}
+__setup("malipm=", malipm_setup);
+
+static int mali_suspend(u32 cores);
+static int mali_resume(u32 cores);
+static void mali_enable_clock(int enab1le);
+static void mali_enable_power(int enable);
+static void mali_set_memory_base(unsigned int val);
+static void mali_set_memory_size(unsigned int val);
+static void mali_set_mem_validation_base(unsigned int val);
+static void mali_set_mem_validation_size(unsigned int val);
+static void mali_get_memory_base(unsigned int *val);
+static void mali_get_memory_size(unsigned int *val);
+static void mali_get_mem_validation_base(unsigned int *val);
+static void mali_get_mem_validation_size(unsigned int *val);
+
+/* symbols for ARM's Mali.ko */
+unsigned int mali_memory_base;
+EXPORT_SYMBOL(mali_memory_base);
+unsigned int mali_memory_size;
+EXPORT_SYMBOL(mali_memory_size);
+unsigned int mali_mem_validation_base;
+EXPORT_SYMBOL(mali_mem_validation_base);
+unsigned int mali_mem_validation_size;
+EXPORT_SYMBOL(mali_mem_validation_size);
+unsigned int mali_ump_secure_id;
+EXPORT_SYMBOL(mali_ump_secure_id);
+unsigned int (*mali_get_ump_secure_id)(unsigned int addr, unsigned int size);
+EXPORT_SYMBOL(mali_get_ump_secure_id);
+void         (*mali_put_ump_secure_id)(unsigned int ump_id);
+EXPORT_SYMBOL(mali_put_ump_secure_id);
+
+/* PMU */
+
+#define REG_MALI400_BASE        (0xd8080000 + WMT_MMAP_OFFSET)
+#define REG_MALI400_GP          (REG_MALI400_BASE)
+#define REG_MALI400_L2          (REG_MALI400_BASE + 0x1000)
+#define REG_MALI400_PMU         (REG_MALI400_BASE + 0x2000)
+#define REG_MALI400_MMU_GP      (REG_MALI400_BASE + 0x3000)
+#define REG_MALI400_MMU_PP0     (REG_MALI400_BASE + 0x4000)
+#define REG_MALI400_MMU_PP1     (REG_MALI400_BASE + 0x5000)
+#define REG_MALI400_MMU_PP2     (REG_MALI400_BASE + 0x6000)
+#define REG_MALI400_MMU_PP3     (REG_MALI400_BASE + 0x7000)
+#define REG_MALI400_PP0         (REG_MALI400_BASE + 0x8000)
+#define REG_MALI400_PP1         (REG_MALI400_BASE + 0xa000)
+#define REG_MALI400_PP2         (REG_MALI400_BASE + 0xc000)
+#define REG_MALI400_PP3         (REG_MALI400_BASE + 0xe000)
+
+#define MMU_DTE_ADDR            0x00
+#define MMU_STATUS              0x04
+#define MMU_COMMAND             0x08
+#define MMU_PAGE_FAULT_ADDR     0x0c
+#define MMU_ZAP_ONE_LINE        0x10
+#define MMU_INT_RAWSTAT         0x14
+#define MMU_INT_CLEAR           0x18
+#define MMU_INT_MASK            0x1c
+#define MMU_INT_STATUS          0x20
+
+#ifdef USE_PMC_POWER_STATUS
+#define REG_PMC_BASE                  (0xd8130000 + WMT_MMAP_OFFSET)
+#define REG_MALI_GP_SHUT_OFF_CONTROL  (REG_PMC_BASE + 0x0600)
+#define REG_MALI_L2C_SHUT_OFF_CONTROL (REG_PMC_BASE + 0x0620)
+#define REG_MALI_PP0_SHUT_OFF_CONTROL (REG_PMC_BASE + 0x0624)
+#define REG_MALI_PP1_SHUT_OFF_CONTROL (REG_PMC_BASE + 0x0628)
+
+#define PWR_SEQ_MSK 0x6
+#define PWR_STA_MSK 0xf0
+
+#ifndef REG_VAL32
+#define REG_VAL32 REG_GET32
+#endif
+
+static int wait_powerup(unsigned int reg)
+{
+	int i = 10; /* 10 * 100 us = 1 ms */
+	unsigned int val;
+
+	while (i) {
+		val = ioread32(reg);
+		if ((val & PWR_SEQ_MSK) == 0)
+			break;
+		udelay(100);
+		i--;
+	}
+	if (i == 0)
+		printk(KERN_ERR "%s %d: *0x%08x = %08x\n",
+			__func__, __LINE__, reg, val);
+	while (i) {
+		val = ioread32(reg);
+		if (val & PWR_STA_MSK)
+			break;
+		udelay(100);
+		i--;
+	}
+	if (i == 0)
+		printk(KERN_ERR "%s %d: *0x%08x = %08x\n",
+			__func__, __LINE__, reg, val);
+
+	return i ? 0 : -1;
+}
+
+static int wait_powerdown(unsigned int reg)
+{
+	int i = 10; /* 10 * 100 us = 1 ms */
+	unsigned int val;
+
+	while (i) {
+		val = ioread32(reg);
+		if ((val & PWR_SEQ_MSK) == 0)
+			break;
+		udelay(100);
+		i--;
+	}
+	if (i == 0)
+		printk(KERN_ERR "%s %d: *0x%08x = %08x\n",
+			__func__, __LINE__, reg, val);
+	while (i) {
+		val = ioread32(reg);
+		if ((val & PWR_STA_MSK) == 0)
+			break;
+		udelay(100);
+		i--;
+	}
+	if (i == 0)
+		printk(KERN_ERR "%s %d: *0x%08x = %08x\n",
+			__func__, __LINE__, reg, val);
+
+	return i ? 0 : -1;
+}
+#endif /* USE_PMC_POWER_STATUS */
+
+int mali_platform_wait_powerup(int msk)
+{
+#ifdef USE_PMC_POWER_STATUS
+	int err;
+
+	if (debug)
+		printk(KERN_DEBUG "%s\n", __func__);
+
+	err = 0;
+
+	if (msk & BIT0)
+		err += wait_powerup(REG_MALI_GP_SHUT_OFF_CONTROL);
+	if (msk & BIT1)
+		err += wait_powerup(REG_MALI_L2C_SHUT_OFF_CONTROL);
+	if (msk & BIT2)
+		err += wait_powerup(REG_MALI_PP0_SHUT_OFF_CONTROL);
+	if (msk & BIT3)
+		err += wait_powerup(REG_MALI_PP1_SHUT_OFF_CONTROL);
+
+	if (err)
+		printk(KERN_ERR "%s error\n", __func__);
+
+	return err;
+#else
+	return 0;
+#endif /* USE_PMC_POWER_STATUS */
+}
+EXPORT_SYMBOL(mali_platform_wait_powerup);
+
+int mali_platform_wait_powerdown(int msk)
+{
+#ifdef USE_PMC_POWER_STATUS
+	int err;
+
+	if (debug)
+		printk(KERN_DEBUG "%s\n", __func__);
+
+	err = 0;
+
+	if (msk & BIT0)
+		err += wait_powerdown(REG_MALI_GP_SHUT_OFF_CONTROL);
+	if (msk & BIT1)
+		err += wait_powerdown(REG_MALI_L2C_SHUT_OFF_CONTROL);
+	if (msk & BIT2)
+		err += wait_powerdown(REG_MALI_PP0_SHUT_OFF_CONTROL);
+	if (msk & BIT3)
+		err += wait_powerdown(REG_MALI_PP1_SHUT_OFF_CONTROL);
+
+	if (err)
+		printk(KERN_ERR "%s error\n", __func__);
+
+	return err;
+#else
+	return 0;
+#endif /* USE_PMC_POWER_STATUS */
+}
+EXPORT_SYMBOL(mali_platform_wait_powerdown);
+
+int mali_pmu_power_up(unsigned int msk)
+{
+	int timeout;
+	unsigned int pmu0c;
+	unsigned int pmu08;
+	unsigned int val;
+
+	val = ioread32(REG_MALI400_PMU + 8);
+	if ((val & msk) == 0)
+		return 0;
+
+	pmu08 = ioread32(REG_MALI400_PMU + 8);
+	pmu0c = ioread32(REG_MALI400_PMU + 0xc);
+	iowrite32(0, REG_MALI400_PMU + 0xc);
+
+	asm volatile("" : : : "memory");
+
+	/* PMU_POWER_UP */
+	iowrite32(msk, REG_MALI400_PMU);
+
+	asm volatile("" : : : "memory");
+
+	timeout = 10;
+
+	do {
+		val = ioread32(REG_MALI400_PMU + 8);
+		if ((val & msk) == 0)
+			break;
+		msleep_interruptible(1);
+		timeout--;
+	} while (timeout > 0);
+
+	if (debug) {
+		val = ioread32(REG_MALI400_PMU + 8);
+		if (timeout == 0)
+			printk(KERN_DEBUG "%s: 0x%x, 0x%08x -> 0x%08x: fail\n",
+				__func__, msk, pmu08, val);
+		else
+			printk(KERN_DEBUG "%s: 0x%x, 0x%08x -> 0x%08x: pass\n",
+				__func__, msk, pmu08, val);
+	}
+
+	iowrite32(pmu0c, REG_MALI400_PMU + 0xc);
+
+	msleep_interruptible(10);
+
+	if (timeout == 0) {
+		printk(KERN_DEBUG "mali pmu power up failure\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+int mali_pmu_power_down(unsigned int msk)
+{
+	unsigned int pmu08;
+	unsigned int pmu0c;
+	int timeout;
+	unsigned int val;
+
+	val = ioread32(REG_MALI400_PMU + 8);
+	if ((val & msk) == msk)
+		return 0;
+
+	pmu08 = ioread32(REG_MALI400_PMU + 8);
+	pmu0c = ioread32(REG_MALI400_PMU + 0xc);
+	iowrite32(0, REG_MALI400_PMU + 0xc);
+
+	asm volatile("" : : : "memory");
+
+	/* PMU_POWER_DOWN */
+	iowrite32(msk, REG_MALI400_PMU + 4);
+
+	asm volatile("" : : : "memory");
+
+	timeout = 10;
+
+	do {
+		val = ioread32(REG_MALI400_PMU + 8);
+		if ((val & msk) == msk)
+			break;
+		msleep_interruptible(1);
+		timeout--;
+	} while (timeout > 0);
+
+	if (debug) {
+		val = ioread32(REG_MALI400_PMU + 8);
+		if (timeout == 0)
+			printk(KERN_DEBUG "%s: 0x%x, 0x%08x -> 0x%08x: fail\n",
+				__func__, msk, pmu08, val);
+		else
+			printk(KERN_DEBUG "%s: 0x%x, 0x%08x -> 0x%08x: pass\n",
+				__func__, msk, pmu08, val);
+	}
+
+	iowrite32(pmu0c, REG_MALI400_PMU + 0xc);
+
+	msleep_interruptible(10);
+
+	if (timeout == 0) {
+		printk(KERN_DEBUG "mali pmu power down failure\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static void mali_show_info(void)
+{
+	/* GP_CONTR_REG_VERSION */
+	printk(KERN_INFO "maligp: version = 0x%08x\n",
+		ioread32(REG_MALI400_GP + 0x6c));
+
+	/* PP0_VERSION */
+	printk(KERN_INFO "malipp: version = 0x%08x\n",
+		ioread32(REG_MALI400_PP0 + 0x1000));
+}
+
+struct mali_device *create_mali_device(void)
+{
+	struct mali_device *dev;
+
+	dev = kcalloc(1, sizeof(struct mali_device), GFP_KERNEL);
+	dev->suspend = &mali_suspend;
+	dev->resume = &mali_resume;
+	dev->enable_clock = &mali_enable_clock;
+	dev->enable_power = &mali_enable_power;
+	dev->set_memory_base = &mali_set_memory_base;
+	dev->set_memory_size = &mali_set_memory_size;
+	dev->set_mem_validation_base = &mali_set_mem_validation_base;
+	dev->set_mem_validation_size = &mali_set_mem_validation_size;
+	dev->get_memory_base = &mali_get_memory_base;
+	dev->get_memory_size = &mali_get_memory_size;
+	dev->get_mem_validation_base = &mali_get_mem_validation_base;
+	dev->get_mem_validation_size = &mali_get_mem_validation_size;
+
+	return dev;
+}
+EXPORT_SYMBOL(create_mali_device);
+
+void release_mali_device(struct mali_device *dev)
+{
+	kfree(dev);
+}
+EXPORT_SYMBOL(release_mali_device);
+
+static int mali_suspend(u32 cores)
+{
+	if (debug)
+		printk(KERN_DEBUG "mali_suspend(%d)\n", cores);
+
+	return 0;
+}
+
+static int mali_resume(u32 cores)
+{
+	if (debug)
+		printk(KERN_DEBUG "mali_resume(%d)\n", cores);
+
+	return 0;
+}
+
+static void mali_enable_clock(int enable)
+{
+	int clk_en;
+
+	/*
+	 * if your enable clock with auto_pll_divisor() twice,
+	 * then you have to call it at least twice to disable clock.
+	 * It is really bad.
+	 */
+
+	if (enable) {
+		auto_pll_divisor(DEV_MALI, CLK_ENABLE, 0, 0);
+		if (debug)
+			printk(KERN_DEBUG "Mali clock enabled\n");
+	} else {
+		do {
+			clk_en = auto_pll_divisor(DEV_MALI, CLK_DISABLE, 0, 0);
+		} while (clk_en);
+		if (debug)
+			printk(KERN_DEBUG "Mali clock disabled\n");
+	}
+}
+
+static void mali_enable_power(int enable)
+{
+	/* Mali-400's power was always enabled on WM3481. */
+}
+
+static void mali_set_memory_base(unsigned int val)
+{
+	spin_lock(&mali_spinlock);
+	mali_memory_base = val;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_set_memory_size(unsigned int val)
+{
+	spin_lock(&mali_spinlock);
+	mali_memory_size = val;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_set_mem_validation_base(unsigned int val)
+{
+	spin_lock(&mali_spinlock);
+	mali_mem_validation_base = val;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_set_mem_validation_size(unsigned int val)
+{
+	spin_lock(&mali_spinlock);
+	mali_mem_validation_size = val;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_get_memory_base(unsigned int *val)
+{
+	spin_lock(&mali_spinlock);
+	*val = mali_memory_base;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_get_memory_size(unsigned int *val)
+{
+	spin_lock(&mali_spinlock);
+	*val = mali_memory_size;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_get_mem_validation_base(unsigned int *val)
+{
+	spin_lock(&mali_spinlock);
+	*val = mali_mem_validation_base;
+	spin_unlock(&mali_spinlock);
+}
+
+static void mali_get_mem_validation_size(unsigned int *val)
+{
+	spin_lock(&mali_spinlock);
+	*val = mali_mem_validation_size;
+	spin_unlock(&mali_spinlock);
+}
+
+/* Export functions */
+
+int mali_platform_init_impl(void *data)
+{
+	if (debug)
+		printk(KERN_DEBUG "mali_platform_init_impl\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(mali_platform_init_impl);
+
+int mali_platform_deinit_impl(void *data)
+{
+	if (debug)
+		printk(KERN_DEBUG "mali_platform_deinit_impl\n");
+
+	return 0;
+}
+EXPORT_SYMBOL(mali_platform_deinit_impl);
+
+int mali_platform_powerdown_impl(u32 cores)
+{
+	unsigned int status;
+
+	if (debug)
+		printk(KERN_DEBUG "mali_platform_powerdown_impl(%d)\n", cores);
+
+	status = MALI_POWER_MASK;
+
+	if (acpi == 0)
+		return 0;
+
+#ifdef MALI_PMU_CONTROL
+	status = ioread32(REG_MALI400_PMU + 8);
+
+	if ((status & MALI_POWER_MASK) != MALI_POWER_MASK)
+		mali_pmu_power_down(MALI_POWER_MASK);
+#endif
+
+#ifdef MALI_CLK_CONTROL
+	spin_lock(&mali_spinlock);
+	mali_enable_clock(0);
+	mali_enable_power(0);
+	spin_unlock(&mali_spinlock);
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(mali_platform_powerdown_impl);
+
+int mali_platform_powerup_impl(u32 cores)
+{
+	unsigned int status;
+
+	if (debug)
+		printk(KERN_DEBUG "mali_platform_powerup_impl(%d)\n", cores);
+
+#ifdef MALI_PMU_CONTROL
+	status = ioread32(REG_MALI400_PMU + 8);
+
+	/* printk("mali pmu: status = 0x08%x\n", status); */
+
+	if ((status & MALI_POWER_MASK) != 0)
+		mali_pmu_power_up(MALI_POWER_MASK);
+#else
+	status = 0;
+#endif
+
+#ifdef MALI_CLK_CONTROL
+	spin_lock(&mali_spinlock);
+	mali_enable_power(1);
+	mali_enable_clock(1);
+	spin_unlock(&mali_spinlock);
+#endif
+
+	return 0;
+}
+EXPORT_SYMBOL(mali_platform_powerup_impl);
+
+void mali_gpu_utilization_handler_impl(u32 utilization)
+{
+	unsigned int freq;
+	unsigned int oldfreq;
+	int ret;
+
+	if (acpi < 2 || mali_max_freq == 0)
+		return;
+
+	utilization = (utilization + 63) & ~63;
+	oldfreq = mali_cur_freq;
+	freq = ((utilization * mali_max_freq) >> 8) + 64;
+	ret = auto_pll_divisor(DEV_MALI, SET_DIV, 2, freq); /* MHz */
+	if (ret > 0)
+		mali_cur_freq = (ret >> 20) + 1; /* MHz */
+	printk(KERN_DEBUG "%s: %d, %d -> %d (%d) MHz\n",
+		__func__, utilization, oldfreq, mali_cur_freq, freq);
+}
+EXPORT_SYMBOL(mali_gpu_utilization_handler_impl);
+
+void set_mali_parent_power_domain(struct platform_device *dev)
+{
+	/* No implemented yet */
+}
+EXPORT_SYMBOL(set_mali_parent_power_domain);
+
+static int __init mali_init(void)
+{
+	unsigned long smem_start;
+	unsigned long smem_len;
+	int err = 0;
+	int ret;
+
+	spin_lock_init(&mali_spinlock);
+
+	smem_start = num_physpages << PAGE_SHIFT;
+
+	smem_len = mem_size;
+
+	mali_set_memory_base(smem_start);
+	mali_set_memory_size(smem_len);
+	mali_set_mem_validation_base(0);
+	mali_set_mem_validation_size(0);
+
+	mali_ump_secure_id = (unsigned int) -1;
+	mali_get_ump_secure_id = NULL;
+	mali_put_ump_secure_id = NULL;
+
+	if (off)
+		return -1;
+
+	mali_enable_power(1);
+	mali_enable_clock(1);
+
+	/* Wait for power stable */
+	msleep_interruptible(1);
+
+	/* Verify Mali-400 PMU */
+	err += mali_pmu_power_down(MALI_POWER_MASK);
+	if (!err)
+		err += mali_pmu_power_up(MALI_POWER_MASK);
+	if (!err)
+		mali_show_info();
+
+	if (acpi)
+		err += mali_pmu_power_down(MALI_POWER_MASK);
+
+	if (acpi > 1) {
+		ret = auto_pll_divisor(DEV_MALI, GET_FREQ, 0, 0);
+		if (ret > 0) {
+			mali_max_freq = (ret >> 20) + 1; /* MHz */
+			mali_cur_freq = mali_max_freq;
+		}
+	} else {
+		mali_max_freq = mali_cur_freq = 0;
+	}
+
+	/* Power on all Mali core at bootup, otherwise Mali driver will fail
+	 * at driver/src/devicedrv/mali/common/mali_pp.c: mali_pp_reset_wait().
+	 */
+	/*
+	mali_pmu_power_up(MALI_POWER_MASK);
+	*/
+	ret = ioread32(REG_MALI400_PMU + 8);
+	printk(KERN_DEBUG "mali power on = %d\n", !ret);
+
+	return err;
+}
+
+static void __exit mali_exit(void)
+{
+	mali_enable_clock(0);
+	mali_enable_power(0);
+}
+
+module_init(mali_init);
+module_exit(mali_exit);
+
+MODULE_AUTHOR("WonderMedia Technologies, Inc.");
+MODULE_DESCRIPTION("Mali PM Kernel Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/wmt/mali.h b/drivers/video/wmt/mali.h
new file mode 100755
index 00000000..34605eae
--- /dev/null
+++ b/drivers/video/wmt/mali.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2008-2011 WonderMedia Technologies, Inc. All Rights Reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+ */
+
+#ifndef MALI_H
+#define MALI_H
+struct mali_device {
+	int (*suspend)(u32 cores);
+	int (*resume)(u32 cores);
+	void (*enable_clock)(int enable);
+	void (*enable_power)(int enable);
+	void (*set_memory_base)(unsigned int val);
+	void (*set_memory_size)(unsigned int val);
+	void (*set_mem_validation_base)(unsigned int val);
+	void (*set_mem_validation_size)(unsigned int val);
+	void (*get_memory_base)(unsigned int *val);
+	void (*get_memory_size)(unsigned int *val);
+	void (*get_mem_validation_base)(unsigned int *val);
+	void (*get_mem_validation_size)(unsigned int *val);
+};
+
+struct mali_device *create_mali_device(void);
+void release_mali_device(struct mali_device *dev);
+
+int mali_platform_init_impl(void *data);
+int mali_platform_deinit_impl(void *data);
+int mali_platform_powerdown_impl(u32 cores);
+int mali_platform_powerup_impl(u32 cores);
+void mali_gpu_utilization_handler_impl(u32 utilization);
+void set_mali_parent_power_domain(struct platform_device *dev);
+
+extern unsigned long msleep_interruptible(unsigned int msecs);
+#endif /* MALI_H */
diff --git a/drivers/video/wmt/parse-edid.c b/drivers/video/wmt/parse-edid.c
new file mode 100755
index 00000000..8bf8da74
--- /dev/null
+++ b/drivers/video/wmt/parse-edid.c
@@ -0,0 +1,1069 @@
+/*++
+ * linux/drivers/video/wmt/parse-edid.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define PARSE_EDID_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "vpp.h"
+#include "edid.h"
+#include "hdmi.h"
+
+const char edid_v1_header[] = {
+	0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00};
+
+const char edid_v1_descriptor_flag[] = { 0x00, 0x00 };
+
+#define COMBINE_HI_8LO(hi, lo) \
+	((((unsigned)hi) << 8) | (unsigned)lo)
+
+#define COMBINE_HI_4LO(hi, lo) \
+	((((unsigned)hi) << 4) | (unsigned)lo)
+
+#define UPPER_NIBBLE(x) \
+	(((128|64|32|16) & (x)) >> 4)
+
+#define LOWER_NIBBLE(x) \
+	((1|2|4|8) & (x))
+
+#define MONITOR_NAME            0xfc
+#define MONITOR_LIMITS          0xfd
+#define UNKNOWN_DESCRIPTOR      -1
+#define DETAILED_TIMING_BLOCK   -2
+
+struct edid_timing_t edid_establish_timing[] = {
+	{ 800, 600, 60 }, { 800, 600, 56 }, { 640, 480, 75 }, { 640, 480, 72 },
+	{ 640, 480, 67 }, { 640, 480, 60 }, { 720, 400, 88 }, { 720, 400, 70 },
+	{ 1280, 1024, 75 }, { 1024, 768, 75 }, { 1024, 768, 70 },
+	{ 1024, 768, 60 }, { 1024, 768, 87 }, { 832, 624, 75 },
+	{ 800, 600, 75 }, { 800, 600, 72 }, { 1152, 870, 75 }
+};
+int edid_msg_enable;
+int edid_disable;
+struct edid_parsed_t edid_parsed;
+
+#undef DBGMSG
+#define DBGMSG(fmt, args...)	if (edid_msg_enable) \
+					DPRINT(fmt, ## args)
+
+static int block_type(char *block)
+{
+	if (!memcmp(edid_v1_descriptor_flag, block, 2)) {
+		/* descriptor */
+		if (block[2] != 0)
+			return UNKNOWN_DESCRIPTOR;
+		return block[3];
+	}
+	/* detailed timing block */
+	return DETAILED_TIMING_BLOCK;
+} /* End of block_type() */
+
+static char *get_vendor_sign(char *block, char *sign)
+{
+	unsigned short h;
+
+	/*
+	08h	WORD	big-endian manufacturer ID (see #00136)
+		    bits 14-10: first letter (01h='A', 02h='B', etc.)
+		    bits 9-5: second letter
+		    bits 4-0: third letter
+	*/
+	h = COMBINE_HI_8LO(block[0], block[1]);
+	sign[0] = ((h >> 10) & 0x1f) + 'A' - 1;
+	sign[1] = ((h >> 5) & 0x1f) + 'A' - 1;
+	sign[2] = (h & 0x1f) + 'A' - 1;
+	sign[3] = 0;
+	return sign;
+} /* End of get_vendor_sign() */
+
+static char *get_monitor_name(char *block, char *name)
+{
+#define DESCRIPTOR_DATA         5
+
+	char *ptr = block + DESCRIPTOR_DATA;
+	unsigned i;
+
+	for (i = 0; i < 13; i++, ptr++) {
+		if (*ptr == 0xa) {
+			name[i] = 0;
+			return name;
+		}
+		name[i] = *ptr;
+	}
+	return name;
+} /* End of get_monitor_name() */
+
+static int parse_timing_description(char *dtd, struct edid_info_t *info)
+{
+#define PIXEL_CLOCK_LO     ((unsigned)dtd[0])
+#define PIXEL_CLOCK_HI     ((unsigned)dtd[1])
+#define PIXEL_CLOCK  (COMBINE_HI_8LO(PIXEL_CLOCK_HI, PIXEL_CLOCK_LO) * 10000)
+#define H_ACTIVE_LO        ((unsigned)dtd[2])
+#define H_BLANKING_LO      ((unsigned)dtd[3])
+#define H_ACTIVE_HI        UPPER_NIBBLE((unsigned)dtd[4])
+#define H_ACTIVE           COMBINE_HI_8LO(H_ACTIVE_HI, H_ACTIVE_LO)
+#define H_BLANKING_HI      LOWER_NIBBLE((unsigned)dtd[4])
+#define H_BLANKING         COMBINE_HI_8LO(H_BLANKING_HI, H_BLANKING_LO)
+#define V_ACTIVE_LO        ((unsigned)dtd[5])
+#define V_BLANKING_LO      ((unsigned)dtd[6])
+#define V_ACTIVE_HI        UPPER_NIBBLE((unsigned)dtd[7])
+#define V_ACTIVE           COMBINE_HI_8LO(V_ACTIVE_HI, V_ACTIVE_LO)
+#define V_BLANKING_HI      LOWER_NIBBLE((unsigned)dtd[7])
+#define V_BLANKING         COMBINE_HI_8LO(V_BLANKING_HI, V_BLANKING_LO)
+#define H_SYNC_OFFSET_LO   ((unsigned)dtd[8])
+#define H_SYNC_WIDTH_LO    ((unsigned)dtd[9])
+#define V_SYNC_OFFSET_LO   UPPER_NIBBLE((unsigned)dtd[10])
+#define V_SYNC_WIDTH_LO    LOWER_NIBBLE((unsigned)dtd[10])
+#define V_SYNC_WIDTH_HI    ((unsigned)dtd[11] & (1|2))
+#define V_SYNC_OFFSET_HI   (((unsigned)dtd[11] & (4|8)) >> 2)
+#define H_SYNC_WIDTH_HI    (((unsigned)dtd[11] & (16|32)) >> 4)
+#define H_SYNC_OFFSET_HI   (((unsigned)dtd[11] & (64|128)) >> 6)
+#define V_SYNC_WIDTH       COMBINE_HI_4LO(V_SYNC_WIDTH_HI, V_SYNC_WIDTH_LO)
+#define V_SYNC_OFFSET      COMBINE_HI_4LO(V_SYNC_OFFSET_HI, V_SYNC_OFFSET_LO)
+#define H_SYNC_WIDTH       COMBINE_HI_4LO(H_SYNC_WIDTH_HI, H_SYNC_WIDTH_LO)
+#define H_SYNC_OFFSET      COMBINE_HI_4LO(H_SYNC_OFFSET_HI, H_SYNC_OFFSET_LO)
+#define H_SIZE_LO          ((unsigned)dtd[12])
+#define V_SIZE_LO          ((unsigned)dtd[13])
+#define H_SIZE_HI          UPPER_NIBBLE((unsigned)dtd[14])
+#define V_SIZE_HI          LOWER_NIBBLE((unsigned)dtd[14])
+#define H_SIZE             COMBINE_HI_8LO(H_SIZE_HI, H_SIZE_LO)
+#define V_SIZE             COMBINE_HI_8LO(V_SIZE_HI, V_SIZE_LO)
+#define H_BORDER           ((unsigned)dtd[15])
+#define V_BORDER           ((unsigned)dtd[16])
+#define FLAGS              ((unsigned) dtd[17])
+#define INTERLACED         (FLAGS & 128)
+#define SYNC_TYPE	   (FLAGS & 3 << 3)  /* bits 4,3 */
+#define SYNC_SEPARATE	   (3 << 3)
+#define HSYNC_POSITIVE	   (FLAGS & 4)
+#define VSYNC_POSITIVE     (FLAGS & 2)
+
+	int htotal, vtotal;
+	int i;
+	struct fb_videomode *t;
+	int fps;
+	int vmul;
+
+	htotal = H_ACTIVE + H_BLANKING;
+	vtotal = V_ACTIVE + V_BLANKING;
+
+	DBGMSG("Detail Timing: \"%dx%d\"\n", H_ACTIVE, V_ACTIVE);
+	DBGMSG("\tVfreq %dHz, Hfreq %dkHz\n",
+	PIXEL_CLOCK / (vtotal * htotal),
+	PIXEL_CLOCK / (htotal * 1000));
+	DBGMSG("\tDotClock\t%d\n", PIXEL_CLOCK / 1000000);
+	DBGMSG("\tHTimings\t%u %u %u %u\n", H_ACTIVE,
+		H_ACTIVE + H_SYNC_OFFSET,
+		H_ACTIVE + H_SYNC_OFFSET + H_SYNC_WIDTH,
+		htotal);
+
+	DBGMSG("\tVTimings\t%u %u %u %u\n", V_ACTIVE,
+	V_ACTIVE + V_SYNC_OFFSET,
+	V_ACTIVE + V_SYNC_OFFSET + V_SYNC_WIDTH,
+	vtotal);
+
+	if (INTERLACED || (SYNC_TYPE == SYNC_SEPARATE)) {
+		DBGMSG("\tFlags\t%s\"%sHSync\" \"%sVSync\"\n",
+		INTERLACED ? "\"Interlace\" " : "",
+		HSYNC_POSITIVE ? "+" : "-",
+		VSYNC_POSITIVE ? "+" : "-");
+	}
+
+	for (i = 0; i < 4; i++) {
+		t = &info->detail_timing[i];
+		if (t->pixclock == 0)
+			break;
+	}
+
+	if (i >= 4) {
+		DBGMSG("*W* slot full\n");
+		return 0;
+	}
+
+	t->pixclock = KHZ2PICOS(PIXEL_CLOCK / 1000);
+	t->right_margin = H_SYNC_OFFSET;
+	t->hsync_len = H_SYNC_WIDTH;
+	t->xres = H_ACTIVE;
+	t->left_margin = H_BLANKING - (H_SYNC_WIDTH + H_SYNC_OFFSET);
+	t->vmode = INTERLACED ? FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+	vmul = (INTERLACED) ? 2 : 1;
+	t->lower_margin = V_SYNC_OFFSET * vmul;
+	t->vsync_len = V_SYNC_WIDTH * vmul;
+	t->yres = V_ACTIVE * vmul;
+	t->upper_margin = V_BLANKING - (V_SYNC_WIDTH + V_SYNC_OFFSET);
+
+	fps = vpp_calc_refresh(PIXEL_CLOCK, htotal, vtotal);
+	t->refresh = fps;
+	t->sync = HSYNC_POSITIVE ? (FB_SYNC_HOR_HIGH_ACT) : 0;
+	t->sync |= VSYNC_POSITIVE ? (FB_SYNC_VERT_HIGH_ACT) : 0;
+
+	if (vout_check_ratio_16_9(H_ACTIVE, V_ACTIVE))
+		info->option |= EDID_OPT_16_9;
+#if 0
+	DBGMSG("%dx%d,%d,%s\n", H_ACTIVE, V_ACTIVE, t->pixel_clock,
+		(info->option & EDID_OPT_16_9) ? "16:9" : "4:3");
+#endif
+	return 0;
+} /* End of parse_timing_description() */
+
+static int parse_dpms_capabilities(char flags)
+{
+#define DPMS_ACTIVE_OFF		(1 << 5)
+#define DPMS_SUSPEND		(1 << 6)
+#define DPMS_STANDBY		(1 << 7)
+
+	DBGMSG("# DPMS capabilities: Active off:%s  Suspend:%s  Standby:%s\n\n",
+	    (flags & DPMS_ACTIVE_OFF) ? "yes" : "no",
+	    (flags & DPMS_SUSPEND)    ? "yes" : "no",
+	    (flags & DPMS_STANDBY)    ? "yes" : "no");
+	return 0;
+} /* End of parse_dpms_capabilities() */
+
+static int parse_monitor_limits(char *block, struct edid_info_t *info)
+{
+#define V_MIN_RATE              block[5]
+#define V_MAX_RATE              block[6]
+#define H_MIN_RATE              block[7]
+#define H_MAX_RATE              block[8]
+#define MAX_PIXEL_CLOCK         (((int)block[9]) * 10)
+#define GTF_SUPPORT             block[10]
+
+	DBGMSG("Monitor limit\n");
+	DBGMSG("\tHorizontal Frequency: %u-%u Hz\n", H_MIN_RATE, H_MAX_RATE);
+	DBGMSG("\tVertical   Frequency: %u-%u kHz\n", V_MIN_RATE, V_MAX_RATE);
+	if (MAX_PIXEL_CLOCK == 10 * 0xff) {
+		DBGMSG("\tMax dot clock not given\n");
+	} else {
+		DBGMSG("\tMax dot clock (video bandwidth) %u MHz\n",
+			(int)MAX_PIXEL_CLOCK);
+		info->pixel_clock_limit = MAX_PIXEL_CLOCK;
+	}
+
+	if (GTF_SUPPORT)
+		DBGMSG("\tEDID version 3 GTF given: contact author\n");
+	return 0;
+} /* End of parse_monitor_limits() */
+
+static int get_established_timing(char *edid, struct edid_info_t *info)
+{
+	char time_1, time_2;
+
+	time_1 = edid[ESTABLISHED_TIMING_I];
+	time_2 = edid[ESTABLISHED_TIMING_II];
+	info->establish_timing = time_1 + (time_2 << 8);
+
+	/*---------------------------------------------------------------------
+	35: ESTABLISHED TIMING I
+	bit 7-0: 720x400@70 Hz, 720x400@88 Hz, 640x480@60 Hz, 640x480@67 Hz,
+	640x480@72 Hz, 640x480@75 Hz, 800x600@56 Hz, 800x600@60 Hz
+	---------------------------------------------------------------------*/
+	DBGMSG("Established Timimgs I: 0x%x\n", time_1);
+	if (time_1 & 0x80)
+		DBGMSG("\t%dx%d@%dHz\n", 720, 400, 70);
+	if (time_1 & 0x40)
+		DBGMSG("\t%dx%d@%dHz\n", 720, 400, 88);
+	if (time_1 & 0x20)
+		DBGMSG("\t%dx%d@%dHz\n", 640, 480, 60);
+	if (time_1 & 0x10)
+		DBGMSG("\t%dx%d@%dHz\n", 640, 480, 67);
+	if (time_1 & 0x08)
+		DBGMSG("\t%dx%d@%dHz\n", 640, 480, 72);
+	if (time_1 & 0x04)
+		DBGMSG("\t%dx%d@%dHz\n", 640, 480, 75);
+	if (time_1 & 0x02)
+		DBGMSG("\t%dx%d@%dHz\n", 800, 600, 56);
+	if (time_1 & 0x01)
+		DBGMSG("\t%dx%d@%dHz\n", 800, 600, 60);
+
+	/*---------------------------------------------------------------------
+	36: ESTABLISHED TIMING II
+	    bit 7-0: 800x600@72 Hz, 800x600@75 Hz, 832x624@75 Hz,
+	    1024x768@87 Hz (Interlaced), 1024x768@60 Hz, 1024x768@70 Hz,
+	    1024x768@75 Hz, 1280x1024@75 Hz
+	---------------------------------------------------------------------*/
+	DBGMSG("Established Timimgs II: 0x%x\n", time_2);
+	if (time_2 & 0x80)
+		DBGMSG("\t%dx%d@%dHz\n", 800, 600, 72);
+	if (time_2 & 0x40)
+		DBGMSG("\t%dx%d@%dHz\n", 800, 600, 75);
+	if (time_2 & 0x20)
+		DBGMSG("\t%dx%d@%dHz\n", 832, 624, 75);
+	if (time_2 & 0x10)
+		DBGMSG("\t%dx%d@%dHz (Interlace)\n", 1024, 768, 87);
+	if (time_2 & 0x08)
+		DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 60);
+	if (time_2 & 0x04)
+		DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 70);
+	if (time_2 & 0x02)
+		DBGMSG("\t%dx%d@%dHz\n", 1024, 768, 75);
+	if (time_2 & 0x01)
+		DBGMSG("\t%dx%d@%dHz\n", 1280, 1024, 75);
+	return 0;
+} /* End of get_established_timing() */
+
+static int get_standard_timing(char *edid, struct edid_info_t *info)
+{
+	char *ptr = edid + STANDARD_TIMING_IDENTIFICATION_START;
+	int h_res, v_res, v_freq;
+	int byte_1, byte_2, aspect, i;
+
+	/*---------------------------------------------------------------------
+	First byte
+	Horizontal resolution.  Multiply by 8, then add 248 for actual value.
+	Second byte
+	bit 7-6: Aspect ratio. Actual vertical resolution depends on horizontal
+	resolution.
+	00=16:10, 01=4:3, 10=5:4, 11=16:9 (00=1:1 prior to v1.3)
+	bit 5-0: Vertical frequency. Add 60 to get actual value.
+	---------------------------------------------------------------------*/
+	DBGMSG("Standard Timing Identification\n");
+	for (i = 0; i < STANDARD_TIMING_IDENTIFICATION_SIZE / 2; i++) {
+		byte_1 = *ptr++;
+		byte_2 = *ptr++;
+		if ((byte_1 == 0x01) && (byte_2 == 0x01))
+			break;
+		h_res = (byte_1 * 8) + 248;
+		aspect = byte_2 & 0xC0;
+		switch (aspect) {
+		default:
+		case 0x00:
+			v_res = h_res * 10/16;
+			break;
+		case 0x40:
+			v_res = h_res * 3/4;
+			break;
+		case 0x80:
+			v_res = h_res * 4/5;
+			break;
+		case 0xC0:
+			v_res = h_res * 9/16;
+			break;
+		}
+		v_freq = (byte_2 & 0x1F) + 60;
+		DBGMSG("\t%dx%d@%dHz\n", h_res, v_res, v_freq);
+		info->standard_timing[i].resx = h_res;
+		info->standard_timing[i].resy = v_res;
+		info->standard_timing[i].freq = v_freq;
+	}
+	return 0;
+} /* End of get_standard_timing() */
+
+static int edid_parse_v1(char *edid, struct edid_info_t *info)
+{
+	char *block;
+	char *monitor_name = 0;
+	char  monitor_alt_name[100];
+	char  vendor_sign[4];
+	int   i, ret = 0;
+
+	if (edid_checksum(edid, EDID_LENGTH)) {
+		DBG_ERR("checksum failed\n");
+		ret = -1;
+		goto parse_end;
+	}
+
+	if (memcmp(edid+EDID_HEADER, edid_v1_header, EDID_HEADER_END+1)) {
+		DBGMSG("*E* first bytes don't match EDID version 1 header\n");
+		ret = -1;
+		goto parse_end;
+	}
+
+	if(edid_msg_enable)
+		edid_dump(edid);
+
+	DBGMSG("[EDID] EDID version:  %d.%d\n",
+		(int)edid[EDID_STRUCT_VERSION],
+		(int)edid[EDID_STRUCT_REVISION]);
+
+	get_vendor_sign(edid + ID_MANUFACTURER_NAME, (char *) &vendor_sign);
+
+	info->width = edid[EDID_MAX_HOR_IMAGE_SIZE] * 10;
+	info->height = edid[EDID_MAX_VER_IMAGE_SIZE] * 10;
+	DBGMSG("[EDID] max hor %d cm ver %d cm\n", info->width, info->height);
+
+	/*---------------------------------------------------------------------
+	Parse Monitor name
+	---------------------------------------------------------------------*/
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+	block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block_type(block) == MONITOR_NAME) {
+			monitor_name =
+				get_monitor_name(block, monitor_alt_name);
+			break;
+		}
+	}
+
+	if (!monitor_name) {
+		/* Stupid djgpp hasn't snDBGMSG so we have to
+			hack something together */
+		if (strlen(vendor_sign) + 10 > sizeof(monitor_alt_name))
+			vendor_sign[3] = 0;
+
+		sprintf(monitor_alt_name, "%s:%02x%02x",
+		vendor_sign, edid[ID_MODEL], edid[ID_MODEL+1]);
+		monitor_name = monitor_alt_name;
+	}
+
+	DBGMSG("Identifier \"%s\"\n", monitor_name);
+	DBGMSG("VendorName \"%s\"\n", vendor_sign);
+	DBGMSG("ModelName  \"%s\"\n", monitor_name);
+
+	memset(edid_parsed.tv_name.vendor_name, 0, sizeof(edid_parsed.tv_name.vendor_name));
+	strcpy(edid_parsed.tv_name.vendor_name, vendor_sign);
+
+	memset(edid_parsed.tv_name.monitor_name, 0, sizeof(edid_parsed.tv_name.monitor_name));
+	if (strlen(monitor_name) < MONITOR_NAME_LEN)
+		strcpy(edid_parsed.tv_name.monitor_name, monitor_name);
+	else
+		strncpy(edid_parsed.tv_name.monitor_name, monitor_name, MONITOR_NAME_LEN - 1);
+
+	parse_dpms_capabilities(edid[DPMS_FLAGS]);
+
+	/*---------------------------------------------------------------------
+	Parse ESTABLISHED TIMING I and II
+	---------------------------------------------------------------------*/
+	get_established_timing(edid, info);
+
+	/*---------------------------------------------------------------------
+	Parse STANDARD TIMING IDENTIFICATION
+	---------------------------------------------------------------------*/
+	get_standard_timing(edid, info);
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+		block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block_type(block) == MONITOR_LIMITS)
+			parse_monitor_limits(block, info);
+	}
+
+	block = edid + DETAILED_TIMING_DESCRIPTIONS_START;
+	for (i = 0; i < NO_DETAILED_TIMING_DESCRIPTIONS; i++,
+		block += DETAILED_TIMING_DESCRIPTION_SIZE) {
+		if (block_type(block) == DETAILED_TIMING_BLOCK)
+			parse_timing_description(block, info);
+	}
+parse_end:
+	return ret;
+}
+
+void edid_parse_CEA_VendorSpecDataBlock(char *block, int len,
+						struct edid_info_t *info)
+{
+	int index;
+	char temp;
+
+	DBGMSG("Vendor Spec Data Block\n");
+	if (len < 5) /* min size */
+		return;
+	/* IEEE Registration Identifier 0x000C03 */
+	if ((block[1] == 0x03) && (block[2] == 0x0C) &&
+		(block[3] == 0x0)) {
+		info->option |= EDID_OPT_HDMI;
+		DBGMSG("\t support HDMI\n");
+	}
+	DBGMSG("\t Source Physical Addr %d.%d.%d.%d\n",
+		(block[4] & 0xF0) >> 4, block[4] & 0x0F,
+		(block[5] & 0xF0) >> 4, block[5] & 0x0F);
+	info->hdmi_phy_addr = (block[4] << 8) + block[5];
+
+	/* extersion fields */
+	if (len < 8)
+		return;
+	DBGMSG("\t%s support AI\n",
+		(block[6] & 0x80) ? "" : "no");
+	DBGMSG("\t%s support 30 bits/pixel(10 bits/color)\n",
+		(block[6] & 0x40) ? "" : "no");
+	DBGMSG("\t%s support 36 bits/pixel(12 bits/color)\n",
+		(block[6] & 0x20) ? "" : "no");
+	DBGMSG("\t%s support 48 bits/pixel(16 bits/color)\n",
+		(block[6] & 0x10) ? "" : "no");
+	DBGMSG("\t%s support YUV444 in Deep Color mode\n",
+		(block[6] & 0x08) ? "" : "no");
+	DBGMSG("\t%s support DVI dual-link\n",
+		(block[6] & 0x01) ? "" : "no");
+	DBGMSG("\tMax TMDS Clock %d MHz\n", block[7] * 5);
+	temp = block[8];
+	index = 9;
+
+	if (temp & BIT(7)) {
+		DBGMSG("\tVideo Latency %d,Audio Latency %d\n",
+			block[index], block[index+1]);
+		index += 2;
+	}
+
+	if (temp & BIT(6)) {
+		DBGMSG("\tInterlaced Video Latency %d,Audio Latency %d\n",
+			block[index], block[index+1]);
+		index += 2;
+	}
+
+	if (temp & BIT(5)) {
+		int hdmi_xx_len, hdmi_3d_len;
+
+		DBGMSG("\tHDMI Video present\n");
+		temp = block[index];
+		if (temp & 0x80)
+			DBGMSG("\t\t3D present support Mandatory formats\n");
+		if (temp & 0x60)
+			DBGMSG("\t\t3D Multi present %d\n", (temp & 0x60) >> 5);
+		DBGMSG("\t\tImage size %d\n", (temp & 0x18) >> 3);
+		hdmi_xx_len = (block[index + 1] & 0xE0) >> 5;
+		hdmi_3d_len = block[index + 1] & 0x1F;
+		DBGMSG("\t\thdmi_xx_len %d,hdmi_3d_len %d\n",
+			hdmi_xx_len, hdmi_3d_len);
+		index += 2;
+
+		if (hdmi_xx_len) {
+			/* Refer to HDMI Spec Ver 1.4a */
+			index += hdmi_xx_len;
+		}
+
+		if (hdmi_3d_len) {
+			int struct_all_3d = 0;
+			int mask_3d = 0xFF;
+			int vic_order_2d;
+			char struct_3d, detail_3d;
+			int i;
+
+			hdmi_3d_len += index;
+			switch (temp & 0x60) {
+			case 0x40:
+				struct_all_3d = (block[index] << 8) +
+					block[index + 1];
+				mask_3d = (block[index + 2] << 8) +
+					block[index + 3]; /* 3D support mask */
+				DBGMSG("\t\t3D struct 0x%x,mask 0x%x\n",
+					struct_all_3d, mask_3d);
+				index += 4;
+				break;
+			case 0x20:
+				struct_all_3d = (block[index] << 8) +
+					block[index + 1];
+				DBGMSG("\t\t3D struct 0x%x\n", struct_all_3d);
+				index += 2;
+				break;
+			default:
+				break;
+			}
+			/* 3D support type */
+			if (struct_all_3d & BIT0)
+				DBGMSG("\t\tSupport Frame packing\n");
+			if (struct_all_3d & BIT6)
+				DBGMSG("\t\tSupport Top and Bottom\n");
+			if (struct_all_3d & BIT8)
+				DBGMSG("\t\tSupport Side by Side\n");
+
+			for (i = 0; i < 16; i++) {
+				if (mask_3d & (0x1 << i))
+					info->vic_3d[i].mask = struct_all_3d;
+			}
+
+			DBGMSG("\t\t[3D Structure type 0-Frame packing");
+			DBGMSG(",6-Top and Bottom,8-Side by Side]\n");
+			while (index < hdmi_3d_len) {
+				vic_order_2d = (block[index] & 0xF0) >> 4;
+				struct_3d = block[index] & 0x0F;
+				index++;
+				if (struct_3d & 0x8) {
+					detail_3d = (block[index] & 0xF0) >> 4;
+					index++;
+				} else {
+					detail_3d = 0;
+				}
+				info->vic_3d[vic_order_2d].mask |=
+					(0x1 << struct_3d);
+				DBGMSG("\t\tVIC %d,3D struct %d,detail %d\n",
+					vic_order_2d, struct_3d, detail_3d);
+			}
+		}
+	}
+}
+
+static int edid_parse_CEA(char *edid, struct edid_info_t *info)
+{
+	char *block, *block_end;
+	char checksum = 0;
+	int i, len;
+	char audio_format;
+	int num = 0, sadcnt_in_block;
+
+	memset(edid_parsed.sad, 0, sizeof(edid_parsed.sad));
+
+	if (edid[0] != 0x2)
+		return -1;
+
+	for (i = 0; i < EDID_LENGTH; i++)
+		checksum += edid[i];
+
+	if (checksum != 0) {
+		DPRINT("*E* CEA EDID checksum (0x%02x) - data is corrupt\n",
+			checksum);
+		info->option |= (EDID_OPT_HDMI + EDID_OPT_AUDIO);
+		edid_dump(edid);
+		return -1;
+	}
+
+	if(edid_msg_enable)
+		edid_dump(edid);
+
+	DBGMSG("[EDID] CEA EDID Version %d.%d\n", edid[0], edid[1]);
+
+	if (edid[1] >= 2) {
+		info->option |= (edid[3] & 0xF0);
+		DBGMSG("\t%s support 422\n", (edid[3] & 0x10) ? "" : "no");
+		DBGMSG("\t%s support 444\n", (edid[3] & 0x20) ? "" : "no");
+		DBGMSG("\t%s support audio\n", (edid[3] & 0x40) ? "" : "no");
+		DBGMSG("\t%s support underscan\n",
+			(edid[3] & 0x80) ? "" : "no");
+	}
+
+	block_end = edid + edid[2];
+	block = edid + 4;
+	do {
+		len = block[0] & 0x1F;
+		switch (((block[0] & 0xE0) >> 5)) {
+		case 1:	/* Audio Data Block */
+			DBGMSG("Audio Data Block (0x%02X)\n", block[0]);
+			info->option |= EDID_OPT_AUDIO;
+			sadcnt_in_block = len / 3;
+
+			for (i = 0; i < sadcnt_in_block; i++) {
+				if (num < AUD_SAD_NUM) {
+					edid_parsed.sad[num].flag = 1;
+					edid_parsed.sad[num].sad_byte[0] =
+						block[i * 3 + 1];
+					edid_parsed.sad[num].sad_byte[1] =
+						block[i * 3 + 2];
+					edid_parsed.sad[num].sad_byte[2] =
+						block[i * 3 + 3];
+					num++;
+				} else {
+					DPRINT("Lose SAD info:%02X %02X %02X\n",
+						block[i * 3 + 1],
+						block[i * 3 + 2],
+						block[i * 3 + 3]);
+				}
+
+				DBGMSG("\t ======== SDA %d ========\n", i);
+				DBGMSG("\t SDA Data: 0x%02X 0x%02X 0x%02X\n",
+					block[i * 3 + 1],
+					block[i * 3 + 2],
+					block[i * 3 + 3]);
+
+				audio_format = (block[i * 3 + 1] & 0x78) >> 3;
+				switch (audio_format) {
+				default:
+				case 0: /* reserved */
+				case 15:/* reserved */
+					DBGMSG("\t Reserved Audio Fmt\n");
+				break;
+				case 1: /* LPCM */
+					DBGMSG("\t Audio Fmt: LPCM\n");
+				break;
+				case 2: /* AC3 */
+					DBGMSG("\t Audio Fmt: AC3\n");
+				break;
+				case 3: /* MPEG1 */
+					DBGMSG("\t Audio Fmt: MPEG1\n");
+				break;
+				case 4: /* MP3 */
+					DBGMSG("\t Audio Fmt: MP3\n");
+				break;
+				case 5: /* MPEG2 */
+					DBGMSG("\t Audio Fmt: MPEG2\n");
+				break;
+				case 6: /* AAC */
+					DBGMSG("\t Audio Fmt: AAC\n");
+				break;
+				case 7: /* DTS */
+					DBGMSG("\t Audio Fmt: DTS\n");
+				break;
+				case 8: /* ATRAC */
+					DBGMSG("\t Audio Fmt: ATRAC\n");
+				break;
+				case 9: /* One bit audio */
+					DBGMSG("\t Audio Fmt: ONE BIT AUDIO\n");
+				break;
+				case 10:/* Dolby */
+					DBGMSG("\t Audio Fmt: DOLBY\n");
+				break;
+				case 11:/* DTS-HD */
+					DBGMSG("\t Audio Fmt: DTS-HD\n");
+				break;
+				case 12:/* MAT (MLP) */
+					DBGMSG("\t Audio Fmt: MAT\n");
+				break;
+				case 13:/* DST */
+					DBGMSG("\t Audio Fmt: DST\n");
+				break;
+				case 14:/* WMA Pro */
+					DBGMSG("\t Audio Fmt: WMA Pro\n");
+				break;
+				}
+
+				DBGMSG("\t Max channel: %d\n",
+					(block[i * 3 + 1] & 0x7) + 1);
+				DBGMSG("\t %s support 32 KHz\n",
+					(block[i * 3 + 2] & 0x1) ? "" : "no");
+				DBGMSG("\t %s support 44 KHz\n",
+					(block[i * 3 + 2] & 0x2) ? "" : "no");
+				DBGMSG("\t %s support 48 KHz\n",
+					(block[i * 3 + 2] & 0x4) ? "" : "no");
+				DBGMSG("\t %s support 88 KHz\n",
+					(block[i * 3 + 2] & 0x8) ? "" : "no");
+				DBGMSG("\t %s support 96 KHz\n",
+					(block[i * 3 + 2] & 0x10) ? "" : "no");
+				DBGMSG("\t %s support 176 KHz\n",
+					(block[i * 3 + 2] & 0x20) ? "" : "no");
+				DBGMSG("\t %s support 192 KHz\n",
+					(block[i * 3 + 2] & 0x40) ? "" : "no");
+				if (audio_format == 1) { /* For LPCM */
+					DBGMSG("\t %s support 16 bit\n",
+						(block[i * 3 + 3] & 0x1) ?
+						"" : "no");
+					DBGMSG("\t %s support 20 bit\n",
+						(block[i * 3 + 3] & 0x2) ?
+						"" : "no");
+					DBGMSG("\t %s support 24 bit\n",
+						(block[i * 3 + 3] & 0x4) ?
+						"" : "no");
+				} else if (audio_format >= 2 &&
+					audio_format <= 8) {
+					/* From AC3 to ATRAC */
+					DBGMSG("\t Max bitrate: %d kbit/s\n",
+						block[i * 3 + 3] * 8);
+				} else if (audio_format >= 9 &&
+					audio_format <= 14) {
+					/* From One-bit-audio to WMA Pro*/
+					DBGMSG("\t Audio Format Code:0x%02X\n",
+					block[i * 3 + 3]);
+				}
+				DBGMSG("\t ========================\n");
+			}
+			break;
+		case 2:	/* Video Data Block */
+			DBGMSG("Video Data Block\n");
+			for (i = 0; i < len; i++) {
+				unsigned int vic;
+
+				vic = block[1 + i] & 0x7F;
+				info->cea_vic[vic / 8] |= (0x1 << (vic % 8));
+				if (i < 16)
+					info->vic_3d[i].vic = vic;
+				DBGMSG("\t %2d : VIC %2d %dx%d@%d%s %s\n", i,
+					vic, hdmi_vic_info[vic].resx,
+					hdmi_vic_info[vic].resy,
+					hdmi_vic_info[vic].freq,
+					(hdmi_vic_info[vic].option
+					& HDMI_VIC_INTERLACE) ? "I" : "P",
+					(hdmi_vic_info[vic].option
+					& HDMI_VIC_4x3) ? "4:3" : "16:9");
+			}
+			break;
+		case 3: /* Vendor Spec Data Block */
+			edid_parse_CEA_VendorSpecDataBlock(block, len, info);
+			break;
+		case 4:	/* Speaker Allocation Data Block */
+			DBGMSG("Speaker Allocation Data Block\n");
+			break;
+		case 5:	/* VESA DTC Data Block */
+			DBGMSG("VESA DTC Data Block\n");
+			break;
+		case 7:	/* Use Extended Tag */
+			DBGMSG("Use Extended Tag\n");
+			break;
+		case 0:	/* Reserved */
+		default:
+			len = 0;
+			break;
+		}
+		block += (1 + len);
+	} while (block < block_end);
+
+	{
+	struct fb_videomode *p;
+	unsigned int fps;
+
+	DBGMSG("Detail Timing\n");
+	block = edid + edid[2];
+	len = (128 - edid[2]) / 18;
+	for (i = 0; i < len; i++, block += 18) {
+		p = &info->cea_timing[i];
+		p->pixclock = ((block[1] << 8) + block[0]) * 10000;
+		if (p->pixclock == 0)
+			break;
+		p->xres = ((block[4] & 0xF0) << 4) + block[2];
+		p->left_margin = ((block[4] & 0x0F) << 8) + block[3];
+		p->yres = ((block[7] & 0xF0) << 4) + block[5];
+		p->upper_margin = ((block[7] & 0x0F) << 8) + block[6];
+		fps = vpp_calc_refresh(p->pixclock, p->xres + p->left_margin,
+			p->yres + p->upper_margin);
+		p->right_margin = ((block[11] & 0xC0) << 2) + block[8];
+		p->hsync_len = ((block[11] & 0x30) << 4) + block[9];
+		p->left_margin = p->left_margin -
+			p->right_margin - p->hsync_len;
+		p->lower_margin = ((block[11] & 0x0C) << 2) +
+			((block[10] & 0xF0) >> 4);
+		p->vsync_len = ((block[11] & 0x03) << 4) + (block[10] & 0x0F);
+		p->upper_margin = p->upper_margin -
+			p->lower_margin - p->vsync_len;
+		p->refresh = fps;
+		p->vmode = (block[17] & 0x80) ?
+			FB_VMODE_INTERLACED : FB_VMODE_NONINTERLACED;
+		p->sync = (block[17] & 0x04) ? FB_SYNC_VERT_HIGH_ACT : 0;
+		p->sync |= (block[17] & 0x02) ? FB_SYNC_HOR_HIGH_ACT : 0;
+		if (p->vmode & FB_VMODE_INTERLACED) {
+			p->yres *= 2;
+			p->upper_margin *= 2;
+			p->lower_margin *= 2;
+			p->vsync_len *= 2;
+		}
+		DBGMSG("\t%dx%d%s@%d,clk %d\n", p->xres, p->yres,
+			(block[17] & 0x80) ? "I" : "P", fps, p->pixclock);
+		DBGMSG("\t\tH bp %d,sync %d,fp %d\n",
+			p->left_margin, p->hsync_len, p->right_margin);
+		DBGMSG("\t\tV bp %d,sync %d,fp %d\n",
+			p->upper_margin, p->vsync_len, p->lower_margin);
+		DBGMSG("\t\thsync %d,vsync %d\n",
+			(p->sync & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0,
+			(p->sync & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0);
+			p->pixclock = KHZ2PICOS(p->pixclock / 1000);
+	}
+	}
+	return 0;
+}
+
+void edid_dump(char *edid)
+{
+	int i;
+
+	DPRINT("===================== EDID BlOCK =====================");
+	for (i = 0; i < 128; i++) {
+		if ((i % 16) == 0)
+			DPRINT("\n");
+		DPRINT("%02x ", edid[i]);
+	}
+	DPRINT("\n");
+	DPRINT("======================================================\n");
+}
+
+int edid_checksum(char *edid, int len)
+{
+	char checksum = 0;
+	int i;
+
+	for (i = 0; i < len; i++)
+		checksum += edid[i];
+
+	if (checksum) {
+#ifdef DEBUG
+		edid_dump(edid);
+#endif
+	}
+	return checksum;
+}
+
+int edid_parse(char *edid, struct edid_info_t *info)
+{
+	int ext_cnt = 0;
+
+	if (edid == 0)
+		return 0;
+
+	if (info->option & EDID_OPT_VALID) {
+		DBG_MSG("[EDID] parse exist\n");
+		return info->option;
+	}
+
+	DBG_MSG("[EDID] Enter\n");
+
+	memset(info, 0, sizeof(struct edid_info_t));
+	info->option = EDID_OPT_VALID;
+	if (edid_parse_v1(edid, info) == 0) {
+		ext_cnt = edid[0x7E];
+		if (ext_cnt >= EDID_BLOCK_MAX) {
+			DPRINT("[EDID] *W* ext block cnt %d\n", ext_cnt);
+			ext_cnt = EDID_BLOCK_MAX - 1;
+		}
+	} else {
+		info->option = 0;
+		return 0;
+	}
+
+	while (ext_cnt) {
+		edid += 128;
+		ext_cnt--;
+		if (edid_parse_CEA(edid, info) == 0)
+			continue;
+
+		DPRINT("*W* not support EDID\n");
+		edid_dump(edid);
+	}
+	return info->option;
+}
+
+int edid_find_support(struct edid_info_t *info, unsigned int resx,
+	unsigned int resy, int freq, struct fb_videomode **vmode)
+{
+	struct fb_videomode *p;
+	int temp;
+	int ret;
+	int i;
+
+	ret = 0;
+	*vmode = 0;
+
+	if (!info)
+		return 0;
+
+	/* find detail timing */
+	for (i = 0; i < 4; i++) {
+		p = &info->detail_timing[i];
+		if (p->pixclock == 0)
+			continue;
+		if (resx != p->xres)
+			continue;
+		if (resy != p->yres)
+			continue;
+
+		temp = p->refresh;
+		temp |= (p->vmode & FB_VMODE_INTERLACED) ?
+			EDID_TMR_INTERLACE : 0;
+		if (freq != temp)
+			continue;
+		*vmode = p;
+		ret = 3;
+		goto find_end;
+	}
+
+	/* find cea timing */
+	for (i = 0; i < 6; i++) {
+		p = &info->cea_timing[i];
+
+		if (p->pixclock == 0)
+			continue;
+		if (resx != p->xres)
+			continue;
+		if (resy != p->yres)
+			continue;
+
+		temp = p->refresh;
+		temp |= (p->vmode & FB_VMODE_INTERLACED) ?
+			EDID_TMR_INTERLACE : 0;
+		if (freq != temp)
+			continue;
+
+		*vmode = p;
+		ret = 4;
+		goto find_end;
+	}
+
+	/* find vic timing */
+	for (i = 0; i < 64; i++) {
+		if ((info->cea_vic[i / 8] & (0x1 << (i % 8))) == 0)
+			continue;
+
+		if (i >= HDMI_VIDEO_CODE_MAX)
+			continue;
+
+		if (resx != hdmi_vic_info[i].resx)
+			continue;
+		if (resy != hdmi_vic_info[i].resy)
+			continue;
+		temp = hdmi_vic_info[i].freq;
+		temp |= (hdmi_vic_info[i].option & HDMI_VIC_INTERLACE) ?
+			EDID_TMR_INTERLACE : 0;
+		if (freq != temp)
+			continue;
+		ret = 5;
+		goto find_end;
+	}
+
+	/* find established timing */
+	if (info->establish_timing) {
+		for (i = 0; i < 17; i++) {
+			if (info->establish_timing & (0x1 << i)) {
+				if ((resx == edid_establish_timing[i].resx) &&
+				(resy == edid_establish_timing[i].resy)) {
+					if (freq ==
+						edid_establish_timing[i].freq) {
+						ret = 1;
+						goto find_end;
+					}
+				}
+			}
+		}
+	}
+
+	/* find standard timing */
+	for (i = 0; i < 8; i++) {
+		if (info->standard_timing[i].resx == 0)
+			continue;
+		if ((resx == info->standard_timing[i].resx) &&
+			(resy == info->standard_timing[i].resy)) {
+			if (freq == info->standard_timing[i].freq) {
+				ret = 2;
+				goto find_end;
+			}
+		}
+	}
+
+find_end:
+#if 0
+	if ((resx == 1920) && (resy == 1080) && !(freq & EDID_TMR_INTERLACE))
+		ret = 0;
+#endif
+#if 0
+	if (!(freq & EDID_TMR_INTERLACE))
+		ret = 0;
+#endif
+#if 0
+	DPRINT("[EDID] %s support %dx%d@%d%s(ret %d)\n",
+		(ret) ? "" : "No", resx, resy, freq & EDID_TMR_FREQ,
+		(freq & EDID_TMR_INTERLACE) ? "I" : "P", ret);
+#endif
+	return ret;
+}
+
+unsigned int edid_get_hdmi_phy_addr(void)
+{
+	struct vout_t *vo;
+
+	vo = vout_get_entry(VPP_VOUT_NUM_HDMI);
+	return vo->edid_info.hdmi_phy_addr;
+}
+
+unsigned int edid_get_hdmi_3d_mask(struct edid_info_t *info, int vic)
+{
+	int i;
+
+	if (!info)
+		return 0;
+	for (i = 0; i < 16; i++) {
+		if (info->vic_3d[i].vic == vic)
+			return info->vic_3d[i].mask;
+	}
+	return 0;
+}
+
diff --git a/drivers/video/wmt/scl.c b/drivers/video/wmt/scl.c
new file mode 100755
index 00000000..f367a0dc
--- /dev/null
+++ b/drivers/video/wmt/scl.c
@@ -0,0 +1,1556 @@
+/*++
+ * linux/drivers/video/wmt/scl.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define SCL_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "scl.h"
+
+HW_REG struct scl_base1_regs *scl_regs1 = (void *) SCL_BASE_ADDR;
+HW_REG struct scl_base2_regs *scl_regs2 = (void *) SCL_BASE2_ADDR;
+
+#ifdef WMT_FTBLK_SCL
+void scl_reg_dump(void)
+{
+	vpp_set_clock_enable(DEV_SCL444U, 1, 0);
+
+	DPRINT("========== SCL register dump ==========\n");
+	vpp_reg_dump(REG_SCL_BASE1_BEGIN,
+		REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN);
+	vpp_reg_dump(REG_SCL_BASE2_BEGIN,
+		REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN);
+
+	DPRINT("---------- SCL scale ----------\n");
+	DPRINT("scale enable %d\n", scl_regs1->en.b.alu_enable);
+	DPRINT("mode bilinear(H %d,V %d),recursive(H %d,V %d)\n",
+		scl_regs1->true_bilinear.b.h, scl_regs1->true_bilinear.b.v,
+		scl_regs2->recursive_mode.b.h, scl_regs2->recursive_mode.b.v);
+	DPRINT("src(%d,%d),dst(%d,%d)\n",
+		scl_regs1->r_h_size.b.pix_w, scl_regs1->vxwidth.b.vxwidth,
+		scl_regs1->hscale1.b.thr, scl_regs1->vscale1.b.thr);
+	DPRINT("scale width H %d,V %d\n",
+		scl_regs1->hxwidth.b.hxwidth, scl_regs1->vxwidth.b.vxwidth);
+	DPRINT("H scale up %d,V scale up %d\n",
+		scl_regs1->sclup_en.b.h, scl_regs1->sclup_en.b.v);
+	DPRINT("H sub step %d,thr %d,step %d,sub step cnt %d,i step cnt %d\n",
+		scl_regs1->hscale1.b.substep, scl_regs1->hscale1.b.thr,
+		scl_regs1->hscale2.b.step, scl_regs1->hscale2.b.substepcnt,
+		scl_regs1->hscale3.b.stepcnt);
+	DPRINT("V sub step %d,thr %d,step %d,sub step cnt %d,i step cnt %d\n",
+		scl_regs1->vscale1.b.substep, scl_regs1->vscale1.b.thr,
+		scl_regs1->vscale2.b.step, scl_regs1->vscale2.b.substepcnt,
+		scl_regs1->vscale3.b.stepcnt);
+
+	DPRINT("---------- SCL filter ----------\n");
+	DPRINT("DEBLOCK %d,boundary 1st 0x%x,2nd 0x%x\n,",
+		scl_regs2->field_mode.b.deblock,
+		scl_regs2->dblk_threshold.b.layer1_boundary,
+		scl_regs2->dblk_threshold.b.layer2_boundary);
+	DPRINT("FIELD DEFLICKER %d,up %s down,thr Y %d,C %d\n",
+		scl_regs2->field_mode.b.field_deflicker,
+		(scl_regs2->field_mode.b.field_deflicker) ? "&" : "or",
+		scl_regs2->field_flicker.b.y_thd,
+		scl_regs2->field_flicker.b.c_thd);
+	DPRINT("FRAME DEFLICKER %d,%s,2^%d,scene chg %d\n",
+		scl_regs2->field_mode.b.frame_deflicker,
+		(scl_regs2->frame_flicker.b.rgb) ? "RGB" : "Y",
+		scl_regs2->frame_flicker.b.sampler,
+		scl_regs2->frame_flicker.b.scene_chg_thd);
+	DPRINT("CSC enable %d,CSC clamp %d\n",
+		scl_regs2->csc_ctl.b.enable,
+		scl_regs2->csc_ctl.b.clamp_enable);
+	DPRINT("---------- SCL TG ----------\n");
+	DPRINT("TG source : %s\n",
+		(scl_regs1->tg_govw.b.enable) ? "GOVW" : "SCL");
+	DPRINT("TG enable %d, wait ready enable %d\n",
+		scl_regs1->tg_ctl.b.enable,
+		scl_regs1->tg_ctl.b.watchdog_enable);
+	DPRINT("clk %d,Read cyc %d,1T %d\n",
+		vpp_get_base_clock(VPP_MOD_SCL),
+		scl_regs1->tg_ctl.b.rdcyc, scl_regs2->readcyc_1t.b.rdcyc_1t);
+	DPRINT("H total %d, beg %d, end %d\n",
+		scl_regs1->tg_total.b.h_allpixel,
+		scl_regs1->tg_h_active.b.h_actbg,
+		scl_regs1->tg_h_active.b.h_actend);
+	DPRINT("V total %d, beg %d, end %d\n",
+		scl_regs1->tg_total.b.v_allline,
+		scl_regs1->tg_v_active.b.v_actbg,
+		scl_regs1->tg_v_active.b.v_actend);
+	DPRINT("VBIE %d,PVBI %d\n",
+		scl_regs1->tg_vbi.b.vbie, scl_regs1->tg_vbi.b.pvbi);
+	DPRINT("Watch dog 0x%x\n",
+		scl_regs1->tg_watchdog);
+	DPRINT("---------- SCLR FB ----------\n");
+	DPRINT("SCLR MIF enable %d\n",
+		scl_regs1->r_ctl.b.mif_enable);
+	DPRINT("color format %s\n", vpp_colfmt_str[sclr_get_color_format()]);
+	DPRINT("color bar enable %d,mode %d,inv %d\n",
+		scl_regs1->r_ctl.b.colorbar_enable,
+		scl_regs1->r_ctl.b.colorbar_mode,
+		scl_regs1->r_ctl.b.colorbar_inv);
+	DPRINT("sourc mode : %s,H264 %d\n",
+		(scl_regs1->r_ctl.b.field) ? "field" : "frame",
+		scl_regs1->r_ctl.b.h264);
+	DPRINT("Y addr 0x%x, C addr 0x%x\n",
+		scl_regs1->r_ysa, scl_regs1->r_csa);
+	DPRINT("width %d, fb width %d\n",
+		scl_regs1->r_h_size.b.pix_w, scl_regs1->r_h_size.b.fb_w);
+	DPRINT("H crop %d, V crop %d\n",
+		scl_regs1->r_crop.b.hcrop, scl_regs1->r_crop.b.vcrop);
+	DPRINT("---------- SCLW FB ----------\n");
+	DPRINT("SCLW MIF enable %d\n", scl_regs1->w_ctl.b.mif_enable);
+	DPRINT("color format %s\n", vpp_colfmt_str[sclw_get_color_format()]);
+	DPRINT("Y addr 0x%x, C addr 0x%x\n",
+		scl_regs1->w_ysa, scl_regs1->w_csa);
+	DPRINT("Y width %d, fb width %d\n",
+		scl_regs1->w_y_time.b.pxl_w, scl_regs1->w_y_time.b.fb_w);
+	DPRINT("C width %d, fb width %d\n",
+		scl_regs1->w_c_time.b.pxl_w, scl_regs1->w_c_time.b.fb_w);
+	DPRINT("Y err %d, C err %d\n",
+		scl_regs1->w_ff_ctl.b.mif_y_err,
+		scl_regs1->w_ff_ctl.b.mif_c_err);
+	DPRINT("---------- SCLR2 FB ----------\n");
+	DPRINT("MIF enable %d\n", scl_regs1->r2_ctl.b.mif_en);
+	DPRINT("color format %s\n", vpp_colfmt_str[scl_R2_get_color_format()]);
+	DPRINT("color bar enable %d,mode %d,inv %d\n",
+		scl_regs1->r2_ctl.b.color_en,
+		scl_regs1->r2_ctl.b.color_wide,
+		scl_regs1->r2_ctl.b.color_inv);
+	DPRINT("sourc mode : %s,H264 %d\n",
+		(scl_regs1->r2_ctl.b.iofmt) ? "field" : "frame",
+		scl_regs1->r2_ctl.b.h264_fmt);
+	DPRINT("Y addr 0x%x, C addr 0x%x\n",
+		scl_regs1->r2_ysa, scl_regs1->r2_csa);
+	DPRINT("width %d, fb width %d\n",
+		scl_regs1->r2_h_size.b.lnsize, scl_regs1->r2_h_size.b.fbw);
+	DPRINT("H crop %d, V crop %d\n",
+		scl_regs1->r2_crop.b.hcrop, scl_regs1->r2_crop.b.vcrop);
+	DPRINT("---------- ALPHA ----------\n");
+	DPRINT("src alpha %d,dst alpha %d,swap %d\n",
+		scl_regs1->alpha_md.b.src,
+		scl_regs1->alpha_md.b.dst,
+		scl_regs1->alpha_md.b.swap);
+	DPRINT("src fix 0x%x,dst fix 0x%x\n",
+		scl_regs1->alpha_fxd.b.src_fixed,
+		scl_regs1->alpha_fxd.b.dst_fixed);
+	DPRINT("---------- ColorKey ----------\n");
+	DPRINT("enable %d\n", scl_regs1->alpha_colorkey.b.enable);
+	DPRINT("from %s,comp %d,mode %d\n",
+		(scl_regs1->alpha_colorkey.b.from) ? "mif2" : "mif1",
+		scl_regs1->alpha_colorkey.b.comp,
+		scl_regs1->alpha_colorkey.b.mode);
+	DPRINT("R 0x%x,G 0x%x,B 0x%x\n",
+		scl_regs1->alpha_colorkey_rgb.b.r,
+		scl_regs1->alpha_colorkey_rgb.b.g,
+		scl_regs1->alpha_colorkey_rgb.b.b);
+	DPRINT("---------- sw status ----------\n");
+	DPRINT("complete %d\n", p_scl->scale_complete);
+
+	vpp_set_clock_enable(DEV_SCL444U, 0, 0);
+}
+
+void scl_set_enable(vpp_flag_t enable)
+{
+	scl_regs1->en.b.alu_enable = enable;
+}
+
+void scl_set_reg_update(vpp_flag_t enable)
+{
+	scl_regs1->upd.b.reg_update = enable;
+}
+
+void scl_set_reg_level(vpp_reglevel_t level)
+{
+	scl_regs1->sel.b.reg_level = level;
+}
+
+void scl_set_int_enable(vpp_flag_t enable, enum vpp_int_t int_bit)
+{
+	/* clean status first before enable/disable interrupt */
+	scl_clean_int_status(int_bit);
+
+	if (int_bit & VPP_INT_ERR_SCL_TG)
+		scl_regs1->w_int_en.b.tg_err = enable;
+	if (int_bit & VPP_INT_ERR_SCLR1_MIF)
+		scl_regs1->w_int_en.b.r1_mif_enable = enable;
+	if (int_bit & VPP_INT_ERR_SCLR2_MIF)
+		scl_regs1->w_int_en.b.r2_mif_enable = enable;
+	if (int_bit & VPP_INT_ERR_SCLW_MIFRGB)
+		scl_regs1->w_int_en.b.mif_rgb_err = enable;
+	if (int_bit & VPP_INT_ERR_SCLW_MIFY)
+		scl_regs1->w_int_en.b.mif_y_err = enable;
+	if (int_bit & VPP_INT_ERR_SCLW_MIFC)
+		scl_regs1->w_int_en.b.mif_c_err = enable;
+}
+
+enum vpp_int_err_t scl_get_int_status(void)
+{
+	enum vpp_int_err_t int_sts;
+
+	int_sts = 0;
+	if (scl_regs1->tg_sts.b.tgerr)
+		int_sts |= VPP_INT_ERR_SCL_TG;
+	if (scl_regs1->r_fifo_ctl.b.r1_mif_err)
+		int_sts |= VPP_INT_ERR_SCLR1_MIF;
+	if (scl_regs1->r_fifo_ctl.b.r2_mif_err)
+		int_sts |= VPP_INT_ERR_SCLR2_MIF;
+	if (scl_regs1->w_ff_ctl.b.mif_rgb_err)
+		int_sts |= VPP_INT_ERR_SCLW_MIFRGB;
+	if (scl_regs1->w_ff_ctl.b.mif_y_err)
+		int_sts |= VPP_INT_ERR_SCLW_MIFY;
+	if (scl_regs1->w_ff_ctl.b.mif_c_err)
+		int_sts |= VPP_INT_ERR_SCLW_MIFC;
+	return int_sts;
+}
+
+void scl_clean_int_status(enum vpp_int_err_t int_sts)
+{
+	if (int_sts & VPP_INT_ERR_SCL_TG)
+		scl_regs1->tg_sts.val = BIT0;
+	if (int_sts & VPP_INT_ERR_SCLR1_MIF)
+		scl_regs1->r_fifo_ctl.val =
+			(scl_regs1->r_fifo_ctl.val & ~0x300) | BIT8;
+	if (int_sts & VPP_INT_ERR_SCLR2_MIF)
+		scl_regs1->r_fifo_ctl.val =
+			(scl_regs1->r_fifo_ctl.val & ~0x300) | BIT9;
+	if (int_sts & VPP_INT_ERR_SCLW_MIFRGB)
+		scl_regs1->w_ff_ctl.val = BIT16;
+	if (int_sts & VPP_INT_ERR_SCLW_MIFY)
+		scl_regs1->w_ff_ctl.val = BIT8;
+	if (int_sts & VPP_INT_ERR_SCLW_MIFC)
+		scl_regs1->w_ff_ctl.val = BIT0;
+}
+
+void scl_set_csc_mode(vpp_csc_t mode)
+{
+	vdo_color_fmt src_fmt, dst_fmt;
+
+	src_fmt = sclr_get_color_format();
+	dst_fmt = sclw_get_color_format();
+	mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, 0);
+	if (p_scl->abgr_mode) {
+		unsigned int parm[5];
+
+		parm[0] = (vpp_csc_parm[mode][1] & 0xFFFF) |
+			(vpp_csc_parm[mode][0] & 0xFFFF0000); /* C3,C2 */
+		parm[1] = (vpp_csc_parm[mode][0] & 0xFFFF) |
+			(vpp_csc_parm[mode][2] & 0xFFFF0000); /* C1,C6 */
+		parm[2] = (vpp_csc_parm[mode][2] & 0xFFFF) |
+			(vpp_csc_parm[mode][1] & 0xFFFF0000); /* C5,C4 */
+		parm[3] = (vpp_csc_parm[mode][4] & 0xFFFF) |
+			(vpp_csc_parm[mode][3] & 0xFFFF0000); /* C9,C8 */
+		parm[4] = (vpp_csc_parm[mode][3] & 0xFFFF) |
+			(vpp_csc_parm[mode][4] & 0xFFFF0000); /* C7,I */
+
+		scl_regs2->csc1 = parm[0];
+		scl_regs2->csc2 = parm[1];
+		scl_regs2->csc3 = parm[2];
+		scl_regs2->csc4 = parm[3];
+		scl_regs2->csc5 = parm[4];
+	} else {
+		scl_regs2->csc1 = vpp_csc_parm[mode][0];
+		scl_regs2->csc2 = vpp_csc_parm[mode][1];
+		scl_regs2->csc3 = vpp_csc_parm[mode][2];
+		scl_regs2->csc4 = vpp_csc_parm[mode][3];
+		scl_regs2->csc5 = vpp_csc_parm[mode][4];
+	}
+	scl_regs2->csc6 = vpp_csc_parm[mode][5];
+	scl_regs2->csc_ctl.val = vpp_csc_parm[mode][6];
+	scl_regs2->csc_ctl.b.enable = (mode >= VPP_CSC_MAX) ? 0 : 1;
+}
+
+void scl_set_scale_enable(vpp_flag_t vscl_enable, vpp_flag_t hscl_enable)
+{
+	DBGMSG("V %d,H %d\n", vscl_enable, hscl_enable);
+	scl_regs1->sclup_en.b.v = vscl_enable;
+	scl_regs1->sclup_en.b.h = hscl_enable;
+}
+
+void scl_set_V_scale(int A, int B) /* A dst,B src */
+{
+	unsigned int V_STEP;
+	unsigned int V_SUB_STEP;
+	unsigned int V_THR_DIV2;
+
+	DBG_DETAIL("scl_set_V_scale(%d,%d)\r\n", A, B);
+	if (A > B) {
+		V_STEP = (B - 1) * 16 / A;
+		V_SUB_STEP = (B - 1) * 16  % A;
+	} else {
+		V_STEP = (16 * B / A);
+		V_SUB_STEP = ((16 * B) % A);
+	}
+	V_THR_DIV2 = A;
+
+	DBG_DETAIL("V step %d,sub step %d, div2 %d\r\n",
+				V_STEP, V_SUB_STEP, V_THR_DIV2);
+
+	scl_regs1->vxwidth.b.dst_vxwidth = (A > B) ? A : B;
+	scl_regs1->vxwidth.b.vxwidth = B;
+	scl_regs1->vscale2.b.step = V_STEP;
+	scl_regs1->vscale1.b.substep = V_SUB_STEP;
+	scl_regs1->vscale1.b.thr = V_THR_DIV2;
+	scl_regs1->vscale2.b.substepcnt = 0;
+}
+
+void scl_set_H_scale(int A, int B) /* A dst,B src */
+{
+	unsigned int H_STEP;
+	unsigned int H_SUB_STEP;
+	unsigned int H_THR_DIV2;
+
+	DBG_DETAIL("scl_set_H_scale(%d,%d)\r\n", A, B);
+	if (A > B) {
+		H_STEP = (B - 1) * 16 / A;
+		H_SUB_STEP = (B - 1) * 16  % A;
+	} else {
+		H_STEP = (16 * B / A);
+		H_SUB_STEP = ((16 * B) % A);
+	}
+	H_THR_DIV2 = A;
+	DBG_DETAIL("H step %d,sub step %d, div2 %d\r\n",
+				H_STEP, H_SUB_STEP, H_THR_DIV2);
+	scl_regs1->hxwidth.b.hxwidth = ((A > B) ? A : B);
+	scl_regs1->hscale2.b.step = H_STEP;
+	scl_regs1->hscale1.b.substep = H_SUB_STEP;
+	scl_regs1->hscale1.b.thr = H_THR_DIV2;
+	scl_regs1->hscale2.b.substepcnt = 0;
+}
+
+void scl_set_crop(int offset_x, int offset_y)
+{
+	/* offset_x &= VPU_CROP_ALIGN_MASK; */ /* ~0x7 */
+	offset_x &= ~0xf;
+
+	scl_regs1->hscale3.b.stepcnt = offset_x * 16;
+	scl_regs1->vscale3.b.stepcnt = offset_y * 16;
+	DBGMSG("[VPU] crop - x : 0x%x, y : 0x%x \r\n",
+				offset_x * 16, offset_y * 16);
+}
+
+void scl_set_tg_enable(vpp_flag_t enable)
+{
+	scl_regs1->tg_ctl.b.enable = enable;
+}
+
+unsigned int scl_set_clock(unsigned int pixel_clock)
+{
+	unsigned int rd_cyc;
+	rd_cyc = vpp_get_base_clock(VPP_MOD_SCL) / pixel_clock;
+	return rd_cyc;
+}
+
+void scl_set_timing(vpp_clock_t *timing, unsigned int pixel_clock)
+{
+#if 1
+	timing->read_cycle = WMT_SCL_RCYC_MIN;
+#else
+	timing->read_cycle = scl_set_clock(pixel_clock * 2) - 1;
+	timing->read_cycle = (timing->read_cycle < WMT_SCL_RCYC_MIN) ?
+		WMT_SCL_RCYC_MIN : timing->read_cycle;
+	timing->read_cycle = (timing->read_cycle > 255) ?
+		0xFF : timing->read_cycle;
+#endif
+	scl_regs1->tg_ctl.b.rdcyc = timing->read_cycle;
+	scl_regs2->readcyc_1t.b.rdcyc_1t = (timing->read_cycle) ? 0 : 1;
+	scl_regs1->tg_total.b.h_allpixel = timing->total_pixel_of_line;
+	scl_regs1->tg_h_active.b.h_actbg = timing->begin_pixel_of_active;
+	scl_regs1->tg_h_active.b.h_actend = timing->end_pixel_of_active;
+	scl_regs1->tg_total.b.v_allline = timing->total_line_of_frame;
+	scl_regs1->tg_v_active.b.v_actbg = timing->begin_line_of_active;
+	scl_regs1->tg_v_active.b.v_actend = timing->end_line_of_active;
+	scl_regs1->tg_vbi.b.vbie = timing->line_number_between_VBIS_VBIE;
+	scl_regs1->tg_vbi.b.pvbi = timing->line_number_between_PVBI_VBIS;
+#ifdef DEBUG_DETAIL
+	vpp_show_timing("scl set timing", 0, timing);
+#endif
+}
+
+void scl_get_timing(vpp_clock_t *p_timing)
+{
+	p_timing->read_cycle = scl_regs1->tg_ctl.b.rdcyc;
+	p_timing->total_pixel_of_line = scl_regs1->tg_total.b.h_allpixel;
+	p_timing->begin_pixel_of_active = scl_regs1->tg_h_active.b.h_actbg;
+	p_timing->end_pixel_of_active = scl_regs1->tg_h_active.b.h_actend;
+	p_timing->total_line_of_frame = scl_regs1->tg_total.b.v_allline;
+	p_timing->begin_line_of_active = scl_regs1->tg_v_active.b.v_actbg;
+	p_timing->end_line_of_active = scl_regs1->tg_v_active.b.v_actend;
+	p_timing->line_number_between_VBIS_VBIE = scl_regs1->tg_vbi.b.vbie;
+	p_timing->line_number_between_PVBI_VBIS = scl_regs1->tg_vbi.b.pvbi;
+}
+
+void scl_set_watchdog(U32 count)
+{
+	if (0 != count) {
+		scl_regs1->tg_watchdog = count;
+		scl_regs1->tg_ctl.b.watchdog_enable = 1;
+	} else
+		scl_regs1->tg_ctl.b.watchdog_enable = 0;
+}
+
+void scl_set_timing_master(vpp_mod_t mod_bit)
+{
+	scl_regs1->tg_govw.b.enable = (mod_bit == VPP_MOD_GOVW) ? 1 : 0;
+}
+
+vpp_mod_t scl_get_timing_master(void)
+{
+	return (scl_regs1->tg_govw.b.enable) ? VPP_MOD_GOVW : VPP_MOD_SCL;
+}
+
+void scl_set_drop_line(vpp_flag_t enable)
+{
+	scl_regs1->scldw = enable;
+}
+
+/* only one feature can work, other should be disable */
+void scl_set_filter_mode(enum vpp_filter_mode_t mode, int enable)
+{
+	DBG_DETAIL("(%d,%d)\n", mode, enable);
+	if (mode != VPP_FILTER_SCALE) {
+		if (scl_regs1->sclup_en.b.v || scl_regs1->sclup_en.b.h)
+			DPRINT("[SCL] *W* filter can't work w scale\n");
+	}
+	scl_regs2->field_mode.b.deblock = 0;
+	scl_regs2->field_mode.b.field_deflicker = 0;
+	scl_regs2->field_mode.b.frame_deflicker = 0;
+	switch (mode) {
+	default:
+	case VPP_FILTER_SCALE: /* scale mode */
+		break;
+	case VPP_FILTER_DEBLOCK: /* deblock */
+		scl_regs2->field_mode.b.deblock = enable;
+		break;
+	case VPP_FILTER_FIELD_DEFLICKER: /* field deflicker */
+		scl_regs2->field_mode.b.field_deflicker = enable;
+		break;
+	case VPP_FILTER_FRAME_DEFLICKER: /* frame deflicker */
+		scl_regs2->field_mode.b.frame_deflicker = enable;
+		break;
+	}
+}
+
+enum vpp_filter_mode_t scl_get_filter_mode(void)
+{
+	if (scl_regs1->sclup_en.b.v || scl_regs1->sclup_en.b.h)
+		return VPP_FILTER_SCALE;
+
+	if (scl_regs2->field_mode.b.deblock)
+		return VPP_FILTER_DEBLOCK;
+
+	if (scl_regs2->field_mode.b.field_deflicker)
+		return VPP_FILTER_FIELD_DEFLICKER;
+
+	if (scl_regs2->field_mode.b.frame_deflicker)
+		return VPP_FILTER_FRAME_DEFLICKER;
+	return VPP_FILTER_SCALE;
+}
+
+void sclr_set_mif_enable(vpp_flag_t enable)
+{
+	scl_regs1->r_ctl.b.mif_enable = enable;
+}
+
+void sclr_set_mif2_enable(vpp_flag_t enable)
+{
+
+}
+
+void sclr_set_colorbar(vpp_flag_t enable, int width, int inverse)
+{
+	scl_regs1->r_ctl.b.colorbar_mode = width;
+	scl_regs1->r_ctl.b.colorbar_inv = inverse;
+	scl_regs1->r_ctl.b.colorbar_enable = enable;
+}
+
+void sclr_set_field_mode(vpp_display_format_t fmt)
+{
+	scl_regs1->r_ctl.b.src_disp_fmt = fmt;
+}
+
+void sclr_set_display_format(vpp_display_format_t source,
+				vpp_display_format_t target)
+{
+	scl_regs1->r_ctl.b.src_disp_fmt =
+		(source == VPP_DISP_FMT_FIELD) ? 1 : 0;
+	scl_regs1->r_ctl.b.field = (target == VPP_DISP_FMT_FIELD) ? 1 : 0;
+}
+
+void sclr_set_color_format(vdo_color_fmt format)
+{
+	p_scl->abgr_mode = 0;
+	if (format >= VDO_COL_FMT_ARGB) {
+		scl_regs1->r_ctl.b.rgb_mode =
+			(format == VDO_COL_FMT_RGB_565) ? 0x1 : 0x3;
+		if (format == VDO_COL_FMT_ABGR)
+			p_scl->abgr_mode = 1;
+		return;
+	}
+	scl_regs1->r_ctl.b.rgb_mode = 0;
+	scl_regs1->r_ctl.b.rgb = 0x0;
+	switch (format) {
+	case VDO_COL_FMT_YUV444:
+		scl_regs1->r_ctl.b.yuv = 0x2;
+		break;
+	case VDO_COL_FMT_YUV422H:
+		scl_regs1->r_ctl.b.yuv = 0x0;
+		break;
+	case VDO_COL_FMT_YUV420:
+		scl_regs1->r_ctl.b.yuv = 0x1;
+		break;
+	default:
+		DBG_ERR("color fmt %d\n", format);
+		return;
+	}
+}
+
+vdo_color_fmt sclr_get_color_format(void)
+{
+	switch (scl_regs1->r_ctl.b.rgb_mode) {
+	case 0x1:
+		return VDO_COL_FMT_RGB_565;
+	case 0x3:
+		return VDO_COL_FMT_ARGB;
+	default:
+		break;
+	}
+	switch (scl_regs1->r_ctl.b.yuv) {
+	case 0:
+		return VDO_COL_FMT_YUV422H;
+	case 1:
+		return VDO_COL_FMT_YUV420;
+	case 2:
+		return VDO_COL_FMT_YUV444;
+	default:
+		break;
+	}
+	return VDO_COL_FMT_YUV444;
+}
+
+void sclr_set_media_format(vpp_media_format_t format)
+{
+	scl_regs1->r_ctl.b.h264 = (format == VPP_MEDIA_FMT_H264) ? 1 : 0;
+}
+
+void sclr_set_fb_addr(U32 y_addr, U32 c_addr)
+{
+	unsigned int line_y, line_c;
+	unsigned int offset_y, offset_c;
+	unsigned int pre_y, pre_c;
+
+	DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", y_addr, c_addr);
+
+	offset_y = offset_c = 0;
+	line_y = line_c = scl_regs1->r_h_size.b.fb_w;
+	switch (sclr_get_color_format()) {
+	case VDO_COL_FMT_YUV420:
+		offset_c /= 2;
+		line_c = 0;
+		break;
+	case VDO_COL_FMT_YUV422H:
+		break;
+	case VDO_COL_FMT_ARGB:
+		offset_y *= 4;
+		line_y *= 4;
+		break;
+	case VDO_COL_FMT_RGB_565:
+		offset_y *= 2;
+		line_y *= 2;
+		break;
+	default:
+		offset_c *= 2;
+		line_c *= 2;
+		break;
+	}
+	pre_y = scl_regs1->r_ysa;
+	pre_c = scl_regs1->r_csa;
+	scl_regs1->r_ysa = y_addr + offset_y;
+	scl_regs1->r_csa = c_addr + offset_c;
+}
+
+void sclr_get_fb_addr(U32 *y_addr, U32 *c_addr)
+{
+	*y_addr = scl_regs1->r_ysa;
+	*c_addr = scl_regs1->r_csa;
+/*	DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", *y_addr, *c_addr); */
+}
+
+void sclr_set_width(U32 y_pixel, U32 y_buffer)
+{
+	scl_regs1->r_h_size.b.pix_w = y_pixel;
+	scl_regs1->r_h_size.b.fb_w = y_buffer;
+}
+
+void sclr_get_width(U32 *p_y_pixel, U32 *p_y_buffer)
+{
+	*p_y_pixel = scl_regs1->r_h_size.b.pix_w;
+	*p_y_buffer = scl_regs1->r_h_size.b.fb_w;
+}
+
+void sclr_set_crop(U32 h_crop, U32 v_crop)
+{
+	scl_regs1->r_crop.b.hcrop = h_crop;
+	scl_regs1->r_crop.b.vcrop = v_crop;
+}
+
+void sclr_get_fb_info(U32 *width, U32 *act_width,
+				U32 *x_offset, U32 *y_offset)
+{
+	*width = scl_regs1->r_h_size.b.fb_w;
+	*act_width = scl_regs1->r_h_size.b.pix_w;
+	*x_offset = scl_regs1->r_crop.b.hcrop;
+	*y_offset = scl_regs1->r_crop.b.vcrop;
+}
+
+void sclr_set_threshold(U32 value)
+{
+	scl_regs1->r_fifo_ctl.b.thr = value;
+}
+
+void sclw_set_mif_enable(vpp_flag_t enable)
+{
+	scl_regs1->w_ctl.b.mif_enable = enable;
+}
+
+void sclw_set_color_format(vdo_color_fmt format)
+{
+	/* 0-888(4 byte), 1-5515(2 byte), 2-666(4 byte), 3-565(2 byte) */
+	switch (format) {
+	case VDO_COL_FMT_RGB_666:
+		scl_regs1->w_ctl.b.rgb = 1;
+		scl_regs2->igs.b.mode = 2;
+		break;
+	case VDO_COL_FMT_RGB_565:
+		scl_regs1->w_ctl.b.rgb = 1;
+		scl_regs2->igs.b.mode = 3;
+		break;
+	case VDO_COL_FMT_RGB_1555:
+		scl_regs1->w_ctl.b.rgb = 1;
+		scl_regs2->igs.b.mode = 1;
+		break;
+	case VDO_COL_FMT_ARGB:
+		scl_regs1->w_ctl.b.rgb = 1;
+		scl_regs2->igs.b.mode = 0;
+		break;
+	case VDO_COL_FMT_YUV444:
+		scl_regs1->w_ctl.b.rgb = 0;
+		scl_regs1->w_ctl.b.yuv = 0;
+		scl_regs2->igs.b.mode = 0;
+		break;
+	case VDO_COL_FMT_YUV422H:
+	case VDO_COL_FMT_YUV420:
+		scl_regs1->w_ctl.b.rgb = 0;
+		scl_regs1->w_ctl.b.yuv = 1;
+		scl_regs2->igs.b.mode = 0;
+		break;
+	default:
+		DBGMSG("*E* check the parameter.\n");
+		return;
+	}
+}
+
+vdo_color_fmt sclw_get_color_format(void)
+{
+	if (scl_regs1->w_ctl.b.rgb) {
+		switch (scl_regs2->igs.b.mode) {
+		case 0:
+			return VDO_COL_FMT_ARGB;
+		case 1:
+			return VDO_COL_FMT_RGB_1555;
+		case 2:
+			return VDO_COL_FMT_RGB_666;
+		case 3:
+			return VDO_COL_FMT_RGB_565;
+		}
+	}
+
+	if (scl_regs1->w_ctl.b.yuv)
+		return VDO_COL_FMT_YUV422H;
+	return VDO_COL_FMT_YUV444;
+}
+
+void sclw_set_alpha(int enable, char data)
+{
+	scl_regs2->argb_alpha.b.data = data;
+	scl_regs2->argb_alpha.b.enable = enable;
+}
+
+void sclw_set_field_mode(vpp_display_format_t fmt)
+{
+	scl_regs1->r_ctl.b.field = fmt;
+}
+
+void sclw_set_fb_addr(U32 y_addr, U32 c_addr)
+{
+	DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", y_addr, c_addr);
+/*	if( (y_addr & 0x3f) || (c_addr & 0x3f) ){
+		DPRINT("[SCL] *E* addr should align 64\n");
+	} */
+	scl_regs1->w_ysa = y_addr;
+	scl_regs1->w_csa = c_addr;
+}
+
+void sclw_get_fb_addr(U32 *y_addr, U32 *c_addr)
+{
+	*y_addr = scl_regs1->w_ysa;
+	*c_addr = scl_regs1->w_csa;
+	DBGMSG("y_addr:0x%08x, c_addr:0x%08x\n", *y_addr, *c_addr);
+}
+
+void sclw_set_fb_width(U32 width, U32 buf_width)
+{
+	scl_regs1->w_y_time.b.pxl_w = width;
+	scl_regs1->w_y_time.b.fb_w = buf_width;
+	if (sclw_get_color_format() == VDO_COL_FMT_YUV444) {
+		scl_regs1->w_c_time.b.pxl_w = width;
+		scl_regs1->w_c_time.b.fb_w = buf_width * 2;
+	} else {
+		scl_regs1->w_c_time.b.pxl_w = width / 2;
+		scl_regs1->w_c_time.b.fb_w = buf_width;
+	}
+}
+
+void sclw_get_fb_width(U32 *width, U32 *buf_width)
+{
+	*width = scl_regs1->w_y_time.b.pxl_w;
+	*buf_width = scl_regs1->w_y_time.b.fb_w;
+}
+
+void scl_R2_set_mif_enable(int enable)
+{
+	scl_regs1->r2_ctl.b.mif_en = enable;
+}
+
+void scl_R2_set_colorbar(int enable, int wide, int inv)
+{
+	scl_regs1->r2_ctl.b.color_en = enable;
+	scl_regs1->r2_ctl.b.color_wide = wide;
+	scl_regs1->r2_ctl.b.color_inv = inv;
+}
+
+void scl_R2_set_color_format(vdo_color_fmt colfmt)
+{
+	if (colfmt >= VDO_COL_FMT_ARGB) {
+		scl_regs1->r2_ctl.b.rgb_mode =
+			(colfmt == VDO_COL_FMT_RGB_565) ? 0x1 : 0x3;
+		return;
+	}
+	scl_regs1->r2_ctl.b.rgb_mode = 0;
+	switch (colfmt) {
+	case VDO_COL_FMT_YUV444:
+		scl_regs1->r2_ctl.b.vfmt = 0x2;
+		break;
+	case VDO_COL_FMT_YUV422H:
+		scl_regs1->r2_ctl.b.vfmt = 0x0;
+		break;
+	case VDO_COL_FMT_YUV420:
+		scl_regs1->r2_ctl.b.vfmt = 0x1;
+		break;
+	default:
+		DBG_ERR("color fmt %d\n", colfmt);
+		return;
+	}
+}
+
+vdo_color_fmt scl_R2_get_color_format(void)
+{
+	switch (scl_regs1->r2_ctl.b.rgb_mode) {
+	case 0:
+		switch (scl_regs1->r2_ctl.b.vfmt) {
+		case 0:
+			return VDO_COL_FMT_YUV422H;
+		case 1:
+			return VDO_COL_FMT_YUV420;
+		case 2:
+		default:
+			return VDO_COL_FMT_YUV444;
+		}
+		break;
+	case 1:
+		return VDO_COL_FMT_RGB_565;
+	case 3:
+	default:
+		break;
+	}
+	return VDO_COL_FMT_ARGB;
+}
+
+void scl_R2_set_csc_mode(vpp_csc_t mode)
+{
+	vdo_color_fmt src_fmt, dst_fmt;
+
+	src_fmt = scl_R2_get_color_format();
+	dst_fmt = sclw_get_color_format();
+	mode = vpp_check_csc_mode(mode, src_fmt, dst_fmt, 0);
+
+	scl_regs2->r2_csc1 = vpp_csc_parm[mode][0];
+	scl_regs2->r2_csc2 = vpp_csc_parm[mode][1];
+	scl_regs2->r2_csc3 = vpp_csc_parm[mode][2];
+	scl_regs2->r2_csc4 = vpp_csc_parm[mode][3];
+	scl_regs2->r2_csc5 = vpp_csc_parm[mode][4];
+	scl_regs2->r2_csc6 = vpp_csc_parm[mode][5];
+	scl_regs2->r2_csc.val = vpp_csc_parm[mode][6];
+	scl_regs2->r2_csc.b.enable = (mode >= VPP_CSC_MAX) ? 0 : 1;
+}
+
+void scl_R2_set_framebuffer(vdo_framebuf_t *fb)
+{
+	scl_regs1->r2_ctl.b.iofmt = (fb->flag & VDO_FLAG_INTERLACE) ? 1 : 0;
+	scl_R2_set_color_format(fb->col_fmt);
+	scl_regs1->r2_ysa = fb->y_addr;
+	scl_regs1->r2_csa = fb->c_addr;
+	scl_regs1->r2_h_size.b.fbw = fb->fb_w;
+	scl_regs1->r2_h_size.b.lnsize = fb->img_w;
+	scl_regs1->r2_crop.b.hcrop = fb->h_crop;
+	scl_regs1->r2_crop.b.vcrop = fb->v_crop;
+	scl_R2_set_csc_mode(p_scl->fb_p->csc_mode);
+}
+
+void scl_ALPHA_set_enable(int enable)
+{
+	scl_regs1->alpha_colorkey.b.enable = enable;
+}
+
+void scl_ALPHA_set_swap(int enable)
+{
+	/* 0-(alpha,1-alpha),1:(1-alpha,alpha) */
+	scl_regs1->alpha_md.b.swap = enable;
+}
+
+void scl_ALPHA_set_src(int mode, int fixed)
+{
+	/* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */
+	scl_regs1->alpha_md.b.src = mode;
+	scl_regs1->alpha_fxd.b.src_fixed = fixed;
+}
+
+void scl_ALPHA_set_dst(int mode, int fixed)
+{
+	/* 0-RMIF1,1-RMIF2,2-Fixed ALPHA */
+	scl_regs1->alpha_md.b.dst = mode;
+	scl_regs1->alpha_fxd.b.dst_fixed = fixed;
+}
+
+void scl_ALPHA_set_color_key(int rmif2, int comp, int mode, int colkey)
+{
+	/* 0-RMIF1,1-RMIF2 */
+	scl_regs1->alpha_colorkey.b.from = rmif2;
+	/* 0-888,1-777,2-666,3-555 */
+	scl_regs1->alpha_colorkey.b.comp = comp;
+	/* (Non-Hit,Hit):0/1-(alpha,alpha),
+	2-(alpha,pix1),3-(pix1,alpha),4-(alpha,pix2),
+	5-(pix2,alpha),6-(pix1,pix2),7-(pix2,pix1) */
+	scl_regs1->alpha_colorkey.b.mode = mode;
+	scl_regs1->alpha_colorkey_rgb.val = colkey;
+}
+
+void scl_set_overlap(vpp_overlap_t *p)
+{
+#if 0
+	DPRINT("alpha src %d,0x%x,dst %d,0x%x\n",
+		p->alpha_src_type, p->alpha_src,
+		p->alpha_dst_type, p->alpha_dst);
+	DPRINT("colkey from %d,comp %d,mode %d,0x%x\n",
+		p->color_key_from, p->color_key_comp,
+		p->color_key_mode, p->color_key);
+#endif
+	scl_ALPHA_set_src(p->alpha_src_type, p->alpha_src);
+	scl_ALPHA_set_dst(p->alpha_dst_type, p->alpha_dst);
+	scl_ALPHA_set_swap(p->alpha_swap);
+	scl_ALPHA_set_color_key(p->color_key_from, p->color_key_comp,
+		p->color_key_mode, p->color_key);
+}
+
+void scl_set_req_num(int ynum, int cnum)
+{
+	scl_regs1->r_req_num.b.y_req_num = ynum;
+	scl_regs1->r_req_num.b.c_req_num = cnum;
+}
+
+static void scl_set_scale_PP(unsigned int src, unsigned int dst,
+					int horizontal)
+{
+	int gcd;
+
+/*	DBGMSG("scale PP(s %d,d %d,is H %d)\n",src,dst,horizontal); */
+
+	/* gcd = scl_get_gcd(src,dst); */
+	gcd = 1;
+	src /= gcd;
+	dst /= gcd;
+
+	if (horizontal)
+		scl_set_H_scale(dst, src);
+	else
+		scl_set_V_scale(dst, src);
+}
+
+void scl_set_scale(unsigned int SRC_W, unsigned int SRC_H,
+			unsigned int DST_W, unsigned int DST_H)
+{
+	int h_scale_up;
+	int v_scale_up;
+
+	DBGMSG("[SCL] src(%dx%d),dst(%dx%d)\n", SRC_W, SRC_H, DST_W, DST_H);
+
+	h_scale_up = (DST_W > SRC_W) ? 1 : 0;
+	v_scale_up = (DST_H > SRC_H) ? 1 : 0;
+
+	if (((DST_W / SRC_W) >= 32) || ((DST_W / SRC_W) < 1/32))
+		DBGMSG("*W* SCL H scale rate invalid\n");
+
+	if (((DST_H / SRC_H) >= 32) || ((DST_H / SRC_H) < 1/32))
+		DBGMSG("*W* SCL V scale rate invalid\n");
+
+/*	DBGMSG("scale H %d,V %d\n",h_scale_up,v_scale_up); */
+
+	sclr_set_mif2_enable(VPP_FLAG_DISABLE);
+	scl_set_scale_PP(SRC_W, DST_W, 1);
+	scl_set_scale_PP(SRC_H, DST_H, 0);
+	scl_set_scale_enable(v_scale_up, h_scale_up);
+
+	{
+		int rec_h, rec_v;
+		int h, v;
+
+		h = rec_h = 0;
+		if (SRC_W > DST_W) { /* scale down */
+			switch (p_scl->scale_mode) {
+			case VPP_SCALE_MODE_ADAPTIVE:
+				if ((DST_W * 2) > SRC_W) /* 1 > mode(3) > 1/2 */
+					h = 1; /* bilinear mode */
+				else
+					rec_h = 1; /* recursive mode */
+				break;
+			case VPP_SCALE_MODE_BILINEAR:
+				h = 1; /* bilinear mode */
+				break;
+			case VPP_SCALE_MODE_RECURSIVE:
+				rec_h = 1;	/* recursive mode */
+				break;
+			default:
+				break;
+			}
+		}
+
+		v = rec_v = 0;
+		if (SRC_H > DST_H) { /* scale down */
+			switch (p_scl->scale_mode) {
+			case VPP_SCALE_MODE_ADAPTIVE:
+				if ((DST_H * 2) > SRC_H) /* 1 > mode(3) > 1/2 */
+					v = 1; /* bilinear mode */
+				else
+					rec_v = 1; /* recursive mode */
+				break;
+			case VPP_SCALE_MODE_BILINEAR:
+				v = 1; /* bilinear mode */
+				break;
+			case VPP_SCALE_MODE_RECURSIVE:
+				rec_v = 1;	/* recursive mode */
+				break;
+			default:
+				break;
+			}
+		}
+
+		if (SRC_W == DST_W)
+			rec_h = 1;
+		if (SRC_H == DST_H)
+			rec_v = 1;
+		scl_regs1->true_bilinear.b.h = h;
+		scl_regs1->true_bilinear.b.v = v;
+		scl_regs2->recursive_mode.b.h = rec_h;
+		scl_regs2->recursive_mode.b.v = rec_v;
+		if (v) {
+			scl_regs1->vxwidth.b.vxwidth =
+				scl_regs1->vxwidth.b.vxwidth - 1;
+			scl_regs1->vxwidth.b.dst_vxwidth =
+				scl_regs1->vxwidth.b.vxwidth;
+		}
+		sclr_set_mif2_enable((v) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE);
+	}
+}
+
+void sclr_set_framebuffer(vdo_framebuf_t *inbuf)
+{
+	sclr_set_color_format(inbuf->col_fmt);
+	sclr_set_crop(inbuf->h_crop, inbuf->v_crop);
+	sclr_set_width(inbuf->img_w, inbuf->fb_w);
+	sclr_set_fb_addr(inbuf->y_addr, inbuf->c_addr);
+	sclr_set_field_mode(vpp_get_fb_field(inbuf));
+}
+
+void scl_set_scale_timing(vdo_framebuf_t *s, vdo_framebuf_t *d)
+{
+	vpp_clock_t timing;
+	unsigned int pixel_clock;
+
+	/* scl TG */
+	timing.total_pixel_of_line = (d->img_w > s->img_w) ?
+					d->img_w : s->img_w;
+	timing.total_line_of_frame = (d->img_h > s->img_h) ?
+					d->img_h : s->img_h;
+	timing.begin_pixel_of_active = 60;
+	timing.end_pixel_of_active = timing.total_pixel_of_line + 60;
+	timing.total_pixel_of_line = timing.total_pixel_of_line + 120;
+	timing.begin_line_of_active = 8;
+	timing.end_line_of_active = timing.total_line_of_frame + 8;
+	timing.total_line_of_frame = timing.total_line_of_frame + 16;
+	timing.line_number_between_VBIS_VBIE = 4;
+	timing.line_number_between_PVBI_VBIS = 1;
+	pixel_clock = timing.total_pixel_of_line *
+		timing.total_line_of_frame * p_scl->fb_p->framerate;
+	scl_set_timing(&timing, pixel_clock);
+}
+
+void sclw_set_framebuffer(vdo_framebuf_t *fb)
+{
+	unsigned int yaddr, caddr;
+	int y_bpp, c_bpp;
+
+	vpp_get_colfmt_bpp(fb->col_fmt, &y_bpp, &c_bpp);
+	yaddr = fb->y_addr + ((fb->fb_w * fb->v_crop + fb->h_crop) * y_bpp / 8);
+	caddr = (c_bpp) ? (fb->c_addr + (((fb->fb_w * fb->v_crop +
+		fb->h_crop) / 2) * 2 * c_bpp / 8)) : 0;
+	sclw_set_fb_addr(yaddr, caddr);
+	sclw_set_color_format(fb->col_fmt);
+	sclw_set_fb_width(fb->img_w, fb->fb_w);
+	sclw_set_field_mode(vpp_get_fb_field(fb));
+	scl_set_csc_mode(p_scl->fb_p->csc_mode);
+}
+
+void scl_init(void *base)
+{
+	struct scl_mod_t *mod_p;
+	struct vpp_fb_base_t *fb_p;
+
+	mod_p = (struct scl_mod_t *) base;
+	fb_p = mod_p->fb_p;
+
+	scl_set_reg_level(VPP_REG_LEVEL_1);
+	scl_set_tg_enable(VPP_FLAG_DISABLE);
+	scl_set_enable(VPP_FLAG_DISABLE);
+	scl_set_int_enable(VPP_FLAG_DISABLE, VPP_INT_ALL);
+	sclr_set_mif_enable(VPP_FLAG_DISABLE);
+	sclr_set_mif2_enable(VPP_FLAG_DISABLE);
+	sclr_set_colorbar(VPP_FLAG_DISABLE, 0, 0);
+
+	scl_set_int_enable(VPP_FLAG_ENABLE, mod_p->int_catch);
+	scl_set_watchdog(fb_p->wait_ready);
+	scl_set_csc_mode(fb_p->csc_mode);
+	sclr_set_media_format(fb_p->media_fmt);
+	sclr_set_threshold(0xf);
+
+	/* filter default value */
+	scl_regs2->dblk_threshold.b.layer1_boundary = 48;
+	scl_regs2->dblk_threshold.b.layer2_boundary = 16;
+
+	scl_regs2->field_flicker.b.y_thd = 8;
+	scl_regs2->field_flicker.b.c_thd = 8;
+	scl_regs2->field_flicker.b.condition = 0;
+
+	scl_regs2->frame_flicker.b.rgb = 0;
+	scl_regs2->frame_flicker.b.sampler = 14;
+	scl_regs2->frame_flicker.b.scene_chg_thd = 32;
+	scl_set_reg_update(VPP_FLAG_ENABLE);
+	scl_set_tg_enable(VPP_FLAG_DISABLE);
+}
+
+void sclw_init(void *base)
+{
+	sclw_set_mif_enable(VPP_FLAG_DISABLE);
+	sclw_set_fb_width(VPP_HD_DISP_RESX, VPP_HD_MAX_RESX);
+/*	vppif_reg32_write(SCL_SCLDW_METHOD,0x1); */	/* drop line enable */
+}
+
+#ifdef __KERNEL__
+/* static struct work_struct scl_proc_scale_wq; */
+DECLARE_WAIT_QUEUE_HEAD(scl_proc_scale_event);
+static void scl_proc_scale_complete_work(struct work_struct *work)
+#else
+static void scl_proc_scale_complete_work(int arg)
+#endif
+{
+/*	DPRINT("[SCL] scl_proc_scale_complete_work\n"); */
+	p_scl->scale_complete = 1;
+#ifdef __KERNEL__
+	wake_up_interruptible(&scl_proc_scale_event);
+#endif
+#if 0 /* avoid mutex in irq */
+	vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0);
+#endif
+}
+
+#ifdef __KERNEL__
+struct timer_list scl_scale_timer;
+#endif
+int scl_proc_scale_complete(void *arg)
+{
+#ifdef __KERNEL__
+	del_timer(&scl_scale_timer);
+#endif
+/*	DPRINT("[SCL] scl_proc_scale_complete\n"); */
+	if (scl_regs1->tg_sts.b.tgerr) {
+		DPRINT("[SCL] scale TG err 0x%x,0x%x\n",
+			scl_regs1->tg_sts.val, scl_regs1->w_ff_ctl.val);
+		scl_regs1->tg_sts.val = BIT0;
+		scl_regs1->w_ff_ctl.val =  0x10101;
+	}
+	scl_set_tg_enable(VPP_FLAG_DISABLE);
+#ifndef CONFIG_UBOOT
+	vppm_set_int_enable(VPP_FLAG_DISABLE, SCL_COMPLETE_INT);
+#endif
+	sclw_set_mif_enable(VPP_FLAG_DISABLE);
+	sclr_set_mif_enable(VPP_FLAG_DISABLE);
+	sclr_set_mif2_enable(VPP_FLAG_DISABLE);
+	scl_set_enable(VPP_FLAG_DISABLE);
+
+/* #ifdef __KERNEL__ */
+#if 0
+	INIT_WORK(&scl_proc_scale_wq, scl_proc_scale_complete_work);
+	schedule_work(&scl_proc_scale_wq);
+#else
+	scl_proc_scale_complete_work(0);
+#endif
+	return 0;
+}
+
+void scl_scale_timeout(int arg)
+{
+	DBG_ERR("scale timeout\n");
+#if 0
+	scl_reg_dump();
+	g_vpp.dbg_msg_level = VPP_DBGLVL_STREAM;
+	g_vpp.dbg_cnt = 1000;
+#endif
+	scl_proc_scale_complete(0);
+}
+
+void scl_set_scale_timer(int ms)
+{
+#ifdef __KERNEL__
+	if (scl_scale_timer.function)
+		del_timer(&scl_scale_timer);
+	init_timer(&scl_scale_timer);
+	scl_scale_timer.function = (void *) scl_scale_timeout;
+	scl_scale_timer.expires = jiffies + msecs_to_jiffies(ms);
+	add_timer(&scl_scale_timer);
+#endif
+}
+
+int scl_proc_scale_finish(void)
+{
+	int ret = 0;
+
+#ifdef __KERNEL__
+
+/*	DPRINT("[SCL] scl_proc_scale_finish\n"); */
+	ret = wait_event_interruptible_timeout(scl_proc_scale_event,
+				(p_scl->scale_complete != 0), 3 * HZ);
+	if (ret == 0) { /* timeout */
+		DPRINT("[SCL] *E* wait scale timeout\n");
+		ret = -1;
+	} else {
+		ret = 0;
+	}
+#endif
+#if 1 /* avoid mutex in irq */
+	vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0);
+#endif
+	return ret;
+}
+
+void scl_check_framebuf(vdo_framebuf_t *s,
+				vdo_framebuf_t *in, vdo_framebuf_t *out)
+{
+	if (s) {
+		if (s->img_w > WMT_SCL_H_DIV_MAX)
+			DBG_ERR("src w %d over %d\n",
+					s->img_w, WMT_SCL_H_DIV_MAX);
+		if (s->img_h > WMT_SCL_V_DIV_MAX)
+			DBG_ERR("src h %d over %d\n",
+					s->img_h, WMT_SCL_V_DIV_MAX);
+		if (s->col_fmt >= VDO_COL_FMT_ARGB) {
+			if (s->y_addr % 4)
+				DBG_ERR("src addr 0x%x not align 4\n",
+						s->y_addr);
+		}
+		if (s->fb_w > WMT_SCL_H_DIV_MAX)
+			DBG_ERR("src fb w %d over %d\n",
+				s->fb_w, WMT_SCL_H_DIV_MAX);
+		if (s->y_addr % 64)
+			DBG_ERR("src fb addr 0x%x no align 64\n", s->y_addr);
+	} else {
+		DBG_ERR("src null\n");
+	}
+
+	if (in) {
+		if (in->img_w > WMT_SCL_H_DIV_MAX)
+			DBG_ERR("in w %d over %d\n",
+					in->img_w, WMT_SCL_H_DIV_MAX);
+		if (in->img_h > WMT_SCL_V_DIV_MAX)
+			DBG_ERR("in h %d over %d\n",
+					in->img_h, WMT_SCL_V_DIV_MAX);
+		if (in->col_fmt >= VDO_COL_FMT_ARGB) {
+			if (in->y_addr % 4)
+				DBG_ERR("in addr 0x%x not align 4\n",
+						in->y_addr);
+		}
+		if (in->fb_w > WMT_SCL_H_DIV_MAX)
+			DBG_ERR("in fb w %d over %d\n",
+				in->fb_w, WMT_SCL_H_DIV_MAX);
+		if (in->y_addr % 64)
+			DBG_ERR("in fb addr 0x%x no align 64\n", in->y_addr);
+	}
+
+	if (out) {
+		if (s && (s->img_w == out->img_w)) {
+			if (out->img_w > WMT_SCL_H_DIV_MAX)
+				DBG_ERR("out w %d over %d\n", out->img_w,
+					WMT_SCL_H_DIV_MAX);
+		} else {
+			if (out->img_w > WMT_SCL_SCALE_DST_H_MAX)
+				DBG_ERR("out w %d over %d\n", out->img_w,
+					WMT_SCL_SCALE_DST_H_MAX);
+
+		}
+		if (out->col_fmt >= VDO_COL_FMT_ARGB) {
+			if (out->y_addr % 4)
+				DBG_ERR("out addr 0x%x not align 4\n",
+						out->y_addr);
+		}
+		if (out->fb_w > WMT_SCL_H_DIV_MAX)
+			DBG_ERR("out fb w %d over %d\n",
+				out->fb_w, WMT_SCL_H_DIV_MAX);
+		if (out->y_addr % 64)
+			DBG_ERR("out fb addr 0x%x no align 64\n", out->y_addr);
+	} else {
+		DBG_ERR("out null\n");
+	}
+}
+
+#define CONFIG_VPP_CHECK_SCL_STATUS
+int scl_set_scale_overlap(vdo_framebuf_t *s,
+				vdo_framebuf_t *in, vdo_framebuf_t *out)
+{
+	int ret = 0;
+
+	if (vpp_check_dbg_level(VPP_DBGLVL_SCALE)) {
+		scl_check_framebuf(s, in, out);
+
+		if (s)
+			vpp_show_framebuf("src1", s);
+		if (in)
+			vpp_show_framebuf("src2", in);
+		if (out)
+			vpp_show_framebuf("dst", out);
+	}
+
+	if (p_scl->scale_sync)
+		vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 0);
+
+	scl_set_timing_master(VPP_MOD_SCL);
+
+	if (s) {
+		p_scl->fb_p->fb = *s;
+		sclr_set_framebuffer(s);
+		sclr_set_mif_enable(VPP_FLAG_ENABLE);
+	} else {
+		DPRINT("[SCL] *E* no source\n");
+		return -1;
+	}
+
+	if (in && (in->y_addr == 0))
+		in = 0;
+
+	scl_ALPHA_set_enable((in) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE);
+	scl_R2_set_mif_enable((in) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE);
+	if (in)
+		scl_R2_set_framebuffer(in);
+	if (out) {
+		p_sclw->fb_p->fb = *out;
+		sclw_set_framebuffer(out);
+	} else {
+		DPRINT("[SCL] *E* no dest\n");
+		return -1;
+	}
+
+	scl_set_scale(s->img_w, s->img_h, out->img_w, out->img_h);
+	scl_set_scale_timing(s, out);
+
+	/* scale process */
+	scl_set_enable(VPP_FLAG_ENABLE);
+	scl_regs1->tg_ctl.b.oneshot = 1;
+	sclw_set_mif_enable(VPP_FLAG_ENABLE);
+	scl_set_tg_enable(VPP_FLAG_ENABLE);
+#ifdef CONFIG_VPP_CHECK_SCL_STATUS
+	scl_regs1->tg_sts.val = BIT0;
+	scl_regs1->w_ff_ctl.val = 0x10101;
+#endif
+	p_scl->scale_complete = 0;
+#ifndef CONFIG_UBOOT
+	vppm_set_int_enable(VPP_FLAG_ENABLE, SCL_COMPLETE_INT);
+#endif
+#if 0   /* for debug scale */
+	scl_reg_dump();
+#endif
+#ifdef CONFIG_UBOOT
+	while (scl_regs1->tg_ctl.b.enable);
+	scl_proc_scale_complete(0);
+	scl_proc_scale_finish();
+#else
+	if (p_scl->scale_sync) {
+		ret = vpp_irqproc_work(SCL_COMPLETE_INT,
+			(void *)scl_proc_scale_complete, 0, 100, 1);
+		scl_proc_scale_finish();
+	} else {
+		vpp_irqproc_work(SCL_COMPLETE_INT,
+			(void *)scl_proc_scale_complete, 0, 0, 1);
+		scl_set_scale_timer(100);
+	}
+#endif
+	return ret;
+}
+
+int scl_proc_scale(vdo_framebuf_t *src_fb, vdo_framebuf_t *dst_fb)
+{
+	int ret = 0;
+
+	if (dst_fb->col_fmt == VDO_COL_FMT_YUV420) {
+		int size;
+		unsigned int buf;
+		vdo_framebuf_t dfb;
+
+		dfb = *dst_fb;	/* backup dst fb */
+
+		/* alloc memory */
+		size = dst_fb->img_w * dst_fb->img_h + 64;
+		buf = (unsigned int) kmalloc(size, GFP_KERNEL);
+		if (!buf) {
+			DPRINT("[SCL] *E* malloc fail %d\n", size);
+			return -1;
+		}
+
+		if (buf % 64)
+			buf = buf + (64 - (buf % 64));
+
+		/* scale for Y */
+		dst_fb->c_addr = buf;
+		ret = scl_set_scale_overlap(src_fb, 0, dst_fb);
+		if (ret == 0) {
+			/* V 1/2 scale for C */
+			dst_fb->y_addr = buf;
+			dst_fb->c_addr = dfb.c_addr;
+			dst_fb->img_h = dfb.img_h / 2;
+			ret = scl_set_scale_overlap(src_fb, 0, dst_fb);
+		}
+		kfree((void *)buf);
+		*dst_fb = dfb;	/* restore dst fb */
+	} else {
+		ret = scl_set_scale_overlap(src_fb, 0, dst_fb);
+	}
+	return ret;
+}
+
+#ifdef CONFIG_PM
+static unsigned int *scl_pm_bk2;
+static unsigned int scl_pm_enable, scl_pm_tg;
+static unsigned int scl_pm_r_mif1, scl_pm_r_mif2, scl_pm_w_mif;
+void scl_suspend(int sts)
+{
+	switch (sts) {
+	case 0:	/* disable module */
+		vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 1);
+		scl_pm_enable = scl_regs1->en.b.alu_enable;
+		scl_regs1->en.b.alu_enable = 0;
+		scl_pm_r_mif1 = scl_regs1->r_ctl.b.mif_enable;
+		scl_pm_r_mif2 = scl_regs1->r2_ctl.b.mif_en;
+		scl_regs1->r2_ctl.b.mif_en = 0;
+		scl_regs1->r_ctl.b.mif_enable = 0;
+		scl_pm_w_mif = scl_regs1->w_ctl.b.mif_enable;
+		scl_regs1->w_ctl.b.mif_enable = 0;
+		break;
+	case 1: /* disable tg */
+		scl_pm_tg = scl_regs1->tg_ctl.b.enable;
+		scl_regs1->tg_ctl.b.enable = 0;
+		break;
+	case 2:	/* backup register */
+		p_scl->reg_bk = vpp_backup_reg(REG_SCL_BASE1_BEGIN,
+			(REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN));
+		scl_pm_bk2 = vpp_backup_reg(REG_SCL_BASE2_BEGIN,
+			(REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN));
+		break;
+	default:
+		break;
+	}
+}
+
+void scl_resume(int sts)
+{
+	switch (sts) {
+	case 0:	/* restore register */
+		vpp_restore_reg(REG_SCL_BASE1_BEGIN,
+			(REG_SCL_BASE1_END - REG_SCL_BASE1_BEGIN),
+			p_scl->reg_bk);
+		vpp_restore_reg(REG_SCL_BASE2_BEGIN,
+			(REG_SCL_BASE2_END - REG_SCL_BASE2_BEGIN), scl_pm_bk2);
+		p_scl->reg_bk = 0;
+		scl_pm_bk2 = 0;
+		break;
+	case 1:	/* enable module */
+		scl_regs1->w_ctl.b.mif_enable = scl_pm_w_mif;
+		scl_regs1->r_ctl.b.mif_enable = scl_pm_r_mif1;
+		scl_regs1->r2_ctl.b.mif_en = scl_pm_r_mif2;
+		scl_regs1->en.b.alu_enable = scl_pm_enable;
+		break;
+	case 2: /* enable tg */
+		scl_regs1->tg_ctl.b.enable = scl_pm_tg;
+		vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 1);
+		break;
+	default:
+		break;
+	}
+}
+#else
+#define scl_suspend NULL
+#define scl_resume NULL
+#endif
+
+int scl_mod_init(void)
+{
+	struct vpp_fb_base_t *mod_fb_p;
+	vdo_framebuf_t *fb_p;
+
+	/* -------------------- SCL module -------------------- */
+	{
+	struct scl_mod_t *scl_mod_p;
+
+	scl_mod_p = (struct scl_mod_t *) vpp_mod_register(VPP_MOD_SCL,
+				sizeof(struct scl_mod_t),
+				VPP_MOD_FLAG_FRAMEBUF);
+	if (!scl_mod_p) {
+		DPRINT("*E* SCL module register fail\n");
+		return -1;
+	}
+
+	/* module member variable */
+	scl_mod_p->int_catch = VPP_INT_NULL;
+	scl_mod_p->scale_mode = VPP_SCALE_MODE_ADAPTIVE;
+	scl_mod_p->pm = DEV_SCL444U;
+	scl_mod_p->filter_mode = VPP_FILTER_SCALE;
+
+	/* module member function */
+	scl_mod_p->init = scl_init;
+	scl_mod_p->set_enable = scl_set_enable;
+	scl_mod_p->set_colorbar = sclr_set_colorbar;
+	scl_mod_p->dump_reg = scl_reg_dump;
+	scl_mod_p->get_sts = scl_get_int_status;
+	scl_mod_p->clr_sts = scl_clean_int_status;
+	scl_mod_p->scale = scl_proc_scale;
+	scl_mod_p->scale_finish = scl_proc_scale_finish;
+	scl_mod_p->suspend = scl_suspend;
+	scl_mod_p->resume = scl_resume;
+
+	/* module frame buffer variable */
+	mod_fb_p = scl_mod_p->fb_p;
+	fb_p = &mod_fb_p->fb;
+
+	fb_p->y_addr = 0;
+	fb_p->c_addr = 0;
+	fb_p->col_fmt = VDO_COL_FMT_YUV422H;
+	fb_p->img_w = VPP_HD_DISP_RESX;
+	fb_p->img_h = VPP_HD_DISP_RESY;
+	fb_p->fb_w = VPP_HD_MAX_RESX;
+	fb_p->fb_h = VPP_HD_MAX_RESY;
+	fb_p->h_crop = 0;
+	fb_p->v_crop = 0;
+
+	/* module frame buffer member function */
+	mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255;
+	mod_fb_p->set_framebuf = sclr_set_framebuffer;
+	mod_fb_p->set_addr = sclr_set_fb_addr;
+	mod_fb_p->get_addr = sclr_get_fb_addr;
+	mod_fb_p->set_csc = scl_set_csc_mode;
+	mod_fb_p->framerate = 0x7fffffff;
+	mod_fb_p->wait_ready = 0xffffffff;
+	mod_fb_p->capability = BIT(VDO_COL_FMT_YUV420)
+		| BIT(VDO_COL_FMT_YUV422H) | BIT(VDO_COL_FMT_YUV444)
+		| BIT(VDO_COL_FMT_ARGB) | BIT(VDO_COL_FMT_RGB_565)
+		| VPP_FB_FLAG_CSC | VPP_FB_FLAG_FIELD;
+	p_scl = scl_mod_p;
+	p_scl->scale_complete = 1;
+	p_scl->scale_sync = 1;
+	}
+
+	/* -------------------- SCLW module -------------------- */
+	{
+	struct sclw_mod_t *sclw_mod_p;
+
+	sclw_mod_p = (struct sclw_mod_t *) vpp_mod_register(VPP_MOD_SCLW,
+				sizeof(struct sclw_mod_t),
+				VPP_MOD_FLAG_FRAMEBUF);
+	if (!sclw_mod_p) {
+		DPRINT("*E* SCLW module register fail\n");
+		return -1;
+	}
+
+	/* module member variable */
+	sclw_mod_p->int_catch = VPP_INT_NULL;
+
+	/* module member function */
+	sclw_mod_p->init = sclw_init;
+	sclw_mod_p->set_enable = sclw_set_mif_enable;
+
+	/* module frame buffer */
+	mod_fb_p = sclw_mod_p->fb_p;
+	fb_p = &mod_fb_p->fb;
+
+	fb_p->y_addr = 0;
+	fb_p->c_addr = 0;
+	fb_p->col_fmt = VDO_COL_FMT_YUV422H;
+	fb_p->img_w = VPP_HD_DISP_RESX;
+	fb_p->img_h = VPP_HD_DISP_RESY;
+	fb_p->fb_w = VPP_HD_MAX_RESX;
+	fb_p->fb_h = VPP_HD_MAX_RESY;
+	fb_p->h_crop = 0;
+	fb_p->v_crop = 0;
+
+	/* module frame buffer member function */
+	mod_fb_p->csc_mode = VPP_CSC_RGB2YUV_SDTV_0_255;
+	mod_fb_p->set_framebuf = sclw_set_framebuffer;
+	mod_fb_p->set_addr = sclw_set_fb_addr;
+	mod_fb_p->get_addr = sclw_get_fb_addr;
+	mod_fb_p->set_csc = scl_set_csc_mode;
+	mod_fb_p->wait_ready = 0xffffffff;
+	mod_fb_p->capability = BIT(VDO_COL_FMT_YUV422H)
+		| BIT(VDO_COL_FMT_YUV444) | BIT(VDO_COL_FMT_ARGB)
+		| BIT(VDO_COL_FMT_RGB_565) | VPP_FB_FLAG_CSC
+		| BIT(VDO_COL_FMT_YUV420);
+	p_sclw = sclw_mod_p;
+	}
+	return 0;
+}
+module_init(scl_mod_init);
+#endif /* WMT_FTBLK_SCL */
diff --git a/drivers/video/wmt/scl.h b/drivers/video/wmt/scl.h
new file mode 100755
index 00000000..2d11b48f
--- /dev/null
+++ b/drivers/video/wmt/scl.h
@@ -0,0 +1,128 @@
+/*++
+ * linux/drivers/video/wmt/scl.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp.h"
+
+#ifndef SCL_H
+#define SCL_H
+
+#define SCL_COMPLETE_INT VPP_INT_SCL_PVBI
+
+struct scl_mod_t {
+	VPP_MOD_BASE;
+
+	int (*scale)(vdo_framebuf_t *src, vdo_framebuf_t *dst);
+	int (*scale_finish)(void);
+
+	enum vpp_scale_mode_t scale_mode;
+	enum vpp_scale_mode_t scale_sync;
+	int scale_complete;
+	enum vpp_filter_mode_t filter_mode;
+	int abgr_mode;
+
+	struct vpp_dbg_timer_t overlap_timer;
+	struct vpp_dbg_timer_t scale_timer;
+};
+
+struct sclw_mod_t {
+	VPP_MOD_BASE;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef SCL_C
+#define EXTERN
+#else
+#define EXTERN   extern
+#endif
+
+EXTERN struct scl_mod_t *p_scl;
+EXTERN struct sclw_mod_t *p_sclw;
+
+#ifdef WMT_FTBLK_SCL
+
+EXTERN void scl_reg_dump(void);
+EXTERN void sclr_set_framebuffer(vdo_framebuf_t *inbuf);
+EXTERN void sclw_set_framebuffer(vdo_framebuf_t *outbuf);
+
+EXTERN void scl_set_enable(vpp_flag_t enable);
+EXTERN void scl_set_reg_update(vpp_flag_t enable);
+EXTERN void scl_set_reg_level(vpp_reglevel_t level);
+EXTERN void scl_set_int_enable(vpp_flag_t enable, enum vpp_int_t int_bit);
+EXTERN enum vpp_int_err_t scl_get_int_status(void);
+EXTERN void scl_clean_int_status(enum vpp_int_err_t int_sts);
+EXTERN void scl_set_csc_mode(vpp_csc_t mode);
+EXTERN void scl_set_scale_enable(vpp_flag_t vscl_enable,
+	vpp_flag_t hscl_enable);
+EXTERN void scl_set_V_scale(int A, int B);
+EXTERN void scl_set_H_scale(int A, int B);
+EXTERN void scl_set_crop(int offset_x, int offset_y);
+EXTERN void scl_set_tg_enable(vpp_flag_t enable);
+EXTERN void scl_set_timing_master(vpp_mod_t mod_bit);
+EXTERN vpp_mod_t scl_get_timing_master(void);
+EXTERN void scl_set_drop_line(vpp_flag_t enable);
+EXTERN void sclr_get_fb_info(U32 *width, U32 *act_width,
+	U32 *x_offset, U32 *y_offset);
+EXTERN void sclr_set_mif_enable(vpp_flag_t enable);
+EXTERN void sclr_set_mif2_enable(vpp_flag_t enable);
+EXTERN void sclr_set_colorbar(vpp_flag_t enable, int width, int inverse);
+EXTERN void sclr_set_display_format(vpp_display_format_t source,
+	vpp_display_format_t target);
+EXTERN void sclr_set_field_mode(vpp_display_format_t fmt);
+EXTERN void sclr_set_color_format(vdo_color_fmt format);
+EXTERN vdo_color_fmt sclr_get_color_format(void);
+EXTERN void sclr_set_media_format(vpp_media_format_t format);
+EXTERN void sclr_set_fb_addr(U32 y_addr, U32 c_addr);
+EXTERN void sclr_get_fb_addr(U32 *y_addr, U32 *c_addr);
+EXTERN void sclr_set_width(U32 y_pixel, U32 y_buffer);
+EXTERN void sclr_get_width(U32 *p_y_pixel, U32 *p_y_buffer);
+EXTERN void sclr_set_crop(U32 h_crop, U32 v_crop);
+EXTERN void sclr_set_threshold(U32 value);
+EXTERN vdo_color_fmt scl_R2_get_color_format(void);
+EXTERN void sclw_set_mif_enable(vpp_flag_t enable);
+EXTERN void sclw_set_color_format(vdo_color_fmt format);
+EXTERN vdo_color_fmt sclw_get_color_format(void);
+EXTERN void sclw_set_field_mode(vpp_display_format_t fmt);
+EXTERN void sclw_set_fb_addr(U32 y_addr, U32 c_addr);
+EXTERN void sclw_get_fb_addr(U32 *y_addr, U32 *c_addr);
+EXTERN void sclw_set_fb_width(U32 y_pixel, U32 y_buffer);
+EXTERN void sclw_get_fb_width(U32 *width, U32 *buf_width);
+EXTERN void scl_set_scale(unsigned int SRC_W, unsigned int SRC_H,
+	unsigned int DST_W, unsigned int DST_H);
+EXTERN int scl_mod_init(void);
+EXTERN void scl_set_deblock_enable(int enable);
+EXTERN void scl_set_field_filter_enable(int enable);
+EXTERN void scl_set_frame_filter_enable(int enable);
+EXTERN int scl_set_scale_overlap(vdo_framebuf_t *s,
+	vdo_framebuf_t *in, vdo_framebuf_t *out);
+EXTERN void scl_set_overlap(vpp_overlap_t *p);
+EXTERN int scl_mod_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* WMT_FTBLK_SCL */
+#undef EXTERN
+#endif /* SCL_H */
diff --git a/drivers/video/wmt/sw_i2c.c b/drivers/video/wmt/sw_i2c.c
new file mode 100755
index 00000000..79acd966
--- /dev/null
+++ b/drivers/video/wmt/sw_i2c.c
@@ -0,0 +1,436 @@
+/*++
+ * linux/drivers/video/wmt/sw_i2c.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp-osif.h"
+#include "sw_i2c.h"
+
+#define   SPEED			50	/* 5000000 */
+
+#define delay_time 30
+
+struct swi2c_reg_bk_t {
+	unsigned int gpio_en;
+	unsigned int out_en;
+	unsigned int data_out;
+	unsigned int pull_en;
+};
+
+#ifdef __KERNEL__
+static DEFINE_SPINLOCK(swi2c_irqlock);
+unsigned long swi2c_irqlock_flags;
+#endif
+void wmt_swi2c_lock(int lock)
+{
+#ifdef __KERNEL__
+	if (lock)
+		spin_lock_irqsave(&swi2c_irqlock, swi2c_irqlock_flags);
+	else
+		spin_unlock_irqrestore(&swi2c_irqlock, swi2c_irqlock_flags);
+#endif
+}
+
+struct swi2c_reg_s *swi2c_scl, *swi2c_sda;
+
+void wmt_swi2c_delay(unsigned int time)
+{
+	udelay(time);
+}
+
+void wmt_swi2c_SetSDAInput(void)
+{
+	outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, swi2c_sda->gpio_en);
+	outw(inw(swi2c_sda->out_en) & ~swi2c_sda->bit_mask, swi2c_sda->out_en);
+}
+
+
+void wmt_swi2c_SetSDAOutput(void)
+{
+	outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask, swi2c_sda->gpio_en);
+	outw(inw(swi2c_sda->out_en) | swi2c_sda->bit_mask, swi2c_sda->out_en);
+}
+
+bool wmt_swi2c_GetSDA(void) /* bit */
+{
+	if (inw(swi2c_sda->data_in) & swi2c_sda->bit_mask)
+#ifdef CFG_LOADER
+		return 1;
+	return 0;
+#else
+		return (HW_REG bool) 1;
+	return (HW_REG bool) 0;
+#endif
+}
+
+bool wmt_swi2c_GetSCL(void) /* bit */
+{
+	if (inw(swi2c_scl->data_in) & swi2c_scl->bit_mask)
+#ifdef CFG_LOADER
+		return 1;
+	return 0;
+#else
+		return (HW_REG bool) 1;
+	return (HW_REG bool) 0;
+#endif
+}
+
+void wmt_swi2c_SetSDA(int high)
+{
+	if (high) {
+		/* set to GPI and pull high */
+		outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask,
+			swi2c_sda->gpio_en);
+		outw(inw(swi2c_sda->out_en) & ~swi2c_sda->bit_mask,
+			swi2c_sda->out_en);
+		if (swi2c_sda->pull_en)
+			outw(inw(swi2c_sda->pull_en) &
+				~swi2c_sda->pull_en_bit_mask,
+				swi2c_sda->pull_en);
+	} else {
+		outw(inw(swi2c_sda->gpio_en) | swi2c_sda->bit_mask,
+			swi2c_sda->gpio_en);
+		outw(inw(swi2c_sda->out_en) | swi2c_sda->bit_mask,
+			swi2c_sda->out_en);
+		outw(inw(swi2c_sda->data_out) & ~swi2c_sda->bit_mask,
+			swi2c_sda->data_out);
+	}
+}
+
+void wmt_swi2c_SetSCL(int high)
+{
+	if (high) {
+		outw(inw(swi2c_scl->gpio_en) | swi2c_scl->bit_mask,
+			swi2c_scl->gpio_en);
+		outw(inw(swi2c_scl->out_en) & ~swi2c_scl->bit_mask,
+			swi2c_scl->out_en);
+		if (swi2c_scl->pull_en)
+			outw(inw(swi2c_scl->pull_en) &
+				~swi2c_scl->pull_en_bit_mask,
+				swi2c_scl->pull_en);
+	} else {
+		outw(inw(swi2c_scl->gpio_en) | swi2c_scl->bit_mask,
+			swi2c_scl->gpio_en);
+		outw(inw(swi2c_scl->out_en) | swi2c_scl->bit_mask,
+			swi2c_scl->out_en);
+		outw(inw(swi2c_scl->data_out) & ~swi2c_scl->bit_mask,
+			swi2c_scl->data_out);
+	}
+}
+
+int wmt_swi2c_SetData(int high)
+{
+	unsigned int wait = 1;
+
+	wmt_swi2c_SetSDA(high);
+	do {
+		if (wmt_swi2c_GetSDA() == ((high) ? 1 : 0))
+			return 0;
+	} while (wait++ < SPEED);
+	return 1;
+}
+
+int wmt_swi2c_SetClock(int high)
+{
+	unsigned int wait = 1;
+
+	udelay(5);	/* 3-100kHz, 5-80kHz */
+
+	wmt_swi2c_SetSCL(high);
+	do {
+		if (wmt_swi2c_GetSCL() == ((high) ? 1 : 0))
+			return 0;
+	} while (wait++ < SPEED);
+	return 1; /* fail */
+}
+
+int wmt_swi2c_StartI2C(void)
+{
+	if (wmt_swi2c_SetData(1))
+		return 1;
+	if (wmt_swi2c_SetClock(1))
+		return 2;
+	if (wmt_swi2c_SetData(0))
+		return 3;
+	wmt_swi2c_delay(0);
+	if (wmt_swi2c_SetClock(0))
+		return 4;
+	return 0; /* success */
+}
+
+int wmt_swi2c_StopI2C(void)
+{
+	if (wmt_swi2c_SetData(0))
+		return 1;
+	if (wmt_swi2c_SetClock(0))
+		return 1;
+	if (wmt_swi2c_SetClock(1))
+		return 1;
+	wmt_swi2c_delay(0);
+	if (wmt_swi2c_SetData(1))
+		return 1;
+	return 0; /* success */
+}
+
+int wmt_swi2c_WriteAck(unsigned char byte)
+{
+	int ret;
+	int bit;
+
+	for (bit = 7; bit >= 0; bit--) {
+		wmt_swi2c_SetData(byte & 0x80);
+		byte <<= 1;
+		if (wmt_swi2c_SetClock(1))
+			return 1;
+		if (wmt_swi2c_SetClock(0))
+			return 1;
+	}
+	ret = 0;
+	wmt_swi2c_SetSDAInput();
+	if (wmt_swi2c_SetClock(1))
+		ret = 1;
+	else if (wmt_swi2c_GetSDA())
+		ret = (wmt_swi2c_SetClock(0)) ? 1 : 0;
+	else if (wmt_swi2c_SetClock(0))
+		ret = 1;
+	wmt_swi2c_SetSDAOutput();
+	return ret;
+}
+
+int wmt_swi2c_ReadAck(unsigned char *byte, int last)
+{
+	unsigned char i;
+	unsigned char Data = 0;
+
+	wmt_swi2c_SetSDAInput();
+
+	for (i = 0; i < 8; i++) {
+		if (wmt_swi2c_SetClock(1)) {
+			wmt_swi2c_SetSDAOutput();
+			return 1;
+		}
+		Data <<= 1;
+		wmt_swi2c_delay(0);
+		Data |= wmt_swi2c_GetSDA();
+		if (wmt_swi2c_SetClock(0)) {
+			wmt_swi2c_SetSDAOutput();
+			return 1;
+		}
+	}
+
+	*byte = Data;
+	wmt_swi2c_SetSDAOutput();
+
+	wmt_swi2c_delay(0);
+	if (wmt_swi2c_SetData((last) ? 1 : 0))
+		return 1;
+	if (wmt_swi2c_SetClock(1))
+		return 1;
+	wmt_swi2c_delay(0);
+	if (wmt_swi2c_SetClock(0))
+		return 1;
+	wmt_swi2c_delay(0);
+	return 0;
+}
+
+int wmt_swi2c_tx(
+	char addr,
+	char *buf,
+	int  cnt,
+	int *ret_cnt
+)
+{
+	int ret = 0;
+	unsigned char i;
+
+	wmt_swi2c_lock(1);
+
+	ret |= wmt_swi2c_StartI2C();
+	if (ret)
+		goto tx_end;
+	ret |= wmt_swi2c_WriteAck(addr);
+	if (ret)
+		goto tx_end;
+	for (i = 0; i < cnt; i++) {
+		ret |= wmt_swi2c_WriteAck(buf[i]);
+		if (ret)
+			goto tx_end;
+	}
+	ret |= wmt_swi2c_StopI2C();
+tx_end:
+	wmt_swi2c_lock(0);
+	return ret;
+}
+
+int wmt_swi2c_rx(
+	char addr,
+	char *buf,
+	int cnt,
+	int *ret_cnt
+)
+{
+	int ret = 0;
+	int i;
+
+	wmt_swi2c_lock(1);
+
+	ret |= wmt_swi2c_StartI2C();
+	if (ret)
+		goto rx_end;
+	ret |= wmt_swi2c_WriteAck(addr | 0x01);
+	if (ret)
+		goto rx_end;
+	for (i = 0; i < cnt; i++) {
+		ret |= wmt_swi2c_ReadAck((unsigned char *)&buf[i],
+			(i == (cnt - 1)));
+		if (ret)
+			goto rx_end;
+	}
+	ret |= wmt_swi2c_StopI2C();
+rx_end:
+	wmt_swi2c_lock(0);
+	return ret;
+}
+
+void wmt_swi2c_reg_bk(struct swi2c_reg_s *reg_p,
+	struct swi2c_reg_bk_t *reg_bk, int bk)
+{
+	if (bk) {
+		reg_bk->gpio_en = inw(reg_p->gpio_en);
+		reg_bk->out_en = inw(reg_p->out_en);
+		reg_bk->data_out = inw(reg_p->data_out);
+		reg_bk->pull_en = inw(reg_p->pull_en);
+	} else {
+		outw(reg_bk->gpio_en, reg_p->gpio_en);
+		outw(reg_bk->out_en, reg_p->out_en);
+		outw(reg_bk->data_out, reg_p->data_out);
+		outw(reg_bk->pull_en, reg_p->pull_en);
+	}
+}
+
+int wmt_swi2c_read(
+	struct swi2c_handle_s *handle,
+	char addr,
+	char index,
+	char *buf,
+	int cnt
+)
+{
+	int ret = 0;
+	char buffer[24];
+	int temp = 0;
+	struct swi2c_reg_bk_t scl_bk, sda_bk;
+
+	swi2c_scl = handle->scl_reg;
+	swi2c_sda = handle->sda_reg;
+
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1);
+
+	buffer[0] = index;
+	ret = wmt_swi2c_tx(addr, buffer, 1, &temp);
+	if (ret) {
+		DPRINT("[SWI2C] *E* tx fail\n");
+		goto exit;
+	}
+	ret = wmt_swi2c_rx(addr, buf, cnt, &temp);
+	if (ret) {
+		DPRINT("[SWI2C] *E* rx fail\n");
+		goto exit;
+	}
+exit:
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0);
+	return ret;
+}
+EXPORT_SYMBOL(wmt_swi2c_read);
+
+int wmt_swi2c_write(
+	struct swi2c_handle_s *handle,
+	char addr,
+	char index,
+	char *buf,
+	int cnt
+)
+{
+	int ret = 0;
+	char buffer[24];
+	int temp;
+	struct swi2c_reg_bk_t scl_bk, sda_bk;
+
+	swi2c_scl = handle->scl_reg;
+	swi2c_sda = handle->sda_reg;
+
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1);
+
+	buffer[0] = index;
+	buffer[1] = *buf;
+	ret = wmt_swi2c_tx(addr, buffer, cnt, &temp);
+	if (ret) {
+		DPRINT("[SWI2C] *E* tx fail\n");
+		goto exit;
+	}
+exit:
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0);
+	return ret;
+}
+EXPORT_SYMBOL(wmt_swi2c_write);
+
+int wmt_swi2c_check(struct swi2c_handle_s *handle)
+{
+	int ret = 0;
+#if 0
+	struct swi2c_reg_s *reg_p;
+	struct swi2c_reg_bk_t scl_bk, sda_bk;
+
+	swi2c_scl = handle->scl_reg;
+	swi2c_sda = handle->sda_reg;
+
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 1);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 1);
+	reg_p = handle->scl_reg;
+	do {
+		outw(inw(reg_p->gpio_en) | reg_p->bit_mask, reg_p->gpio_en);
+		outw(inw(reg_p->out_en) | reg_p->bit_mask, reg_p->out_en);
+		outw(inw(reg_p->data_out) & ~reg_p->bit_mask, reg_p->data_out);
+
+		outw(inw(reg_p->out_en) & ~reg_p->bit_mask, reg_p->out_en);
+		if (reg_p->pull_en)
+			outw(inw(reg_p->pull_en) & ~reg_p->pull_en_bit_mask,
+				reg_p->pull_en);
+		if (inw(reg_p->data_in) & reg_p->bit_mask) {
+			if (reg_p == handle->sda_reg)
+				break;
+			reg_p = handle->sda_reg;
+		} else {
+			ret = 1;
+			break;
+		}
+	} while (1);
+	wmt_swi2c_reg_bk(swi2c_scl, &scl_bk, 0);
+	wmt_swi2c_reg_bk(swi2c_sda, &sda_bk, 0);
+	DPRINT("[SWI2C] %s exist\n", (ret) ? "not" : "");
+#endif
+	return ret;
+}
+EXPORT_SYMBOL(wmt_swi2c_check);
diff --git a/drivers/video/wmt/sw_i2c.h b/drivers/video/wmt/sw_i2c.h
new file mode 100755
index 00000000..593fd08f
--- /dev/null
+++ b/drivers/video/wmt/sw_i2c.h
@@ -0,0 +1,63 @@
+/*++
+ * linux/drivers/video/wmt/sw_i2c.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef _SWI2C_H_
+#define _SWI2C_H_
+
+struct swi2c_reg_s {
+	unsigned int bit_mask;
+	unsigned int gpio_en;
+	unsigned int out_en;
+	unsigned int data_in;
+	unsigned int data_out;
+	unsigned int pull_en_bit_mask;
+	unsigned int pull_en;
+};
+#define swi2c_reg_t struct swi2c_reg_s
+
+struct swi2c_handle_s {
+	struct swi2c_reg_s *scl_reg;
+	struct swi2c_reg_s *sda_reg;
+};
+#define swi2c_handle_t struct swi2c_handle_s
+
+int wmt_swi2c_read(
+	struct swi2c_handle_s *handle,
+	char addr,
+	char index,
+	char *buf,
+	int cnt
+);
+
+int wmt_swi2c_write(
+	struct swi2c_handle_s *handle,
+	char addr,
+	char index,
+	char *buf,
+	int cnt
+);
+
+int wmt_swi2c_check(struct swi2c_handle_s *handle);
+
+#endif
+
diff --git a/drivers/video/wmt/vout-wmt.c b/drivers/video/wmt/vout-wmt.c
new file mode 100755
index 00000000..b7ff0bf4
--- /dev/null
+++ b/drivers/video/wmt/vout-wmt.c
@@ -0,0 +1,1344 @@
+/*++
+ * linux/drivers/video/wmt/vout-wmt.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "vpp.h"
+
+#ifndef CFG_LOADER
+static int vo_plug_flag;
+#endif
+int vo_plug_vout;
+int (*vo_plug_func)(int hotplug);
+enum vout_mode_t dvo_vout_mode;
+enum vout_mode_t int_vout_mode;
+int hdmi_cur_plugin;
+struct vout_t *vo_poll_vout;
+
+/* GPIO 10 & 11 */
+struct swi2c_reg_s vo_gpio_scl = {
+	.bit_mask = BIT10,
+	.gpio_en = (__GPIO_BASE + 0x40),
+	.out_en = (__GPIO_BASE + 0x80),
+	.data_in = (__GPIO_BASE + 0x00),
+	.data_out = (__GPIO_BASE + 0xC0),
+	.pull_en = (__GPIO_BASE + 0x480),
+	.pull_en_bit_mask = BIT10,
+};
+
+struct swi2c_reg_s vo_gpio_sda = {
+	.bit_mask = BIT11,
+	.gpio_en = (__GPIO_BASE + 0x40),
+	.out_en = (__GPIO_BASE + 0x80),
+	.data_in = (__GPIO_BASE + 0x00),
+	.data_out = (__GPIO_BASE + 0xC0),
+	.pull_en = (__GPIO_BASE + 0x480),
+	.pull_en_bit_mask = BIT11,
+};
+
+struct swi2c_handle_s vo_swi2c_dvi = {
+	.scl_reg = &vo_gpio_scl,
+	.sda_reg = &vo_gpio_sda,
+};
+
+#define DVI_POLL_TIME_MS	1000
+
+extern void hdmi_config_audio(struct vout_audio_t *info);
+
+/*---------------------------------- API ------------------------------------*/
+#ifdef DEBUG
+void vout_print_entry(struct vout_t *vo)
+{
+	if (vo == 0)
+		return;
+
+	MSG(" =============== vout %d ===============\n", vo->num);
+	MSG("fix 0x%x", vo->fix_cap);
+	MSG("(inf %d,bus %d,govr %d,ext dev %d,fix plug %d,aud %d,edid %d)\n",
+		(vo->fix_cap & VOUT_CAP_INTERFACE),
+		(vo->fix_cap & VOUT_CAP_BUS) >> 8,
+		(vo->fix_cap & VOUT_CAP_GOVR) >> 12,
+		(vo->fix_cap & VOUT_CAP_EXT_DEV) ? 1 : 0,
+		(vo->fix_cap & VOUT_CAP_FIX_PLUG) ? 1 : 0,
+		(vo->fix_cap & VOUT_CAP_AUDIO) ? 1 : 0,
+		(vo->fix_cap & VOUT_CAP_EDID) ? 1 : 0);
+	MSG("info %d,%s\n", vo->info->num, vpp_mod_str[vo->govr->mod]);
+	MSG("inf 0x%x,dev 0x%x\n", (int)vo->inf, (int)vo->dev);
+	MSG("resx %d,resy %d,fps %d\n", vo->resx, vo->resy, vo->fps);
+	MSG("pixclk %d,option %d,%d,%d,disable %d\n", vo->pixclk,
+		vo->option[0], vo->option[1], vo->option[2], vo->disable);
+	MSG("sts(reg %d,act %d,plug %d,edid %d,blank %d,pwrdn %d,cp %d)\n",
+		(vo->status & VPP_VOUT_STS_REGISTER) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_ACTIVE) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_PLUGIN) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_EDID) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_BLANK) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_POWERDN) ? 1 : 0,
+		(vo->status & VPP_VOUT_STS_CONTENT_PROTECT) ? 1 : 0);
+
+	if (vo->inf) {
+		MSG(" ===== inf entry =====\n");
+		MSG("mode %d, %s\n",
+			vo->inf->mode, vout_inf_str[vo->inf->mode]);
+	}
+
+	if (vo->dev) {
+		MSG(" ===== dev entry =====\n");
+		MSG("name %s,inf %d,%s\n", vo->dev->name,
+			vo->dev->mode, vout_inf_str[vo->dev->mode]);
+		MSG("vout 0x%x,capability 0x%x\n",
+			(int)vo->dev->vout, vo->dev->capability);
+	}
+}
+#endif
+
+int vo_i2c_proc(int id, unsigned int addr, unsigned int index,
+			char *pdata, int len)
+{
+	struct swi2c_handle_s *handle = 0;
+	int ret = 0;
+
+	switch (id) {
+	case 1:	/* dvi */
+		if (lcd_get_type())	/* share pin with LVDS */
+			return -1;
+		handle = &vo_swi2c_dvi;
+		break;
+	default:
+		break;
+	}
+
+	if (handle) {
+		if (wmt_swi2c_check(handle))
+			return -1;
+		if (addr & 0x1) { /* read */
+			*pdata = 0xff;
+#ifdef CONFIG_WMT_EDID
+			ret = wmt_swi2c_read(handle, addr & ~0x1,
+						index, pdata, len);
+#else
+			ret = -1;
+#endif
+		} else { /* write */
+			DBG_ERR("not support sw i2c write\n");
+		}
+	}
+	return ret;
+}
+
+#ifndef CONFIG_UBOOT
+static void vo_do_plug(struct work_struct *ptr)
+{
+	struct vout_t *vo;
+	int plugin;
+
+	if (vo_plug_func == 0)
+		return;
+
+	vo = vout_get_entry(vo_plug_vout);
+	govrh_set_dvo_enable(vo->govr, 1);
+	plugin = vo_plug_func(1);
+/*	govrh_set_dvo_enable(vo->govr, plugin); */
+	vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin);
+	vo_plug_flag = 0;
+	DBG_DETAIL("vo_do_plug %d\n", plugin);
+	/* GPIO irq enable */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, 0x80, 7, 1);
+	/* GPIO input mode */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x80, 0x1 << VPP_VOINT_NO,
+				VPP_VOINT_NO, 0x0);
+#ifdef __KERNEL__
+	vpp_netlink_notify_plug(VPP_VOUT_NUM_DVI, plugin);
+#endif
+	return;
+}
+
+DECLARE_DELAYED_WORK(vo_plug_work, vo_do_plug);
+
+static irqreturn_t vo_plug_interrupt_routine
+(
+	int irq,		/*!<; // irq id */
+	void *dev_id		/*!<; // device id */
+)
+{
+	DBG_DETAIL("Enter\n");
+	if ((inb(GPIO_BASE_ADDR + 0x360) &
+		(0x1 << VPP_VOINT_NO)) == 0)
+		return IRQ_NONE;
+
+	/* clear int status */
+	outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360);
+#ifdef __KERNEL__
+	/* if (vo_plug_flag == 0) { */
+	/* GPIO irq disable */
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO, 0x80, 7, 0);
+	schedule_delayed_work(&vo_plug_work, HZ/5);
+	vo_plug_flag = 1;
+	/* } */
+#else
+	if (vo_plug_func)
+		vo_do_plug(0);
+#endif
+	return IRQ_HANDLED;
+}
+
+#define CONFIG_VO_POLL_WORKQUEUE
+struct timer_list vo_poll_timer;
+#ifdef CONFIG_VO_POLL_WORKQUEUE
+static void vo_do_poll(struct work_struct *ptr)
+{
+	struct vout_t *vo;
+
+	vo = vo_poll_vout;
+	if (vo) {
+		if (vo->dev)
+			vo->dev->poll();
+		mod_timer(&vo_poll_timer,
+			jiffies + msecs_to_jiffies(vo_poll_timer.data));
+	}
+	return;
+}
+
+DECLARE_DELAYED_WORK(vo_poll_work, vo_do_poll);
+#else
+struct tasklet_struct vo_poll_tasklet;
+static void vo_do_poll_tasklet
+(
+	unsigned long data		/*!<; // tasklet input data */
+)
+{
+	struct vout_t *vo;
+
+	vpp_lock();
+	vo = vo_poll_vout;
+	if (vo) {
+		if (vo->dev)
+			vo->dev->poll();
+		mod_timer(&vo_poll_timer,
+			jiffies + msecs_to_jiffies(vo_poll_timer.data));
+	}
+	vpp_unlock();
+}
+#endif
+
+void vo_do_poll_tmr(int ms)
+{
+#ifdef CONFIG_VO_POLL_WORKQUEUE
+	schedule_delayed_work(&vo_poll_work, msecs_to_jiffies(ms));
+#else
+	tasklet_schedule(&vo_poll_tasklet);
+#endif
+}
+
+static void vo_set_poll(struct vout_t *vo, int on, int ms)
+{
+	DMSG("%d\n", on);
+
+	if (on) {
+		vo_poll_vout = vo;
+		if (vo_poll_timer.function) {
+			vo_poll_timer.data = ms / 2;
+			mod_timer(&vo_poll_timer,
+				jiffies + msecs_to_jiffies(vo_poll_timer.data));
+		} else {
+			init_timer(&vo_poll_timer);
+			vo_poll_timer.data = ms / 2;
+			vo_poll_timer.function = (void *) vo_do_poll_tmr;
+			vo_poll_timer.expires = jiffies +
+				msecs_to_jiffies(vo_poll_timer.data);
+			add_timer(&vo_poll_timer);
+		}
+#ifndef CONFIG_VO_POLL_WORKQUEUE
+		tasklet_init(&vo_poll_tasklet, vo_do_poll_tasklet, 0);
+#endif
+	} else {
+		del_timer(&vo_poll_timer);
+#ifndef CONFIG_VO_POLL_WORKQUEUE
+		tasklet_kill(&vo_poll_tasklet);
+#endif
+		vo_poll_vout = 0;
+	}
+}
+#endif
+
+void vout_set_int_type(int type)
+{
+	unsigned char reg;
+
+	reg = inb(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO);
+	reg &= ~0x7;
+	switch (type) {
+	case 0:	/* low level */
+	case 1:	/* high level */
+	case 2:	/* falling edge */
+	case 3:	/* rising edge */
+	case 4:	/* rising edge or falling */
+		reg |= type;
+		break;
+	default:
+		break;
+	}
+	outb(reg, GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO);
+}
+EXPORT_SYMBOL(vout_set_int_type);
+
+void vout_set_int_enable(int enable)
+{
+	vppif_reg32_write(GPIO_BASE_ADDR + 0x300 +
+		VPP_VOINT_NO, 0x80, 7, enable);	/* GPIO irq enable/disable */
+}
+EXPORT_SYMBOL(vout_set_int_enable);
+
+int vout_get_clr_int(void)
+{
+	if ((inb(GPIO_BASE_ADDR + 0x360) &
+		(0x1 << VPP_VOINT_NO)) == 0)
+		return 1;
+	/* clear int status */
+	outb(0x1 << VPP_VOINT_NO, GPIO_BASE_ADDR + 0x360);
+	return 0;
+}
+EXPORT_SYMBOL(vout_get_clr_int);
+
+static void vo_plug_enable(int enable, void *func, int no)
+{
+	struct vout_t *vo;
+
+	DBG_DETAIL("%d\n", enable);
+	vo_plug_vout = no;
+	vo = vout_get_entry(no);
+#ifdef CONFIG_WMT_EXT_DEV_PLUG_DISABLE
+	vo_plug_func = 0;
+	govrh_set_dvo_enable(vo->govr, enable);
+#else
+	vo_plug_func = func;
+	if (vo_plug_func == 0)
+		return;
+
+	if (enable) {
+		vppif_reg32_write(GPIO_BASE_ADDR + 0x40, 0x1 << VPP_VOINT_NO,
+			VPP_VOINT_NO, 0x0); /* GPIO disable */
+		vppif_reg32_write(GPIO_BASE_ADDR + 0x80, 0x1 << VPP_VOINT_NO,
+			VPP_VOINT_NO, 0x0); /* GPIO input mode */
+		vppif_reg32_write(GPIO_BASE_ADDR + 0x480, 0x1 << VPP_VOINT_NO,
+			VPP_VOINT_NO, 0x1); /* GPIO pull enable */
+		vppif_reg32_write(GPIO_BASE_ADDR + 0x4c0, 0x1 << VPP_VOINT_NO,
+			VPP_VOINT_NO, 0x1); /* GPIO pull-up */
+#ifndef CONFIG_UBOOT
+		vo_do_plug(0);
+		if (vpp_request_irq(IRQ_GPIO, vo_plug_interrupt_routine,
+			IRQF_SHARED, "vo plug", (void *) &vo_plug_vout))
+			DBG_ERR("request GPIO ISR fail\n");
+
+		vppif_reg32_write(GPIO_BASE_ADDR + 0x300 + VPP_VOINT_NO,
+			0x80, 7, 1); /* GPIO irq enable */
+	} else {
+		vpp_free_irq(IRQ_GPIO, (void *) &vo_plug_vout);
+#endif
+	}
+#endif
+}
+
+/*--------------------------------- DVI ------------------------------------*/
+#ifdef WMT_FTBLK_VOUT_DVI
+static int vo_dvi_blank(struct vout_t *vo, enum vout_blank_t arg)
+{
+	DMSG("(%d, %d)\n", vo->pre_blank, arg);
+        if(vo->pre_blank == arg)
+                return 0;
+
+        if (vo->pre_blank == VOUT_BLANK_POWERDOWN) {
+                if (vo->dev) {
+#ifdef __KERNEL__
+                        if (!g_vpp.dvi_int_disable && vo->dev->interrupt)
+                                vo_plug_enable(VPP_FLAG_ENABLE,
+                                                vo->dev->interrupt, vo->num);
+                        else if (vo->dev->poll)
+                                vo_set_poll(vo, (vo->dev->poll) ? 1 : 0,
+                                        DVI_POLL_TIME_MS);
+#endif
+                }
+        }
+#ifdef __KERNEL__
+        if (arg == VOUT_BLANK_POWERDOWN)
+                vo_set_poll(vo, 0, 0);
+#endif
+        if (!lcd_get_dev()) /* enable DVO not contain LCD */
+                govrh_set_dvo_enable(vo->govr,
+                                (arg == VOUT_BLANK_UNBLANK) ? 1 : 0);
+        vo->pre_blank = arg;
+        return 0;
+}
+
+static int vo_dvi_config(struct vout_t *vo, int arg)
+{
+	struct vout_info_t *vo_info;
+
+	DBG_DETAIL("Enter\n");
+
+	vo_info = (struct vout_info_t *) arg;
+	govrh_set_dvo_sync_polar(vo->govr,
+		(vo_info->option & VPP_DVO_SYNC_POLAR_HI) ? 0 : 1,
+		(vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1);
+	return 0;
+}
+
+static int vo_dvi_init(struct vout_t *vo, int arg)
+{
+	unsigned int clk_delay;
+
+	DBG_DETAIL("(%d)\n", arg);
+
+	vo->pre_blank = VOUT_BLANK_POWERDOWN;
+
+	lvds_set_enable(0);
+	govrh_set_dvo_color_format(vo->govr, vo->option[0]);
+	govrh_set_dvo_outdatw(vo->govr, vo->option[1] & WMT_DISP_FB_DVI_24BIT);
+	govrh_IGS_set_mode(vo->govr, 0, WMT_DISP_FB_GET_RGB_MODE(vo->option[1]),
+		(vo->option[1] & WMT_DISP_FB_MSB) ? 1 : 0);
+	govrh_IGS_set_RGB_swap(vo->govr, WMT_DISP_FB_RGB_SWAP(vo->option[1]));
+	clk_delay = (vo->option[1] & WMT_DISP_FB_DVI_24BIT) ?
+		VPP_GOVR_DVO_DELAY_24 : VPP_GOVR_DVO_DELAY_12;
+	govrh_set_dvo_clock_delay(vo->govr, ((clk_delay & BIT14) != 0x0),
+		clk_delay & 0x3FFF);
+	if (vo->dev) {
+		vo->dev->set_mode(&vo->option[0]);
+		vo->dev->set_power_down(VPP_FLAG_DISABLE);
+		if (!g_vpp.dvi_int_disable && vo->dev->interrupt)
+			vo_plug_enable(VPP_FLAG_ENABLE,
+					vo->dev->interrupt, vo->num);
+#ifdef __KERNEL__
+		else if (vo->dev->poll) {
+			vo_set_poll(vo, (vo->dev->poll) ? 1 : 0,
+					DVI_POLL_TIME_MS);
+		}
+#endif
+		vout_change_status(vo, VPP_VOUT_STS_PLUGIN,
+				vo->dev->check_plugin(0));
+	}
+	vo->govr->fb_p->set_csc(vo->govr->fb_p->csc_mode);
+	if (!lcd_get_dev()) {
+		govrh_set_dvo_enable(vo->govr,
+			(vo->status & VPP_VOUT_STS_BLANK) ? 0 : 1);
+	}
+	return 0;
+}
+
+static int vo_dvi_uninit(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+
+	vo_plug_enable(VPP_FLAG_DISABLE, 0, VPP_VOUT_NUM);
+	govrh_set_dvo_enable(vo->govr, VPP_FLAG_DISABLE);
+#ifdef __KERNEL__
+	vo_set_poll(vo, 0, DVI_POLL_TIME_MS);
+#endif
+	return 0;
+}
+
+static int vo_dvi_chkplug(struct vout_t *vo, int arg)
+{
+	int plugin = 1;
+
+	DBG_MSG("plugin %d\n", plugin);
+	return plugin;
+}
+
+static int vo_dvi_get_edid(struct vout_t *vo, int arg)
+{
+	char *buf;
+	int i, cnt;
+
+	DBG_DETAIL("Enter\n");
+
+	buf = (char *) arg;
+	memset(&buf[0], 0x0, 128 * EDID_BLOCK_MAX);
+	if (vpp_i2c_read(VPP_DVI_EDID_ID, 0xA0, 0, &buf[0], 128)) {
+		DBG_ERR("read edid\n");
+		return 1;
+	}
+
+	if (edid_checksum(buf, 128)) {
+		DBG_ERR("checksum\n");
+		return 1;
+	}
+
+	cnt = buf[0x7E];
+	if (cnt >= 3)
+		cnt = 3;
+	for (i = 1; i <= cnt; i++) {
+		vpp_i2c_read(VPP_DVI_EDID_ID, 0xA0, 0x80 * i,
+			&buf[128 * i], 128);
+	}
+	return 0;
+}
+
+struct vout_inf_t vo_dvi_inf = {
+	.mode = VOUT_INF_DVI,
+	.init = vo_dvi_init,
+	.uninit = vo_dvi_uninit,
+	.blank = vo_dvi_blank,
+	.config = vo_dvi_config,
+	.chkplug = vo_dvi_chkplug,
+	.get_edid = vo_dvi_get_edid,
+};
+
+int vo_dvi_initial(void)
+{
+	vout_inf_register(VOUT_INF_DVI, &vo_dvi_inf);
+	return 0;
+}
+module_init(vo_dvi_initial);
+
+#endif /* WMT_FTBLK_VOUT_DVI */
+
+/*---------------------------------- HDMI -----------------------------------*/
+void vo_hdmi_set_clock(int enable)
+{
+	DBG_DETAIL("(%d)\n", enable);
+
+	enable = (enable) ? CLK_ENABLE : CLK_DISABLE;
+	vpp_set_clock_enable(DEV_HDMII2C, enable, 0);
+	vpp_set_clock_enable(DEV_HDMI, enable, 0);
+	vpp_set_clock_enable(DEV_HDCE, enable, 0);
+}
+
+#ifdef WMT_FTBLK_VOUT_HDMI
+#ifdef __KERNEL__
+struct timer_list hdmi_cp_timer;
+static struct timer_list hdmi_plug_timer;
+#endif
+
+void vo_hdmi_cp_set_enable_tmr(int sec)
+{
+#ifdef __KERNEL__
+	int ms = sec * 1000;
+#endif
+
+	DBG_MSG("[HDMI] set enable tmr %d sec\n", sec);
+
+	if (sec == 0) {
+		hdmi_set_cp_enable(VPP_FLAG_ENABLE);
+		return ;
+	}
+#ifdef __KERNEL__
+	if (hdmi_cp_timer.function)
+		del_timer(&hdmi_cp_timer);
+	init_timer(&hdmi_cp_timer);
+	hdmi_cp_timer.data = VPP_FLAG_ENABLE;
+	hdmi_cp_timer.function = (void *) hdmi_set_cp_enable;
+	hdmi_cp_timer.expires = jiffies + msecs_to_jiffies(ms);
+	add_timer(&hdmi_cp_timer);
+#else
+	hdmi_set_cp_enable(VPP_FLAG_ENABLE);
+#endif
+}
+EXPORT_SYMBOL(vo_hdmi_cp_set_enable_tmr);
+
+static int vo_hdmi_blank(struct vout_t *vo, enum vout_blank_t arg)
+{
+	int enable;
+
+	DBG_DETAIL("(%d)\n", arg);
+
+	enable = (arg == VOUT_BLANK_UNBLANK) ? 1 : 0;
+	if (g_vpp.hdmi_cp_enable && enable)
+		vo_hdmi_cp_set_enable_tmr(2);
+	else
+		hdmi_set_cp_enable(VPP_FLAG_DISABLE);
+	hdmi_set_enable(enable);
+	hdmi_set_power_down((enable) ? 0 : 1);
+	return 0;
+}
+
+#ifndef CFG_LOADER
+static irqreturn_t vo_hdmi_cp_interrupt
+(
+	int irq,		/*!<; // irq id */
+	void *dev_id		/*!<; // device id */
+)
+{
+	struct vout_t *vo;
+
+	DBG_DETAIL("%d\n", irq);
+	vo = vout_get_entry(VPP_VOUT_NUM_HDMI);
+	switch (hdmi_check_cp_int()) {
+	case 1:
+		if (hdmi_cp)
+			hdmi_cp->enable(VPP_FLAG_DISABLE);
+		vo_hdmi_cp_set_enable_tmr(HDMI_CP_TIME);
+		vout_change_status(vo, VPP_VOUT_STS_CONTENT_PROTECT, 0);
+		vpp_netlink_notify_cp(0);
+		break;
+	case 0:
+		vout_change_status(vo, VPP_VOUT_STS_CONTENT_PROTECT, 1);
+		vpp_netlink_notify_cp(1);
+		break;
+	case 2:
+		hdmi_ri_tm_cnt = 3 * 30;
+		break;
+	default:
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef __KERNEL__
+static void vo_hdmi_do_plug(struct work_struct *ptr)
+#else
+static void vo_hdmi_do_plug(void)
+#endif
+{
+	struct vout_t *vo;
+	int plugin;
+	int option = 0;
+
+	plugin = hdmi_check_plugin(1);
+	vo = vout_get_entry(VPP_VOUT_NUM_HDMI);
+	vout_change_status(vo, VPP_VOUT_STS_PLUGIN, plugin);
+	if (plugin) {
+		option = vout_get_edid_option(VPP_VOUT_NUM_HDMI);
+#ifdef CONFIG_VPP_DEMO
+		option |= (EDID_OPT_HDMI + EDID_OPT_AUDIO);
+#endif
+		hdmi_set_option(option);
+	} else {
+		g_vpp.hdmi_bksv[0] = g_vpp.hdmi_bksv[1] = 0;
+	}
+	vo_hdmi_blank(vo, (vo->status & VPP_VOUT_STS_BLANK) ? 1 : !(plugin));
+	if (!g_vpp.hdmi_certify_flag)
+		hdmi_hotplug_notify(plugin);
+	DBG_MSG("%d\n", plugin);
+	return;
+}
+DECLARE_WORK(vo_hdmi_plug_work, vo_hdmi_do_plug);
+
+static void hdmi_handle_plug(vpp_flag_t enable)
+{
+	schedule_work(&vo_hdmi_plug_work);
+}
+
+static void vo_hdmi_handle_plug_tmr(int ms)
+{
+	static int timer_init;
+
+	if (timer_init == 0) {
+		init_timer(&hdmi_plug_timer);
+		hdmi_plug_timer.data = VPP_FLAG_ENABLE;
+		hdmi_plug_timer.function = (void *) hdmi_handle_plug;
+		timer_init = 1;
+	}
+	hdmi_plug_timer.expires = jiffies + msecs_to_jiffies(ms);
+	mod_timer(&hdmi_plug_timer, hdmi_plug_timer.expires);
+}
+
+static irqreturn_t vo_hdmi_plug_interrupt
+(
+	int irq,		/*!<; // irq id */
+	void *dev_id		/*!<; // device id */
+)
+{
+	DBG_MSG("vo_hdmi_plug_interrupt %d\n", irq);
+	hdmi_clear_plug_status();
+	if (g_vpp.hdmi_certify_flag)
+		vo_hdmi_do_plug(0);
+	else
+		vo_hdmi_handle_plug_tmr(HDMI_PLUG_DELAY);
+	return IRQ_HANDLED;
+}
+#endif
+
+static int vo_hdmi_init(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+
+	vo_hdmi_set_clock(1);
+	vout_change_status(vout_get_entry(VPP_VOUT_NUM_HDMI),
+		VPP_VOUT_STS_PLUGIN, hdmi_check_plugin(0));
+	hdmi_enable_plugin(1);
+
+	if (g_vpp.hdmi_disable)
+		return 0;
+#ifndef CONFIG_UBOOT
+	if (vpp_request_irq(VPP_IRQ_HDMI_CP, vo_hdmi_cp_interrupt,
+		SA_INTERRUPT, "hdmi cp", (void *) 0)) {
+		DBG_ERR("*E* request HDMI ISR fail\n");
+	}
+	if (vpp_request_irq(VPP_IRQ_HDMI_HPDH, vo_hdmi_plug_interrupt,
+		SA_INTERRUPT, "hdmi plug", (void *) 0)) {
+		DBG_ERR("*E* request HDMI ISR fail\n");
+	}
+	if (vpp_request_irq(VPP_IRQ_HDMI_HPDL, vo_hdmi_plug_interrupt,
+		SA_INTERRUPT, "hdmi plug", (void *) 0)) {
+		DBG_ERR("*E* request HDMI ISR fail\n");
+	}
+#endif
+	hdmi_set_enable((vo->status & VPP_VOUT_STS_BLANK) ?
+		VPP_FLAG_DISABLE : VPP_FLAG_ENABLE);
+	return 0;
+}
+
+static int vo_hdmi_uninit(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+	hdmi_enable_plugin(0);
+	hdmi_set_cp_enable(VPP_FLAG_DISABLE);
+	hdmi_set_enable(VPP_FLAG_DISABLE);
+#ifndef CONFIG_UBOOT
+	vpp_free_irq(VPP_IRQ_HDMI_CP, (void *) 0);
+	vpp_free_irq(VPP_IRQ_HDMI_HPDH, (void *) 0);
+	vpp_free_irq(VPP_IRQ_HDMI_HPDL, (void *) 0);
+#endif
+	vo_hdmi_set_clock(0);
+	return 0;
+}
+
+static int vo_hdmi_config(struct vout_t *vo, int arg)
+{
+	struct vout_info_t *vo_info;
+	vdo_color_fmt colfmt;
+
+	hdmi_set_enable(0);
+	vo_info = (struct vout_info_t *) arg;
+
+	DBG_DETAIL("(%dx%d@%d)\n", vo_info->resx, vo_info->resy, vo_info->fps);
+
+	/* 1280x720@60, HDMI pixel clock 74250060 not 74500000 */
+	if ((vo_info->resx == 1280)
+		&& (vo_info->resy == 720) && (vo_info->pixclk == 74500000))
+		vo_info->pixclk = 74250060;
+	colfmt = (vo->option[0] == VDO_COL_FMT_YUV422V) ?
+		VDO_COL_FMT_YUV422H : vo->option[0];
+	hdmi_cur_plugin = hdmi_check_plugin(0);
+	hdmi_info.option = (hdmi_cur_plugin) ?
+		vout_get_edid_option(VPP_VOUT_NUM_HDMI) : 0;
+	hdmi_info.outfmt = colfmt;
+	hdmi_info.vic = hdmi_get_vic(vo_info->resx, vo_info->resy,
+		vo_info->fps, (vo_info->option & VPP_OPT_INTERLACE) ? 1 : 0);
+
+	govrh_set_csc_mode(vo->govr, vo->govr->fb_p->csc_mode);
+	hdmi_set_sync_low_active((vo_info->option & VPP_DVO_SYNC_POLAR_HI) ?
+		0 : 1, (vo_info->option & VPP_DVO_VSYNC_POLAR_HI) ? 0 : 1);
+	hdmi_config(&hdmi_info);
+#ifdef __KERNEL__
+	mdelay(200);	/* patch for VIZIO change resolution issue */
+#endif
+	hdmi_cur_plugin = hdmi_check_plugin(0);
+	vo_hdmi_blank(vo, (vo->status & VPP_VOUT_STS_BLANK) ?
+		1 : !(hdmi_cur_plugin));
+	return 0;
+}
+
+static int vo_hdmi_chkplug(struct vout_t *vo, int arg)
+{
+	int plugin;
+
+	if (g_vpp.hdmi_disable)
+		return 0;
+	plugin = hdmi_get_plugin();
+	DBG_DETAIL("%d\n", plugin);
+	return plugin;
+}
+
+static int vo_hdmi_get_edid(struct vout_t *vo, int arg)
+{
+	char *buf;
+#ifdef CONFIG_WMT_EDID
+	int i, cnt;
+#endif
+	DBG_DETAIL("Enter\n");
+	buf = (char *) arg;
+#ifdef CONFIG_WMT_EDID
+	memset(&buf[0], 0x0, 128*EDID_BLOCK_MAX);
+	if (!hdmi_get_plugin())
+		return 1;
+
+	if (hdmi_DDC_read(0xA0, 0x0, &buf[0], 128)) {
+		DBG_ERR("read edid\n");
+		return 1;
+	}
+
+	if (edid_checksum(buf, 128)) {
+		DBG_ERR("hdmi checksum\n");
+/*		g_vpp.dbg_hdmi_ddc_crc_err++; */
+		return 1;
+	}
+
+	cnt = buf[0x7E];
+	if (cnt >= 3)
+		cnt = 3;
+	for (i = 1; i <= cnt; i++)
+		hdmi_DDC_read(0xA0, 0x80 * i, &buf[128 * i], 128);
+#endif
+	return 0;
+}
+
+struct vout_inf_t vo_hdmi_inf = {
+	.mode = VOUT_INF_HDMI,
+	.init = vo_hdmi_init,
+	.uninit = vo_hdmi_uninit,
+	.blank = vo_hdmi_blank,
+	.config = vo_hdmi_config,
+	.chkplug = vo_hdmi_chkplug,
+	.get_edid = vo_hdmi_get_edid,
+};
+
+int vo_hdmi_initial(void)
+{
+	vout_inf_register(VOUT_INF_HDMI, &vo_hdmi_inf);
+	return 0;
+}
+module_init(vo_hdmi_initial);
+
+#endif /* WMT_FTBLK_VOUT_HDMI */
+
+/*--------------------------------- LVDS ------------------------------------*/
+#ifdef WMT_FTBLK_VOUT_LVDS
+int vo_lvds_init_flag;
+static int vo_lvds_blank(struct vout_t *vo, enum vout_blank_t arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+	if (arg == VOUT_BLANK_POWERDOWN) {
+		lvds_regs->test.b.tre_en = 0;
+	} else { /* avoid suspend signal not clear */
+		lvds_set_enable((arg == VOUT_BLANK_UNBLANK) ? 1 : 0);
+	}
+
+	if (vo_lvds_init_flag)
+		lvds_set_power_down(arg);
+	return 0;
+}
+
+static int vo_lvds_config(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+	lvds_set_power_down(VPP_FLAG_DISABLE);
+	vo_lvds_init_flag = 1;
+	return 0;
+}
+
+static int vo_lvds_init(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+
+	vpp_set_clock_enable(DEV_LVDS, 1, 0);
+	if (vo->dev)
+		vo->dev->set_mode(&vo->option[0]);
+	govrh_set_dvo_enable(p_govrh2, 0);
+	govrh_set_csc_mode(vo->govr, vo->govr->fb_p->csc_mode);
+	lvds_set_enable((vo->status & VPP_VOUT_STS_BLANK) ?
+		VPP_FLAG_DISABLE : VPP_FLAG_ENABLE);
+	return 0;
+}
+
+static int vo_lvds_uninit(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("(%d)\n", arg);
+	lvds_set_enable(VPP_FLAG_DISABLE);
+	if (vo->dev)
+		vo->dev->set_mode(0);
+	lvds_set_power_down(VPP_FLAG_ENABLE);
+	vpp_set_clock_enable(DEV_LVDS, 0, 0);
+	vo_lvds_init_flag = 0;
+	return 0;
+}
+
+static int vo_lvds_chkplug(struct vout_t *vo, int arg)
+{
+	DBG_DETAIL("\n");
+#if 0
+	vo = vout_get_info(VOUT_LVDS);
+	if (vo->dev)
+		return vo->dev->check_plugin(0);
+#endif
+	return 1;
+}
+
+struct vout_inf_t vo_lvds_inf = {
+	.mode = VOUT_INF_LVDS,
+	.capability = VOUT_INF_CAP_FIX_PLUG,
+	.init = vo_lvds_init,
+	.uninit = vo_lvds_uninit,
+	.blank = vo_lvds_blank,
+	.config = vo_lvds_config,
+	.chkplug = vo_lvds_chkplug,
+#ifdef WMT_FTBLK_VOUT_HDMI
+	.get_edid = vo_hdmi_get_edid,
+#endif
+};
+
+int vo_lvds_initial(void)
+{
+	vout_inf_register(VOUT_INF_LVDS, &vo_lvds_inf);
+	return 0;
+}
+module_init(vo_lvds_initial);
+
+#endif /* WMT_FTBLK_VOUT_LVDS */
+/*---------------------------------- API ------------------------------------*/
+#ifndef CFG_LOADER
+int vout_set_audio(struct vout_audio_t *arg)
+{
+	struct vout_t *vout;
+	int ret = 0;
+
+#if 0
+	vout = vout_get_info(VPP_VOUT_DVO2HDMI);
+	if (vout && (vout->status & VPP_VOUT_STS_PLUGIN)) {
+		if (vout->dev->set_audio)
+			vout->dev->set_audio(arg);
+	}
+#endif
+
+#ifdef WMT_FTBLK_VOUT_HDMI
+	vout = vout_get_entry(VPP_VOUT_NUM_HDMI);
+	if (vout) {
+		g_vpp.hdmi_ch_change = 1;
+		hdmi_config_audio(arg);
+		g_vpp.hdmi_ch_change = 0;
+		ret = 1;
+	}
+#endif
+	return ret;
+}
+#endif
+
+/* 3445 port1 : DVI/SDD, port2 : VGA/SDA, port3 : HDMI/LVDS */
+/* 3481 port1 : HDMI/LVDS, port2 : DVI */
+/* 3498 port1 : HDMI, port2 : DVI/LVDS */
+struct vout_t vout_entry_0 = {
+	.fix_cap = BIT(VOUT_INF_HDMI),
+	.option[0] = VDO_COL_FMT_ARGB,
+	.option[1] = VPP_DATAWIDHT_24,
+	.option[2] = 0,
+};
+
+struct vout_t vout_entry_1 = {
+	.fix_cap = BIT(VOUT_INF_DVI) + BIT(VOUT_INF_LVDS) +
+		VOUT_CAP_EXT_DEV + 0x100,	/* i2c bus 1,ext dev */
+	.option[0] = VDO_COL_FMT_ARGB,
+	.option[1] = VPP_DATAWIDHT_24,
+	.option[2] = 0,
+};
+
+int vout_add_display(int fb_no, unsigned int *parm)
+{
+	struct vout_info_t *info;
+	struct vout_t *vout;
+	int ret = 0;
+
+	info = vout_info[fb_no];
+	if (!info) {
+		info = kmalloc(sizeof(struct vout_info_t), GFP_KERNEL);
+		if (!info)
+			return 1;
+		memset(info, 0, sizeof(struct vout_info_t));
+		vout_info[fb_no] = info;
+		DBG_MSG("malloc vout_info %d,0x%x\n", fb_no, (int) info);
+#ifdef CONFIG_KERNEL
+		sema_init(&info->sem, 1);
+#endif
+	}
+
+	if (parm[0] == VOUT_BOOT) {
+		struct vout_t *vo_boot;
+
+		MSG("[VOUT] %s (%d:%d:%d)\n",
+			(fb_no == 0) ? "tvbox" : "virtual display",
+			parm[0], parm[1], parm[2]);
+		if (fb_no == 0) {
+			g_vpp.virtual_display = 1;
+			g_vpp.fb0_bitblit = 1;
+		} else {
+			g_vpp.stream_fb = fb_no;
+		}
+		vo_boot = kmalloc(sizeof(struct vout_t), GFP_KERNEL);
+		if (vo_boot == 0)
+			return 1;
+		memset(vo_boot, 0, sizeof(struct vout_t));
+		vo_boot->resx = parm[3];
+		vo_boot->resy = parm[4];
+		vo_boot->fps = parm[5];
+		vo_boot->num = VPP_VOUT_NUM;
+		vout_info_add_entry(fb_no, vo_boot);
+		kfree(vo_boot);
+		return 0;
+	}
+
+	vout = vout_get_entry_adapter(parm[0]);
+	vout->inf = vout_get_inf_entry_adapter(parm[0]);
+	vout->option[0] = parm[1];
+	vout->option[1] = parm[2];
+	vout->resx = parm[3];
+	vout->resy = parm[4];
+	vout->fps = parm[5];
+	vout->disable = (parm[2] & VOUT_OPT_BLANK) ? 1 : 0;
+	switch (parm[0]) {
+	case VOUT_LVDS:
+		{
+		struct fb_videomode *vmode = 0;
+
+		/* lvds auto detect edid */
+		if ((parm[1] == 0) && (parm[3] == 0) && (parm[4] == 0)) {
+			if (vout_get_edid_option(vout->num)) {
+				vmode = &vout->edid_info.detail_timing[0];
+				if (vmode->pixclock == 0) {
+					vmode = 0;
+					DBG_ERR("LVDS timing\n");
+				}
+			}
+
+			if (vout->inf->get_edid(vout, (int)vout->edid) == 0) {
+				if (edid_parse(vout->edid,
+					&vout->edid_info) == 0)
+					DBG_ERR("LVDS edid parse\n");
+			} else {
+				DBG_ERR("LVDS edid read\n");
+			}
+		}
+
+		if (vmode == 0) { /* use internal timing */
+			struct lcd_parm_t *p = 0;
+
+			if (parm[1]) {
+				p = lcd_get_parm(parm[1], parm[2]);
+				if (p)
+					lcd_set_lvds_id(parm[1]);
+			}
+
+			if (p == 0)
+				p = lcd_get_oem_parm(parm[3], parm[4]);
+			vmode = &p->vmode;
+		}
+		vout->option[2] = vmode->vmode;
+		info->resx = vmode->xres;
+		info->resy = vmode->yres;
+		info->fps  = vmode->refresh;
+		vout_info_set_fixed_timing(fb_no, vmode);
+		lcd_set_type(1);
+		}
+	case VOUT_LCD:
+		{
+		struct vout_dev_t *dev;
+
+		lcd_set_parm(parm[1], parm[2] & 0xFF);
+		dev = lcd_get_dev();
+		vout->dev = dev;
+		dev->vout = vout;
+		vout->option[0] = VDO_COL_FMT_ARGB;
+		vout->option[1] &= ~0xFF;
+		vout->option[1] |= VPP_DATAWIDHT_24;
+		vout->dev->init(vout);
+		vout_info_set_fixed_timing(fb_no, &p_lcd->vmode);
+		}
+		break;
+	case VOUT_DVI:
+		{
+		struct vout_dev_t *dev = 0;
+
+		g_vpp.dvi_int_disable =
+			(parm[2] & WMT_DISP_FB_DISBALE_DVI_INT) ? 1 : 0;
+		g_vpp.dvi_int_no = (parm[2] & WMT_DISP_FB_DVI_INT) ?
+			((parm[1] & 0xF000) >> 12) : VPP_DVI_INT_DEFAULT;
+		g_vpp.dvi_i2c_no = (parm[2] & WMT_DISP_FB_DVI_I2C) ?
+			((parm[1] & 0xF00) >> 8) : VPP_DVI_I2C_DEFAULT;
+		g_vpp.dvi_i2c_no &= VPP_DVI_I2C_ID_MASK;
+
+		if (parm[2] & WMT_DISP_FB_DISABLE_EXTDEV)
+			vout->dev = 0;
+		else {
+			vpp_i2c_init(VPP_DVI_I2C_ID, 0xA0);
+			do {
+				dev = vout_get_device(dev);
+				if (dev == 0)
+					break;
+				if (vout->fix_cap & BIT(dev->mode)) {
+					vout->inf =
+						vout_inf_get_entry(dev->mode);
+					if (dev->init(vout) == 0) {
+						vout->dev = dev;
+						dev->vout = vout;
+						break;
+					}
+				}
+			} while (1);
+		}
+
+		DBG_MSG("DVI ext dev : %s\n",
+			(vout->dev) ? vout->dev->name : "NO");
+		}
+		info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ?
+			VPP_OPT_INTERLACE : 0;
+		break;
+	case VOUT_HDMI:
+		info->option = (parm[2] & WMT_DISP_FB_INTERLACE) ?
+			VPP_OPT_INTERLACE : 0;
+#if 0 /* use old uboot param and wait next chip */
+		g_vpp.hdmi_disable =
+			(parm[2] & WMT_DISP_FB_HDMI_DISABLE) ? 1 : 0;
+
+		g_vpp.hdmi_sp_mode =
+			(parm[2] & WMT_DISP_FB_HDMI_SP_MODE) ? 1 : 0;
+#endif
+		break;
+	default:
+		break;
+	}
+
+	if (ret == 0)
+		vout_info_add_entry(fb_no, vout);
+	return ret;
+}
+
+int vout_check_display(void)
+{
+	#define BUF_LEN 100
+	char buf[BUF_LEN];
+	int varlen = BUF_LEN;
+	unsigned int parm[32];
+	int i, idx;
+
+	if (wmt_getsyspara("wmt.display.fb0", buf, &varlen)) {
+		/* default for no uboot parameter */
+		parm[0] = VOUT_HDMI;
+		parm[1] = VDO_COL_FMT_ARGB;
+		parm[2] = VPP_DATAWIDHT_24;
+		parm[3] = 1280;
+		parm[4] = 720;
+		parm[5] = 60;
+		vout_add_display(0, &parm[0]);
+		parm[0] = VOUT_DVI;
+		parm[1] = VDO_COL_FMT_ARGB;
+		parm[2] = VPP_DATAWIDHT_24;
+		parm[3] = 1024;
+		parm[4] = 768;
+		parm[5] = 60;
+		vout_add_display(0, &parm[0]);
+		return 1;
+	} else {
+		int fb_no = 0;
+		int num;
+
+		while (fb_no < VPP_VOUT_INFO_NUM) {
+			sprintf(buf, "wmt.display.fb%d", fb_no);
+			varlen = BUF_LEN;
+			if (wmt_getsyspara(buf, buf, &varlen))
+				break;
+
+			DBG_DETAIL("fb%d : %s\n", fb_no, buf);
+			varlen = vpp_parse_param(buf,
+				(unsigned int *)parm, 32, 0x1C1C1C1D);
+			DBG_DETAIL("op 0x%x\n", parm[0]);
+			num = (varlen - 1) / 7;
+			for (i = 0; i < num; i++) {
+				idx = 1 + 8 * i; /* [ + 6 + ] = 8 */
+				DBG_DETAIL("%d : %x, %x, %x (%dx%d@%d)\n", i,
+					parm[idx + 1], parm[idx + 2],
+					parm[idx + 3], parm[idx + 4],
+					parm[idx + 5], parm[idx + 6]);
+				vout_add_display(fb_no, &parm[idx + 1]);
+			}
+
+			vout_info[fb_no]->multi =
+				(parm[0] & WMT_DISP_FB_MULTI) ? 1 : 0;
+			vout_info[fb_no]->alloc_mode = (parm[0] & 0xF);
+			vout_info[fb_no]->hwc_mode = (parm[0] & 0xF0) >> 4;
+			if (parm[0] & WMT_DISP_FB_COLFMT)
+				vout_info[fb_no]->fb.col_fmt = ((parm[0] &
+					WMT_DISP_FB_COLFMT_MASK) >> 16);
+			fb_no++;
+		}
+	}
+
+	/* [uboot parameter] oem timing :
+		pixclk:option:hsync:hbp:hpixel:hfp:vsync:vbp:vpixel:vfp */
+	varlen = BUF_LEN;
+	if (wmt_getsyspara("wmt.display.tmr", buf, &varlen) == 0) {
+		struct fb_videomode *p;
+		int xres, yres;
+		struct fb_videomode vo_oem_vmode;
+
+		p = &vo_oem_vmode;
+		DBG_MSG("tmr %s\n", buf);
+		vpp_parse_param(buf, parm, 12, 0);
+		p->pixclock = parm[0];
+		p->vmode = parm[1];
+		p->hsync_len = parm[2];
+		p->left_margin = parm[3];
+		p->xres = parm[4];
+		p->right_margin = parm[5];
+		p->vsync_len = parm[6];
+		p->upper_margin = parm[7];
+		p->yres = parm[8];
+		p->lower_margin = parm[9];
+		p->pixclock *= 1000;
+		xres = p->hsync_len + p->left_margin + p->xres +
+			p->right_margin;
+		yres = p->vsync_len + p->upper_margin + p->yres +
+			p->lower_margin;
+		p->refresh = vpp_calc_refresh(p->pixclock, xres, yres);
+		if (p->refresh == 59)
+			p->refresh = 60;
+		p->vmode = (parm[1] & VPP_OPT_INTERLACE) ? FB_VMODE_INTERLACED : 0;
+		p->sync = (parm[1] & VPP_DVO_SYNC_POLAR_HI) ? FB_SYNC_HOR_HIGH_ACT : 0;
+		p->sync |= (parm[1] & VPP_DVO_VSYNC_POLAR_HI) ? FB_SYNC_VERT_HIGH_ACT : 0;
+		DBG_MSG("tmr pixclk %d,option 0x%x\n",
+			p->pixclock, p->vmode);
+		DBG_MSG("H sync %d,bp %d,pixel %d,fp %d\n", p->hsync_len,
+			p->left_margin,	p->xres, p->right_margin);
+		DBG_MSG("V sync %d,bp %d,pixel %d,fp %d\n", p->vsync_len,
+			p->upper_margin, p->yres, p->lower_margin);
+		p->pixclock = KHZ2PICOS(p->pixclock / 1000);
+		vout_info_set_fixed_timing(0, &vo_oem_vmode);
+		vout_info[0]->fixed_width = parm[10];
+		vout_info[0]->fixed_height = parm[11];
+		vout_info[0]->resx = p->xres;
+		vout_info[0]->resy = p->yres;
+		vout_info[0]->fps = p->refresh;
+		vout_info[0]->vout[0]->resx = p->xres;
+		vout_info[0]->vout[0]->resy = p->yres;
+		vout_info[0]->vout[0]->fps = p->refresh;
+	}
+	return 0;
+}
+
+int vout_init(void)
+{
+	struct vout_info_t *info;
+	struct vout_t *vout;
+	int i, j;
+
+	DBG_DETAIL("Enter\n");
+
+	for(i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+		if(vout_info[i] != NULL) {
+			kfree(vout_info[i]);
+			vout_info[i] = NULL;
+		}
+	}
+
+	/* register vout & set default */
+	vout_register(0, &vout_entry_0);
+	vout_entry_0.inf = vout_inf_get_entry(VOUT_INF_HDMI);
+	vout_entry_0.govr = p_govrh;
+	vout_register(1, &vout_entry_1);
+	vout_entry_1.inf = vout_inf_get_entry(VOUT_INF_DVI);
+	vout_entry_1.govr = p_govrh2;
+
+	/* check vout info */
+	DBG_DETAIL("check display\n");
+	vout_check_display();
+
+	/* initial vout */
+	DBG_DETAIL("init display\n");
+	for (i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+		info = vout_info[i];
+		if (!info)
+			break;
+		for (j = 0; ; j++) {
+			vout = info->vout[j];
+			if (vout == 0)
+				break;
+			if (vout->inf)
+				vout->inf->init(vout, 0);
+		}
+	}
+
+	/* check monitor resolution */
+	DBG_DETAIL("check resolution\n");
+	for (i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+		struct vout_t *vout_first = 0;
+		struct vout_t *vout_plug = 0;
+
+		info = vout_info[i];
+		if (!info)
+			break;
+		for (j = 0; ; j++) {
+			vout = info->vout[j];
+			if (vout == 0)
+				break;
+
+			if (vout_first == 0) /* first priority */
+				vout_first = vout;
+
+			if (vout_chkplug(vout->num)) {
+				struct fb_videomode vmode;
+
+				vmode.xres = vout->resx;
+				vmode.yres = vout->resy;
+				vmode.refresh = vout->fps;
+				vmode.vmode = 0;
+				vout_find_match_mode(i, &vmode, 1);
+				vout->resx = vmode.xres;
+				vout->resy = vmode.yres;
+				vout->fps = vmode.refresh;
+				if (vout_plug == 0) /* first plugin */
+					vout_plug = vout;
+			}
+
+			if (info->multi)
+				vout_change_status(vout,
+					VPP_VOUT_STS_ACTIVE, 1);
+		}
+
+		vout = (vout_plug) ? vout_plug : vout_first;
+		if (vout) {
+			vout_change_status(vout, VPP_VOUT_STS_ACTIVE, 1);
+			info->resx = vout->resx;
+			info->resy = vout->resy;
+			info->fps = vout->fps;
+		}
+	}
+
+#ifdef DEBUG
+	/* show display info */
+	for (i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+		info = vout_info[i];
+		if (!info)
+			break;
+		MSG("-----------------------------------------------------\n");
+		MSG("fb%d, resx %d,resy %d,fps %d\n", i,
+			info->resx, info->resy, info->fps);
+		MSG("resx_vir %d,resy_vir %d,pixclk %d\n", info->resx_virtual,
+			info->resy_virtual, info->pixclk);
+		MSG("multi %d,alloc %d,option 0x%x\n", info->multi,
+			info->alloc_mode, info->option);
+
+		for (j = 0; ; j++) {
+			vout = info->vout[j];
+			if (vout == 0)
+				break;
+			vout_print_entry(vout);
+		}
+	}
+	MSG("-----------------------------------------------------\n");
+#endif
+	DBG_DETAIL("Leave\n");
+	return 0;
+}
+
+int vout_exit(void)
+{
+	return 0;
+}
diff --git a/drivers/video/wmt/vout.c b/drivers/video/wmt/vout.c
new file mode 100755
index 00000000..9291ac55
--- /dev/null
+++ b/drivers/video/wmt/vout.c
@@ -0,0 +1,941 @@
+/*++
+ * linux/drivers/video/wmt/vout.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VOUT_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "vout.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+/* #define  VO_XXXX  xxxx    *//*Example*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define VO_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx vo_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in vout.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  vo_xxx;        *//*Example*/
+struct vout_t *vout_array[VPP_VOUT_NUM];
+struct vout_inf_t *vout_inf_array[VOUT_INF_MODE_MAX];
+struct vout_dev_t *vout_dev_list;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void vo_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+/*----------------------- vout API --------------------------------------*/
+void vout_register(int no, struct vout_t *vo)
+{
+	if (no >= VPP_VOUT_NUM)
+		return;
+
+	vo->num = no;
+	vo->govr = (void *) p_govrh;
+	vo->status = VPP_VOUT_STS_REGISTER;
+	vo->info = 0;
+	vout_array[no] = vo;
+}
+
+struct vout_t *vout_get_entry(int no)
+{
+	if (no >= VPP_VOUT_NUM)
+		return 0;
+	return vout_array[no];
+}
+EXPORT_SYMBOL(vout_get_entry);
+
+struct vout_info_t *vout_get_info_entry(int no)
+{
+	struct vout_info_t *info;
+	struct vout_t *vout;
+	int i, j;
+
+	if (no >= VPP_VOUT_NUM)
+		return 0;
+
+	for (i = 0; i < VPP_VOUT_INFO_NUM; i++) {
+		info = vout_info[i];
+		if (!info)
+			break;
+		for (j = 0; j < VPP_VOUT_NUM; j++) {
+			vout = info->vout[j];
+			if (vout == 0)
+				break;
+			if (vout->num == no)
+				return info;
+		}
+	}
+	return 0;
+}
+
+void vout_change_status(struct vout_t *vo, int mask, int sts)
+{
+	DBG_DETAIL("(0x%x,%d)\n", mask, sts);
+	if (sts)
+		vo->status |= mask;
+	else
+		vo->status &= ~mask;
+
+	switch (mask) {
+	case VPP_VOUT_STS_PLUGIN:
+		if (sts == 0) {
+			vo->status &= ~(VPP_VOUT_STS_EDID +
+				VPP_VOUT_STS_CONTENT_PROTECT);
+			vo->edid_info.option = 0;
+#ifdef __KERNEL__
+			vpp_netlink_notify_cp(0);
+#endif
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+int vout_query_inf_support(int no, enum vout_inf_mode_t mode)
+{
+	struct vout_t *vo;
+
+	if (no >= VPP_VOUT_NUM)
+		return 0;
+
+	if (mode >= VOUT_INF_MODE_MAX)
+		return 0;
+
+	vo = vout_get_entry(no);
+	return (vo->fix_cap & BIT(mode)) ? 1 : 0;
+}
+
+/*----------------------- vout interface API --------------------------------*/
+int vout_inf_register(enum vout_inf_mode_t mode, struct vout_inf_t *inf)
+{
+	if (mode >= VOUT_INF_MODE_MAX) {
+		DBG_ERR("vout interface mode invalid %d\n", mode);
+		return -1;
+	}
+
+	if (vout_inf_array[mode])
+		DBG_ERR("vout interface register again %d\n", mode);
+
+	vout_inf_array[mode] = inf;
+	return 0;
+} /* End of vout_register */
+
+struct vout_inf_t *vout_inf_get_entry(enum vout_inf_mode_t mode)
+{
+	if (mode >= VOUT_INF_MODE_MAX) {
+		DBG_ERR("vout interface mode invalid %d\n", mode);
+		return 0;
+	}
+	return vout_inf_array[mode];
+}
+
+/*----------------------- vout device API -----------------------------------*/
+int vout_device_register(struct vout_dev_t *ops)
+{
+	struct vout_dev_t *list;
+
+	if (vout_dev_list == 0) {
+		vout_dev_list = ops;
+		list = ops;
+	} else {
+		list = vout_dev_list;
+		while (list->next != 0)
+			list = list->next;
+		list->next = ops;
+	}
+	ops->next = 0;
+	return 0;
+}
+
+struct vout_dev_t *vout_get_device(struct vout_dev_t *ops)
+{
+	if (ops == 0)
+		return vout_dev_list;
+	return ops->next;
+}
+
+struct vout_t *vout_get_entry_adapter(enum vout_mode_t mode)
+{
+	int no;
+
+	switch (mode) {
+	case VOUT_SD_DIGITAL:
+	case VOUT_DVI:
+	case VOUT_LCD:
+	case VOUT_DVO2HDMI:
+	case VOUT_SD_ANALOG:
+	case VOUT_VGA:
+		no = VPP_VOUT_NUM_DVI;
+		break;
+	case VOUT_HDMI:
+		no = VPP_VOUT_NUM_HDMI;
+		break;
+	case VOUT_LVDS:
+		no = VPP_VOUT_NUM_LVDS;
+		break;
+	default:
+		no = VPP_VOUT_NUM;
+		break;
+	}
+	return vout_get_entry(no);
+}
+
+struct vout_inf_t *vout_get_inf_entry_adapter(enum vout_mode_t mode)
+{
+	int no;
+
+	switch (mode) {
+	case VOUT_SD_DIGITAL:
+	case VOUT_SD_ANALOG:
+	case VOUT_DVI:
+	case VOUT_LCD:
+	case VOUT_DVO2HDMI:
+	case VOUT_VGA:
+		no = VOUT_INF_DVI;
+		break;
+	case VOUT_HDMI:
+		no = VOUT_INF_HDMI;
+		break;
+	case VOUT_LVDS:
+		no = VOUT_INF_LVDS;
+		break;
+	default:
+		no = VOUT_INF_MODE_MAX;
+		return 0;
+	}
+	return vout_inf_get_entry(no);
+}
+
+enum vpp_vout_s vout_get_mode_adapter(struct vout_t *vout)
+{
+	enum vpp_vout_s mode;
+
+	switch (vout->inf->mode) {
+	case VOUT_INF_DVI:
+		mode = VPP_VOUT_DVI;
+		if (vout->dev && (strcmp("LCD", vout->dev->name) == 0))
+			mode = VPP_VOUT_LCD;
+		break;
+	case VOUT_INF_HDMI:
+		mode = VPP_VOUT_HDMI;
+		break;
+	case VOUT_INF_LVDS:
+		mode = VPP_VOUT_LVDS;
+		break;
+	default:
+		mode = VPP_VOUT_NONE;
+		break;
+	}
+	return mode;
+}
+
+int vout_info_add_entry(int no, struct vout_t *vo)
+{
+	struct vout_info_t *info;
+	int i = 0;
+
+	if ((vo == 0) || (vo->info))
+		return 0;
+
+	info = vout_info[no];
+	info->num = no;
+	if (vo->num < VPP_VOUT_NUM) { /* not virtual vout */
+		for (i = 0; i < VPP_VOUT_NUM; i++) {
+			if (info->vout[i] == 0) {
+				info->vout[i] = vo;
+				vo->info = info;
+				break;
+			} else {
+				if (info->vout[i] == vo) /* exist */
+					break;
+			}
+		}
+	}
+
+	if (i == 0) { /* new */
+		info->resx = vo->resx;
+		info->resy = vo->resy;
+		info->resx_virtual = vpp_calc_align(info->resx, 4);
+		info->resy_virtual = info->resy;
+		info->fps = (int) vo->fps;
+		DBG_MSG("new %dx%d@%d\n", info->resx, info->resy, info->fps);
+	}
+
+	DBG_MSG("info %d,%dx%d@%d\n", no, info->resx, info->resy, info->fps);
+	return no;
+}
+
+struct vout_info_t *vout_info_get_entry(int no)
+{
+	if (no >= VPP_VOUT_INFO_NUM)
+		return 0;
+	return vout_info[no];
+}
+
+void vout_info_set_fixed_timing(int no, struct fb_videomode *vmode)
+{
+	struct vout_info_t *info;
+
+	DBG_MSG("(%d)\n", no);
+
+	info = vout_info_get_entry(no);
+	if (!info->fixed_vmode) {
+		info->fixed_vmode =
+			kmalloc(sizeof(struct fb_videomode), GFP_KERNEL);
+		if (!info->fixed_vmode)
+			return;
+	}
+	memcpy(info->fixed_vmode, vmode, sizeof(struct fb_videomode));
+}
+
+struct govrh_mod_t *vout_info_get_govr(int no)
+{
+	struct vout_info_t *info;
+	struct govrh_mod_t *govr = 0;
+	int i;
+
+	info = vout_info[no];
+	if (!info)
+		return 0;
+
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		if (info->vout[i]) {
+			if (govr == 0)
+				govr = info->vout[i]->govr;
+			if (info->vout[i]->status & VPP_VOUT_STS_ACTIVE) {
+				govr = info->vout[i]->govr;
+				break;
+			}
+		}
+	}
+	return govr;
+}
+
+int vout_check_ratio_16_9(unsigned int resx, unsigned int resy)
+{
+	int val;
+
+	val = (resy) ? ((resx * 10) / resy) : 0;
+	return (val >= 15) ? 1 : 0;
+}
+
+struct fb_videomode *vout_get_video_mode(int vout_num,
+	struct fb_videomode *vmode, int option)
+{
+	int i;
+	struct fb_videomode *p, *best = NULL;
+	unsigned int diff = -1, diff_refresh = -1;
+	int d;
+	int resx, resy, fps;
+	unsigned int pixel_clock, diff_pixel_clock = -1;
+	struct vout_t *vo = 0;
+	char *edid = 0;
+
+	resx = vmode->xres;
+	resy = vmode->yres;
+	fps = vmode->refresh;
+#ifdef DEBUG
+	pixel_clock = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) * 1000 : 0;
+	DBG_MSG("%d,%dx%d@%d,%d,0x%x\n", vout_num, resx, resy, fps,
+		pixel_clock, option);
+#endif
+	pixel_clock = vmode->pixclock;
+
+	/* EDID detail timing */
+	if (option & VOUT_MODE_OPTION_EDID) {
+		unsigned int opt;
+		struct fb_videomode *edid_vmode;
+
+		vo = vout_get_entry(vout_num);
+		if (vo == 0)
+			return 0;
+
+		edid = vout_get_edid(vout_num);
+		if (edid_parse(edid, &vo->edid_info)) {
+			opt = fps | ((option &
+				VOUT_MODE_OPTION_INTERLACE) ?
+				EDID_TMR_INTERLACE : 0);
+			if (edid_find_support(&vo->edid_info,
+				resx, resy, opt, &edid_vmode)) {
+				if (edid_vmode) {
+					DBG_MSG("EDID detail timing\n");
+					return edid_vmode;
+				}
+			}
+		}
+	}
+
+	/* video mode table */
+	for (i = 0; ; i++) {
+		p = (struct fb_videomode *) &vpp_videomode[i];
+		if (p->pixclock == 0)
+			break;
+
+		if (option & VOUT_MODE_OPTION_LESS) {
+			if ((p->xres > resx) || (p->yres > resy))
+				continue;
+		}
+		if (option & VOUT_MODE_OPTION_GREATER) {
+			if ((p->xres < resx) || (p->yres < resy))
+				continue;
+		}
+		if (option & VOUT_MODE_OPTION_INTERLACE) {
+			if (!(p->vmode & FB_VMODE_INTERLACED))
+				continue;
+		}
+		if (option & VOUT_MODE_OPTION_PROGRESS) {
+			if ((p->vmode & FB_VMODE_INTERLACED))
+				continue;
+		}
+		if ((option & VOUT_MODE_OPTION_EDID) &&
+			(edid_parse(edid, &vo->edid_info))) {
+			unsigned int opt;
+			struct fb_videomode *edid_vmode;
+
+			opt = p->refresh | ((option &
+				VOUT_MODE_OPTION_INTERLACE) ?
+				EDID_TMR_INTERLACE : 0);
+			if (edid_find_support(&vo->edid_info,
+				p->xres, p->yres, opt, &edid_vmode)) {
+				if (edid_vmode)
+					p = edid_vmode;
+			} else {
+				continue;
+			}
+		}
+		d = abs(p->xres - resx) + abs(p->yres - resy);
+		d = abs(d);
+		if (diff > d) {
+			diff = d;
+			diff_refresh = abs(p->refresh - fps);
+			diff_pixel_clock = abs(p->pixclock - pixel_clock);
+			best = p;
+		} else if (diff == d) {
+			d = abs(p->refresh - fps);
+			if (diff_refresh > d) {
+				diff_refresh = d;
+				diff_pixel_clock =
+					abs(p->pixclock - pixel_clock);
+				best = p;
+			} else if (diff_refresh == d) {
+				d = abs(p->pixclock - pixel_clock);
+				if (diff_pixel_clock > d) {
+					diff_pixel_clock = d;
+					best = p;
+				}
+			}
+		}
+	}
+	if (best)
+		DBG_MSG("%dx%d@%d\n", best->xres, best->yres, best->refresh);
+	return best;
+}
+
+int vout_get_width_height(int fbnum, int *width, int *height)
+{
+	struct vout_info_t *info;
+	int i;
+
+	info = vout_info_get_entry(fbnum);
+	*width = 0;
+	*height = 0;
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		struct vout_t *vout;
+
+		vout = info->vout[i];
+		if (vout) {
+			if ((vout->inf->mode == VOUT_INF_DVI) && p_lcd) {
+				if (info->fixed_width != 0 && info->fixed_height != 0) {
+					*width = info->fixed_width;
+					*height = info->fixed_height;
+				} else {
+					*width = p_lcd->width;
+					*height = p_lcd->height;
+				}
+				break;
+			}
+			if (vout_chkplug(vout->num)) {
+				if (vout_get_edid_option(vout->num)
+					& EDID_OPT_VALID) {
+					*width = vout->edid_info.width;
+					*height = vout->edid_info.height;
+					break;
+				}
+			}
+		}
+	}
+	return 0;
+}
+
+#ifndef CONFIG_VPOST
+int vout_find_match_mode(int fbnum,
+				struct fb_videomode *vmode, int match)
+{
+	struct vout_info_t *info;
+	struct fb_videomode *p;
+	int no = VPP_VOUT_NUM;
+	unsigned int option;
+	int i;
+
+	DBG_DETAIL("(%d)\n", fbnum);
+
+	info = vout_info_get_entry(fbnum);
+	if (vmode->refresh == 59)
+		vmode->refresh = 60;
+
+	/* fixed timing */
+	if (info->fixed_vmode) {
+		if (info->fixed_vmode->xres != vmode->xres)
+			return -1;
+		if (info->fixed_vmode->yres != vmode->yres)
+			return -1;
+		if (info->fixed_vmode->refresh != vmode->refresh)
+			return -1;
+		p = info->fixed_vmode;
+		goto label_find_match;
+	}
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		if (info->vout[i]) {
+			int vout_no = info->vout[i]->num;
+
+			if (no == VPP_VOUT_NUM)
+				no = vout_no; /* get first vo */
+			if (vout_chkplug(vout_no)) {
+				no = vout_no;
+				break;
+			}
+		}
+	}
+	/* resolution match and interlace match */
+	option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS;
+	option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID;
+	option |= (vmode->vmode & FB_VMODE_INTERLACED) ?
+		VOUT_MODE_OPTION_INTERLACE : VOUT_MODE_OPTION_PROGRESS;
+	p = vout_get_video_mode(no, vmode, option);
+	if (p)
+		goto label_find_match;
+
+	/* resolution match but interlace not match */
+	option = VOUT_MODE_OPTION_GREATER + VOUT_MODE_OPTION_LESS;
+	option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID;
+	option |= (vmode->vmode & FB_VMODE_INTERLACED) ?
+		VOUT_MODE_OPTION_PROGRESS : VOUT_MODE_OPTION_INTERLACE;
+	p = vout_get_video_mode(no, vmode, option);
+	if (p)
+		goto label_find_match;
+
+/*	if( !match ){ */
+		/* resolution less best mode */
+		option = VOUT_MODE_OPTION_LESS;
+		option |= (no == VPP_VOUT_NUM) ? 0 : VOUT_MODE_OPTION_EDID;
+		p = vout_get_video_mode(no, vmode, option);
+		if (p)
+			goto label_find_match;
+/*	} */
+	DBG_ERR("no support mode\n");
+	return -1;
+label_find_match:
+	*vmode = *p;
+#ifdef CONFIG_UBOOT
+	info->p_vmode = p;
+#endif
+	return 0;
+}
+#endif
+
+int vout_find_edid_support_mode(
+	struct edid_info_t *info,
+	unsigned int *resx,
+	unsigned int *resy,
+	unsigned int *fps,
+	int r_16_9
+)
+{
+	/* check the EDID to find one that not large and same ratio mode*/
+#ifdef CONFIG_WMT_EDID
+	int i, cnt;
+	struct fb_videomode *p;
+	unsigned int w, h, f, option;
+
+	if ((*resx == 720) && (*resy == 480) && (*fps == 50))
+		*fps = 60;
+
+	for (i = 0, cnt = 0; ; i++) {
+		if (vpp_videomode[i].pixclock == 0)
+			break;
+		cnt++;
+	}
+
+	for (i = cnt - 1; i >= 0; i--) {
+		p = (struct fb_videomode *) &vpp_videomode[i];
+		h = p->yres;
+		if (h > *resy)
+			continue;
+
+		w = p->xres;
+		if (w > *resx)
+			continue;
+
+		f = p->refresh;
+		if (f > *fps)
+			continue;
+
+		if (r_16_9 != vout_check_ratio_16_9(w, h))
+			continue;
+
+		option = f & EDID_TMR_FREQ;
+		option |= (p->vmode & FB_VMODE_INTERLACED) ?
+			EDID_TMR_INTERLACE : 0;
+
+		if (edid_find_support(info, w, h, option, &p)) {
+			*resx = w;
+			*resy = h;
+			*fps = f;
+			DBG_MSG("(%dx%d@%d)\n", w, h, f);
+			return 1;
+		}
+	}
+#endif
+	return 0;
+}
+
+/*----------------------- vout control API ----------------------------------*/
+void vout_set_framebuffer(struct vout_info_t *info, vdo_framebuf_t *fb)
+{
+	int i;
+	struct vout_t *vo;
+
+	if (!info)
+		return;
+
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		vo = info->vout[i];
+		if (vo == 0)
+			break;
+		if (vo->govr)
+			vo->govr->fb_p->set_framebuf(fb);
+	}
+}
+
+int vout_set_blank(int no, enum vout_blank_t arg)
+{
+	struct vout_t *vo;
+
+	DBG_DETAIL("(%d,%d)\n", no, arg);
+
+	vo = vout_get_entry(no);
+	if (vo && (vo->inf)) {
+		vout_change_status(vo, VPP_VOUT_STS_BLANK, arg);
+		vo->inf->blank(vo, arg);
+		if (vo->dev && vo->dev->set_power_down)
+			vo->dev->set_power_down(
+				(arg == VOUT_BLANK_POWERDOWN) ? 1 : 0);
+		if (vo->govr)
+			govrh_set_MIF_enable(vo->govr, (arg) ? 0 : 1);
+	}
+	return 0;
+}
+
+int vout_set_mode(int no, enum vout_inf_mode_t mode)
+{
+	struct vout_t *vo;
+
+	DBG_DETAIL("(%d,%d)\n", no, mode);
+
+	if (vout_query_inf_support(no, mode) == 0) {
+		DBG_ERR("not support this interface(%d,%d)\n", no, mode);
+		return -1;
+	}
+
+	vo = vout_get_entry(no);
+	if (vo->inf) {
+		if (vo->inf->mode == mode)
+			return 0;
+		vo->inf->uninit(vo, 0);
+		vout_change_status(vo, VPP_VOUT_STS_ACTIVE, 0);
+		if (vo->dev)
+			vo->dev->set_power_down(1);
+	}
+
+	vo->inf = vout_inf_get_entry(mode);
+	vo->inf->init(vo, 0);
+	vout_change_status(vo, VPP_VOUT_STS_ACTIVE, 1);
+	return 0;
+}
+
+int vout_config(struct vout_info_t *info, struct fb_videomode *vmode,
+	vdo_framebuf_t *fb)
+{
+	struct vout_t *vo;
+	int i;
+
+	DBG_DETAIL("\n");
+
+	if (!vmode && !fb)
+		return 0;
+
+	if (vmode) {
+		/* option for interface & device config */
+		info->resx = vmode->xres;
+		info->resy = vmode->yres;
+		info->fps = (vmode->refresh == 59) ? 60 : vmode->refresh;
+		info->option = (vmode->vmode & FB_VMODE_INTERLACED) ?
+						VPP_OPT_INTERLACE : 0;
+		info->option |= (vmode->sync & FB_SYNC_HOR_HIGH_ACT) ?
+						VPP_DVO_SYNC_POLAR_HI : 0;
+		info->option |= (vmode->sync & FB_SYNC_VERT_HIGH_ACT) ?
+						VPP_DVO_VSYNC_POLAR_HI : 0;
+	}
+
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		vo = info->vout[i];
+		if (vo == 0)
+			break;
+
+		if (vo->govr == 0)
+			continue;
+
+		if (vmode) {
+			govrh_set_videomode(vo->govr, vmode);
+
+			if (vo->inf) {
+				vo->inf->config(vo, (int)info);
+				if (vo->dev)
+					vo->dev->config(info);
+			}
+		}
+
+		if (fb)
+			govrh_set_framebuffer(vo->govr, fb);
+	}
+	return 0;
+}
+
+int vout_chkplug(int no)
+{
+	struct vout_t *vo;
+	struct vout_inf_t *inf;
+	int ret = 0;
+
+	DBG_DETAIL("(%d)\n", no);
+
+	vo = vout_get_entry(no);
+	if (vo == 0)
+		return 0;
+
+	if (vo->inf == 0)
+		return 0;
+
+	inf = vout_inf_get_entry(vo->inf->mode);
+	if (inf == 0)
+		return 0;
+
+	if (vo->dev && vo->dev->check_plugin)
+		ret = vo->dev->check_plugin(0);
+	else
+		ret = inf->chkplug(vo, 0);
+	vout_change_status(vo, VPP_VOUT_STS_PLUGIN, ret);
+	return ret;
+}
+
+int vout_inf_chkplug(int no, enum vout_inf_mode_t mode)
+{
+	struct vout_t *vo;
+	struct vout_inf_t *inf;
+	int plugin = 0;
+
+	DBG_MSG("(%d,%d)\n", no, mode);
+	if (vout_query_inf_support(no, mode) == 0)
+		return 0;
+
+	vo = vout_get_entry(no);
+	inf = vout_inf_get_entry(mode);
+	if (inf) {
+		if (inf->chkplug)
+			plugin = inf->chkplug(vo, 0);
+	}
+	return plugin;
+}
+
+char *vout_get_edid(int no)
+{
+	struct vout_t *vo;
+	int ret;
+
+	DBG_DETAIL("(%d)\n", no);
+
+	if (edid_disable)
+		return 0;
+	vo = vout_get_entry(no);
+	if (vo == 0)
+		return 0;
+
+	if (vo->status & VPP_VOUT_STS_EDID) {
+		DBG_MSG("edid exist\n");
+		return vo->edid;
+	}
+
+	vout_change_status(vo, VPP_VOUT_STS_EDID, 0);
+#ifdef CONFIG_VOUT_EDID_ALLOC
+	if (vo->edid == 0) {
+		vo->edid = kmalloc(128 * EDID_BLOCK_MAX, GFP_KERNEL);
+		if (!vo->edid) {
+			DBG_ERR("edid buf alloc\n");
+			return 0;
+		}
+	}
+#endif
+
+	ret = 1;
+	if (vo->dev && vo->dev->get_edid) {
+		ret = vo->dev->get_edid(vo->edid);
+	} else {
+		if (vo->inf->get_edid)
+			ret = vo->inf->get_edid(vo, (int)vo->edid);
+	}
+
+	if (ret == 0) {
+		DBG_DETAIL("edid read\n");
+		vout_change_status(vo, VPP_VOUT_STS_EDID, 1);
+		return vo->edid;
+	} else {
+		DBG_MSG("read edid fail\n");
+	}
+
+#ifdef CONFIG_VOUT_EDID_ALLOC
+	kfree(vo->edid);
+	vo->edid = 0;
+#endif
+	return 0;
+}
+
+int vout_get_edid_option(int no)
+{
+	struct vout_t *vo;
+
+	DBG_DETAIL("(%d)\n", no);
+
+	vo = vout_get_entry(no);
+	if (vo == 0)
+		return 0;
+
+	if (vo->edid_info.option)
+		return vo->edid_info.option;
+
+	if (vout_get_edid(no) == 0) {
+		if (no == VPP_VOUT_NUM_HDMI) { /* HDMI wo EDID still can work */
+			vo->edid_info.option = (EDID_OPT_HDMI + EDID_OPT_AUDIO);
+			return vo->edid_info.option;
+		}
+		return 0;
+	}
+
+	edid_parse(vo->edid, &vo->edid_info);
+	return vo->edid_info.option;
+}
+
+unsigned int vout_get_mask(struct vout_info_t *vo_info)
+{
+	unsigned int mask;
+	int i;
+
+	if (g_vpp.virtual_display) {
+		if (vo_info->num == 0)
+			return 0;
+		return VPP_VOUT_ALL;
+	}
+
+	mask = 0;
+	for (i = 0; i <= VPP_VOUT_NUM; i++) {
+		if (vo_info->vout[i] == 0)
+			break;
+		mask |= (0x1 << vo_info->vout[i]->num);
+	}
+	return mask;
+}
+
+int vout_check_plugin(int clr_sts)
+{
+	struct vout_t *vo;
+	int i;
+	int plugin = 0;
+
+	for (i = 0; i <= VPP_VOUT_NUM; i++) {
+		vo = vout_get_entry(i);
+		if (vo == 0)
+			continue;
+		if (vo->inf == 0)
+			continue;
+
+		if (vo->dev) {
+			if (!(vo->dev->capability & VOUT_DEV_CAP_FIX_PLUG)) {
+				if (vout_chkplug(i)) {
+					plugin = 1;
+					if (clr_sts)
+						vout_change_status(vo,
+							VPP_VOUT_STS_PLUGIN, 0);
+					DBG_MSG("[VPP] ext dev plugin\n");
+				}
+			}
+		} else {
+			if (!(vo->inf->capability & VOUT_INF_CAP_FIX_PLUG)) {
+				if (vout_chkplug(i)) {
+					plugin = 1;
+					if (clr_sts)
+						vout_change_status(vo,
+							VPP_VOUT_STS_PLUGIN, 0);
+					DBG_MSG("[VPP] inf dev plugin\n");
+				}
+			}
+		}
+	}
+	return plugin;
+}
+
+enum vout_tvformat_t vout_get_tvformat(void)
+{
+	char buf[40] = {0};
+	int varlen = 40;
+	enum vout_tvformat_t s_tvformat = TV_MAX;
+
+	if (wmt_getsyspara("wmt.display.tvformat", buf, &varlen) == 0) {
+		if (!strnicmp(buf, "PAL", 3))
+			s_tvformat = TV_PAL;
+		else if (!strnicmp(buf, "NTSC", 4))
+			s_tvformat = TV_NTSC;
+		else
+			s_tvformat = TV_UNDEFINED;
+	} else
+		s_tvformat = TV_UNDEFINED;
+
+	return s_tvformat;
+}
+
+/*--------------------End of Function Body -----------------------------------*/
+#undef VOUT_C
diff --git a/drivers/video/wmt/vout.h b/drivers/video/wmt/vout.h
new file mode 100755
index 00000000..d6dbcb66
--- /dev/null
+++ b/drivers/video/wmt/vout.h
@@ -0,0 +1,391 @@
+/*++
+ * linux/drivers/video/wmt/vout.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef VOUT_H
+/* To assert that only one occurrence is included */
+#define VOUT_H
+/*-------------------- MODULE DEPENDENCY -------------------------------------*/
+#include "vpp.h"
+#include "sw_i2c.h"
+#include "edid.h"
+
+/*	following is the C++ header	*/
+#ifdef	__cplusplus
+extern	"C" {
+#endif
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+/* #define  VO_XXXX  1    *//*Example*/
+/* #define CONFIG_VOUT_EDID_ALLOC */
+#define CONFIG_VOUT_REFACTORY
+
+#define VOUT_INFO_DEFAULT_RESX	1024
+#define VOUT_INFO_DEFAULT_RESY	768
+#define VOUT_INFO_DEFAULT_FPS	60
+
+/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/
+/* typedef  void  vo_xxx_t;  *//*Example*/
+
+enum vout_mode_t {
+	VOUT_SD_ANALOG,
+	VOUT_SD_DIGITAL,
+	VOUT_LCD,
+	VOUT_DVI,
+	VOUT_HDMI,
+	VOUT_DVO2HDMI,
+	VOUT_LVDS,
+	VOUT_VGA,
+	VOUT_BOOT,
+	VOUT_MODE_MAX,
+	VOUT_MODE_ALL = VOUT_MODE_MAX
+};
+
+enum vout_dev_mode_t {
+	VOUT_DEV_VGA,
+	VOUT_DEV_DVI,
+	VOUT_DEV_LCD,
+	VOUT_DEV_HDMI,
+	VOUT_DEV_SDD,
+	VOUT_DEV_LVDS,
+	VOUT_DEV_MODE_MAX
+};
+
+enum vout_inf_mode_t {
+	VOUT_INF_DVI,
+	VOUT_INF_HDMI,
+	VOUT_INF_LVDS,
+	VOUT_INF_MODE_MAX
+};
+
+enum vout_tvformat_t {
+	TV_PAL,
+	TV_NTSC,
+	TV_UNDEFINED,
+	TV_MAX
+};
+
+/* wmt.display.fb0 - op:[type:op1:op2:resx:resy:fps]:[...]:[...]
+<op>:[<type>:<op1>:<op2>:<resx>:<resy>:<fps>]:[...]...
+[H] <op>:=
+<op>.Bit[3:0] : fb type (0-GE,1-alloc & fix,2-dynamic alloc,3-GE overscan)
+<op>.Bit[7:4] : hwc type (0-normal,1-scale,2-overscan,3-virtual)
+<op>.Bit[8] : multi display
+<op>.Bit[9] : color format valid flag
+<op>.Bit[23:16] : color format
+
+[H] <type>:=
+1: SDA
+[H]<op1>:= mode (0-YCbCr,1-VGA,2-YPbPr,4-SVideo,5-CVBS)
+[H]<op2>
+2: LCD
+[H]<op1>:= lcd id (0-auto or OEM,1-Chilin,2-Innolux,3-AUO,4-Eking,5-Hannstar)
+[H]<op2>:=
+<op2>.Bit[7:0] : bit per pixel
+<op2>.Bit[10:8] : rgb mode (0-888,1-555,2-666,3-565)
+<op2>.Bit[11] : msb(0-lsb,1-msb)
+<op2>.Bit[13:12] : swap (0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7])
+3: DVI
+[H]<op1> :=
+<op1>.Bit[7:0] : color format(6-ARGB)
+<op1>.Bit[11:8] : dvi i2c bus id
+<op1>.Bit[15:12] : dvi interrupt gpio no
+[H]<op2> :=
+<op2>.Bit[0] : (0-12bit,1-24bit)
+<op2>.Bit[1] : (1:interlace)
+<op2>.Bit[2] : disable external device
+<op2>.Bit[3] : disable external device interrupt
+<op2>.Bit[4] : dvi i2c bus id valid
+<op2>.Bit[5] : dvi interrupt gpio no valid
+<op2>.Bit[10:8] : rgb mode (0-888,1-555,2-666,3-565)
+<op2>.Bit[11] : (0-lsb,1-msb)
+<op2>.Bit[13:12] : swap (0-RGB [7-0], 1-RGB [0-7], 2-BGR [7-0], 3-BGR [0-7])
+4: HDMI
+[H]<op1> (1-422,3-444,6-ARGB)
+[H]<op2> :=
+<op2>.Bit[0] : (0-12bit,1-24bit)
+<op2>.Bit[1] : (1:interlace)
+<op2>.Bit[2] : (1:CEC)
+<op2>.Bit[3] : (1:disable)
+<op2>.Bit[4] : (1:sp mode)
+6:LVDS
+same as LCD
+8: virtual frame buffer
+[H]<op1> (0-disable,1-enable)
+
+[D] <resx> := horizontal resolution
+[D] <resy> := vertical resolution
+[D] <fps> := frame per second
+*/
+
+#define WMT_DISP_FB_MULTI BIT(8)
+#define WMT_DISP_FB_COLFMT BIT(9)
+#define WMT_DISP_FB_COLFMT_MASK	0xFF0000
+
+#define WMT_DISP_FB_GET_BPP(a) (a & 0xFF)
+#define WMT_DISP_FB_GET_RGB_MODE(a) ((a & 0x700) >> 8)
+#define WMT_DISP_FB_MSB	BIT(11)
+#define WMT_DISP_FB_RGB_SWAP(a) ((a & 0x3000) >> 12)
+
+#define WMT_DISP_FB_DVI_24BIT BIT(0)
+#define WMT_DISP_FB_INTERLACE BIT(1)
+#define WMT_DISP_FB_DISABLE_EXTDEV BIT(2)
+#define WMT_DISP_FB_DISBALE_DVI_INT BIT(3)
+#define WMT_DISP_FB_DVI_I2C BIT(4)
+#define WMT_DISP_FB_DVI_INT BIT(5)
+
+#define WMT_DISP_FB_HDMI_CEC BIT(2)
+#define WMT_DISP_FB_HDMI_DISABLE BIT(3)
+#define WMT_DISP_FB_HDMI_SP_MODE BIT(4)
+
+enum vout_alloc_mode_t {
+	VOUT_ALLOC_GE,
+	VOUT_ALLOC_FIX_MB,
+	VOUT_ALLOC_DYNAMIC_MB,
+	VOUT_ALLOC_GE_OVERSCAN,
+	VOUT_ALLOC_MODE_MAX
+};
+
+enum vout_hwc_mode_t {
+	VOUT_HWC_NORMAL,
+	VOUT_HWC_SCALE,
+	VOUT_HWC_OVERSCAN,
+	VOUT_HWC_VIRTUAL,
+	VOUT_HWC_MODE_MAX
+};
+
+struct vout_info_t {
+	int num;
+	struct vout_t *vout[VPP_VOUT_NUM + 1];
+	int multi; /* multi display in same time */
+
+	/* frame buffer alloc */
+	enum vout_alloc_mode_t alloc_mode;
+	enum vout_hwc_mode_t hwc_mode;
+	void *fb_info_p; /* fb info pointer */
+#ifdef CONFIG_KERNEL
+	struct semaphore sem;
+#endif
+
+	int resx;
+	int resy;
+	int resx_virtual;
+	int resy_virtual;
+	int bpp;
+	int fps;
+	unsigned int pixclk;
+	unsigned int option;
+
+	struct fb_videomode *fixed_vmode;
+	int fixed_width;
+	int fixed_height;
+	vdo_framebuf_t fb;
+#ifdef CONFIG_UBOOT
+	struct fb_videomode *p_vmode;
+#endif
+	struct vpp_dbg_timer_t pandisp_timer;
+	unsigned int mb;
+	unsigned int mb_size;
+};
+
+struct vout_audio_t {
+	int fmt; /* sample bits */
+	int sample_rate; /* sample rate */
+	int channel; /* channel count */
+};
+
+struct vout_t;
+struct vout_inf_t;
+
+#define VOUT_DEV_CAP_FIX_RES		0x1
+#define VOUT_DEV_CAP_EDID		0x2
+#define VOUT_DEV_CAP_AUDIO		0x4
+#define VOUT_DEV_CAP_FIX_PLUG		0x8
+
+struct vout_dev_t {
+	struct vout_dev_t *next;
+	char name[10];
+	enum vout_inf_mode_t mode;
+	struct vout_t *vout;
+	unsigned int capability;
+
+	int (*init)(struct vout_t *vo);
+	void (*set_power_down)(int enable);
+	int (*set_mode)(unsigned int *option);
+	int (*config)(struct vout_info_t *info);
+	int (*check_plugin)(int hotplug);
+	int (*get_edid)(char *buf);
+	int (*set_audio)(struct vout_audio_t *arg);
+	int (*interrupt)(void);
+	void (*poll)(void);
+	int (*suspend)(void);
+	int (*resume)(void);
+};
+
+enum vout_blank_t {
+	VOUT_BLANK_UNBLANK, /* screen: unblanked, hsync: on,  vsync: on */
+	VOUT_BLANK_NORMAL,  /* screen: blanked,   hsync: on,  vsync: on */
+	VOUT_BLANK_VSYNC_SUSPEND,/* screen: blanked,   hsync: on,  vsync: off */
+	VOUT_BLANK_HSYNC_SUSPEND,/* screen: blanked,   hsync: off, vsync: on */
+	VOUT_BLANK_POWERDOWN /* screen: blanked,   hsync: off, vsync: off */
+};
+
+#define VOUT_CAP_INTERFACE	0x000000FF
+#define VOUT_CAP_BUS		0x00000F00
+#define VOUT_CAP_GOVR		0x0000F000
+#define VOUT_CAP_EXT_DEV	0x00010000
+#define VOUT_CAP_FIX_PLUG	0x00020000
+#define VOUT_CAP_AUDIO		0x00040000
+#define VOUT_CAP_EDID		0x00080000
+
+struct vout_t {
+	int num;
+	unsigned int fix_cap;
+	struct vout_info_t *info;	
+	struct vout_inf_t *inf;	/* interface ops */
+	struct vout_dev_t *dev; /* device ops */
+	struct govrh_mod_t *govr;
+	int resx;
+	int resy;
+	int fps;
+	int pixclk;
+	unsigned int status;
+#ifdef CONFIG_VOUT_EDID_ALLOC
+	char *edid;
+#else
+	char edid[128*EDID_BLOCK_MAX];
+#endif
+	struct edid_info_t edid_info;
+	unsigned int option[3];
+	enum vout_blank_t pre_blank;
+	int disable;
+};
+
+#define VOUT_INF_CAP_FIX_PLUG	BIT(0)
+struct vout_inf_t {
+	enum vout_inf_mode_t mode;
+	unsigned int capability;
+
+	/* function */
+	int (*init)(struct vout_t *vo, int arg);
+	int (*uninit)(struct vout_t *vo, int arg);
+	int (*blank)(struct vout_t *vo, enum vout_blank_t arg);
+	int (*config)(struct vout_t *vo, int arg);
+	int (*chkplug)(struct vout_t *vo, int arg);
+	int (*get_edid)(struct vout_t *vo, int arg);
+/*	int (*ioctl)(struct vout_t *vo,int arg); */
+};
+
+/*-------------------- EXPORTED PRIVATE VARIABLES ---------------------------*/
+#ifdef VOUT_C /* allocate memory for variables only in vout.c */
+#define EXTERN
+
+const char *vout_inf_str[] = {"DVI", "HDMI", "LVDS", "VGA", "SDA", "SDD"};
+const char *vout_adpt_str[] = {"SD_DIGITAL", "SD_DIGITAL", "LCD", "DVI",
+	"HDMI", "DVO2HDMI", "LVDS", "VGA", "BOOT"};
+
+#else
+#define	EXTERN	extern
+
+extern const char *vout_inf_str[];
+extern const char *vout_adpt_str[];
+
+#endif /* ifdef VOUT_C */
+
+EXTERN struct vout_info_t *vout_info[VPP_VOUT_INFO_NUM];
+
+/* EXTERN int      vo_xxx; *//*Example*/
+EXTERN int (*vout_board_info)(int arg);
+
+#undef EXTERN
+
+/*--------------------- EXPORTED PRIVATE MACROS -----------------------------*/
+/* #define VO_XXX_YYY   xxxx *//*Example*/
+/*--------------------- EXPORTED PRIVATE FUNCTIONS  -------------------------*/
+/* extern void  vo_xxx(void); *//*Example*/
+
+void vout_register(int no, struct vout_t *vo);
+struct vout_t *vout_get_entry(int no);
+struct vout_info_t *vout_get_info_entry(int no);
+void vout_change_status(struct vout_t *vo, int mask, int sts);
+int vout_query_inf_support(int no, enum vout_inf_mode_t mode);
+
+int vout_inf_register(enum vout_inf_mode_t mode, struct vout_inf_t *inf);
+struct vout_inf_t *vout_inf_get_entry(enum vout_inf_mode_t mode);
+
+int vout_device_register(struct vout_dev_t *ops);
+struct vout_dev_t *vout_get_device(struct vout_dev_t *ops);
+
+struct vout_t *vout_get_entry_adapter(enum vout_mode_t mode);
+struct vout_inf_t *vout_get_inf_entry_adapter(enum vout_mode_t mode);
+int vout_info_add_entry(int no, struct vout_t *vo);
+struct vout_info_t *vout_info_get_entry(int no);
+void vout_info_set_fixed_timing(int no, struct fb_videomode *vmode);
+struct govrh_mod_t *vout_info_get_govr(int no);
+enum vpp_vout_s vout_get_mode_adapter(struct vout_t *vout);
+
+int vout_config(struct vout_info_t *info, struct fb_videomode *vmode,
+	vdo_framebuf_t *fb);
+int vout_set_mode(int no, enum vout_inf_mode_t mode);
+int vout_set_blank(int no, enum vout_blank_t blank);
+void vout_set_framebuffer(struct vout_info_t *info, vdo_framebuf_t *fb);
+int vout_chkplug(int no);
+void vout_set_int_type(int type);
+char *vout_get_edid(int no);
+int vout_get_edid_option(int no);
+int vout_check_plugin(int clr_sts);
+void vout_print_entry(struct vout_t *vo);
+
+int vout_init(void);
+int vout_exit(void);
+int vo_i2c_proc(int id, unsigned int addr, unsigned int index,
+	char *pdata, int len);
+int vout_set_audio(struct vout_audio_t *arg);
+int vout_find_edid_support_mode(struct edid_info_t *info,
+	unsigned int *resx, unsigned int *resy, unsigned int *fps, int r_16_9);
+int vout_check_ratio_16_9(unsigned int resx, unsigned int resy);
+unsigned int vout_get_mask(struct vout_info_t *vo_info);
+void vout_set_int_enable(int enable);
+int vout_get_clr_int(void);
+void vo_hdmi_set_clock(int enable);
+enum vout_tvformat_t vout_get_tvformat(void);
+#ifndef CONFIG_VPOST
+int vout_find_match_mode(int fbnum,
+		struct fb_videomode *vmode, int match);
+#endif
+#define VOUT_MODE_OPTION_LESS		BIT0
+#define VOUT_MODE_OPTION_GREATER	BIT1
+#define VOUT_MODE_OPTION_EDID		BIT2
+#define VOUT_MODE_OPTION_INTERLACE	BIT3
+#define VOUT_MODE_OPTION_PROGRESS	BIT4
+struct fb_videomode *vout_get_video_mode(int vout_num,
+			struct fb_videomode *vmode, int option);
+int vout_get_width_height(int fbnum, int *width, int *height);
+void vo_hdmi_cp_set_enable_tmr(int sec);
+struct vout_dev_t *lcd_get_dev(void);
+#ifdef	__cplusplus
+}
+#endif
+
+#endif /* ifndef VOUT_H */
+
+/*=== END vout.h ==========================================================*/
diff --git a/drivers/video/wmt/vpp-osif.c b/drivers/video/wmt/vpp-osif.c
new file mode 100755
index 00000000..52bcca10
--- /dev/null
+++ b/drivers/video/wmt/vpp-osif.c
@@ -0,0 +1,912 @@
+/*++
+ * linux/drivers/video/wmt/osif.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VPP_OSIF_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include "vpp.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define LVDS_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx lvds_xxx_t; *//*Example*/
+
+/*----------EXPORTED PRIVATE VARIABLES are defined in lvds.h  -------------*/
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  lvds_xxx;        *//*Example*/
+#ifdef __KERNEL__
+static DEFINE_SPINLOCK(vpp_irqlock);
+static unsigned long vpp_lock_flags;
+#endif
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void lvds_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+#ifdef __KERNEL__
+#include <asm/io.h>
+#include <linux/proc_fs.h>
+#else
+inline unsigned int inl(unsigned int offset)
+{
+	return *(unsigned int *)(offset);
+}
+
+inline void outl(unsigned int val, unsigned int offset)
+{
+	(*(unsigned int *)(offset)) = val;
+}
+
+inline unsigned short inw(unsigned int offset)
+{
+	return *(unsigned short *)(offset);
+}
+
+inline void outw(unsigned short val, unsigned int offset)
+{
+	(*(unsigned short *)(offset)) = val;
+}
+
+inline unsigned char inb(unsigned int offset)
+{
+	return *(unsigned char *)(offset);
+}
+
+inline void outb(unsigned char val, unsigned int offset)
+{
+	(*(unsigned char *)(offset)) = val;
+}
+#ifndef CFG_LOADER
+int get_key(void)
+{
+	int key;
+
+	key = get_num(0, 256, "Input:", 5);
+	DPRINT("\n");
+	return key;
+}
+
+void udelay(int us)
+{
+	vpp_post_delay(us);
+}
+
+void mdelay(int ms)
+{
+	udelay(ms * 1000);
+}
+#endif
+#endif
+
+void vpp_udelay(unsigned int us)
+{
+#if 1
+	udelay(us);
+#else
+	unsigned int cur;
+	unsigned int cross;
+
+	if (us == 0)
+		return;
+
+	cur = wmt_read_oscr();
+	us = cur + us * 3;
+	cross = (us < cur) ? cur : 0; /* check overflow */
+	while (1) {
+		if (cross) {
+			if (cur < cross)
+				cross = 0;
+		} else {
+			if (us < cur)
+				break;
+		}
+		cur = wmt_read_oscr();
+	}
+#endif
+}
+
+/* Internal functions */
+U32 vppif_reg32_write(U32 offset, U32 mask, U32 shift, U32 val)
+{
+	U32 new_val;
+
+#if 0
+	if (val > (mask >> shift))
+		MSG("*E* check the parameter 0x%x 0x%x 0x%x 0x%x\n",
+						offset, mask, shift, val);
+#endif
+	new_val = (inl(offset) & ~(mask)) | (((val) << (shift)) & mask);
+	outl(new_val, offset);
+	return new_val;
+}
+EXPORT_SYMBOL(vppif_reg32_write);
+
+U32 vppif_reg32_read(U32 offset, U32 mask, U32 shift)
+{
+	return (inl(offset) & mask) >> shift;
+}
+EXPORT_SYMBOL(vppif_reg32_read);
+
+U32 vppif_reg32_mask(U32 offset, U32 mask, U32 shift)
+{
+	return mask;
+}
+
+int vpp_request_irq(unsigned int irq_no, void *routine,
+				unsigned int flags, char *name, void *arg)
+{
+#if 0	/* disable irq */
+	return 0;
+#endif
+
+#ifdef __KERNEL__
+	if (request_irq(irq_no, routine, flags, name, arg)) {
+		DPRINT("[VPP] *E* request irq %s fail\n", name);
+		return -1;
+	}
+#endif
+	return 0;
+}
+
+void vpp_free_irq(unsigned int irq_no, void *arg)
+{
+#ifdef __KERNEL__
+	free_irq(irq_no, arg);
+#endif
+}
+
+#ifndef __KERNEL__
+int wmt_getsyspara(char *varname, char *varval, int *varlen)
+{
+#ifdef CONFIG_VPOST
+	struct env_para_def param;
+#endif
+	int i = 0;
+	char *p;
+
+#ifdef CONFIG_VPOST
+	p = 0;
+	if (env_read_para(varname, &param) == 0)
+		p = param.value;
+#else
+	p = getenv(varname);
+#endif
+	if (!p) {
+		/* printf("## Warning: %s not defined\n", varname); */
+		return -1;
+	}
+	while (p[i] != '\0') {
+		varval[i] = p[i];
+		i++;
+	}
+	varval[i] = '\0';
+	*varlen = i;
+/*	printf("getsyspara: %s,len %d\n", p, *varlen); */
+#ifdef CONFIG_VPOST
+	free(param.value);
+#endif
+	return 0;
+}
+#endif
+
+int vpp_parse_param(char *buf, unsigned int *param,
+					int cnt, unsigned int hex_mask)
+{
+	char *p;
+	char *endp;
+	int i = 0;
+
+	if (*buf == '\0')
+		return 0;
+
+	for (i = 0; i < cnt; i++)
+		param[i] = 0;
+
+	p = (char *)buf;
+	for (i = 0; i < cnt; i++) {
+#ifdef CONFIG_VPOST
+		param[i] = strtoul(p, &endp,
+				(hex_mask & (0x1 << i)) ? 16 : 0);
+#else
+		param[i] = simple_strtoul(p, &endp,
+				(hex_mask & (0x1 << i)) ? 16 : 0);
+#endif
+		if (*endp == '\0')
+			break;
+		p = endp + 1;
+
+		if (*p == '\0')
+			break;
+	}
+	return i + 1;
+}
+
+unsigned int vpp_lock_cnt;
+void vpp_lock_l(void)
+{
+#ifdef __KERNEL__
+#if 0
+	vpp_lock_cnt++;
+	DPRINT("vpp_lock(%d)\n", vpp_lock_cnt);
+#endif
+	spin_lock_irqsave(&vpp_irqlock, vpp_lock_flags);
+#else
+#endif
+}
+
+void vpp_unlock(void)
+{
+#ifdef __KERNEL__
+#if 0
+	vpp_lock_cnt--;
+	DPRINT("vpp_unlock(%d)\n", vpp_lock_cnt);
+#endif
+	spin_unlock_irqrestore(&vpp_irqlock, vpp_lock_flags);
+#else
+#endif
+}
+
+#ifdef __KERNEL__
+struct i2c_adapter *vpp_i2c_adapter;
+struct i2c_client *vpp_i2c_client;
+struct vpp_i2c_priv {
+	unsigned int var;
+};
+static int __devinit vpp_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct vpp_i2c_priv *vpp_i2c;
+	int ret = 0;
+
+	DBGMSG("\n");
+	if (vpp_i2c_client == 0)
+		return -ENODEV;
+
+	if (!i2c_check_functionality(vpp_i2c_client->adapter, I2C_FUNC_I2C)) {
+		DBG_ERR("need I2C_FUNC_I2C\n");
+		return -ENODEV;
+	}
+
+	vpp_i2c = kzalloc(sizeof(struct vpp_i2c_priv), GFP_KERNEL);
+	if (vpp_i2c == NULL) {
+		DBG_ERR("kzalloc fail\n");
+		return -ENOMEM;
+	}
+	i2c_set_clientdata(i2c, vpp_i2c);
+	return ret;
+}
+
+static int  vpp_i2c_remove(struct i2c_client *client)
+{
+	kfree(i2c_get_clientdata(client));
+	return 0;
+}
+
+static const struct i2c_device_id vpp_i2c_id[] = {
+	{ "vpp_i2c", 0},
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, vpp_i2c_id);
+
+static struct i2c_driver vpp_i2c_driver = {
+	.probe = vpp_i2c_probe,
+	.remove = vpp_i2c_remove,
+	.id_table = vpp_i2c_id,
+	.driver = { .name = "vpp_i2c", },
+};
+
+static struct i2c_board_info vpp_i2c_board_info = {
+	.type          = "vpp_i2c",
+	.flags         = 0x00,
+	.platform_data = NULL,
+	.archdata      = NULL,
+	.irq           = -1,
+};
+#endif
+#ifdef __KERNEL__
+int vpp_i2c_xfer(struct i2c_msg *msg, unsigned int num, int bus_id)
+#else
+int vpp_i2c_xfer(struct i2c_msg_s *msg, unsigned int num, int bus_id)
+#endif
+{
+	int  ret = 1;
+
+#ifdef __KERNEL__
+	int i = 0;
+#if 0
+	if (bus_id == 1) {
+		ret = wmt_i2c_xfer_continue_if_4(msg, num, bus_id);
+		return ret;
+	}
+#endif
+
+	if (num > 1) {
+		for (i = 0; i < num - 1; ++i)
+			msg[i].flags |= I2C_M_NOSTART;
+	}
+	ret = i2c_transfer(vpp_i2c_adapter, msg, num);
+	if (ret <= 0) {
+		DBG_ERR("i2c fail\n");
+		return ret;
+	}
+#elif defined(CONFIG_VPOST)
+	ret = i2c_transfer(msg, num);
+#else
+	ret = wmt_i2c_transfer(msg, num, bus_id);
+#endif
+	return ret;
+}
+
+int vpp_i2c_init(int i2c_id, unsigned short addr)
+{
+#ifdef __KERNEL__
+	struct i2c_board_info *vpp_i2c_bi = &vpp_i2c_board_info;
+	int ret = 0;
+
+	DBGMSG("id %d,addr 0x%x\n", i2c_id, addr);
+
+	if (i2c_id & VPP_DVI_I2C_SW_BIT)
+		return 0;
+
+	i2c_id &= VPP_DVI_I2C_ID_MASK;
+	vpp_i2c_adapter = i2c_get_adapter(i2c_id);
+	if (vpp_i2c_adapter == NULL) {
+		DBG_ERR("can not get i2c adapter, client address error\n");
+		return -ENODEV;
+	}
+
+	vpp_i2c_bi->addr = addr >> 1;
+
+	vpp_i2c_client = i2c_new_device(vpp_i2c_adapter, vpp_i2c_bi);
+	if (vpp_i2c_client == NULL) {
+		DBG_ERR("allocate i2c client failed\n");
+		return -ENOMEM;
+	}
+	i2c_put_adapter(vpp_i2c_adapter);
+
+	ret = i2c_add_driver(&vpp_i2c_driver);
+	if (ret)
+		DBG_ERR("i2c_add_driver fail\n");
+	return ret;
+#else
+	return 0;
+#endif
+}
+
+int vpp_i2c_release(void)
+{
+#ifdef __KERNEL__
+	if (vpp_i2c_client) {
+		i2c_del_driver(&vpp_i2c_driver);
+		i2c_unregister_device(vpp_i2c_client);
+		vpp_i2c_remove(vpp_i2c_client);
+		vpp_i2c_client = 0;
+	}
+#else
+
+#endif
+	return 0;
+}
+
+#ifdef __KERNEL__
+static DEFINE_SEMAPHORE(vpp_i2c_sem);
+#endif
+void vpp_i2c_set_lock(int lock)
+{
+#ifdef __KERNEL__
+	if (lock)
+		down(&vpp_i2c_sem);
+	else
+		up(&vpp_i2c_sem);
+#endif
+}
+
+int vpp_i2c_lock;
+int vpp_i2c_enhanced_ddc_read(int id, unsigned int addr,
+			unsigned int index, char *pdata, int len)
+{
+#ifdef __KERNEL__
+	struct i2c_msg msg[3];
+#else
+	struct i2c_msg_s msg[3];
+#endif
+	unsigned char buf[len + 1];
+	unsigned char buf2[2];
+	int ret = 0;
+
+	vpp_i2c_set_lock(1);
+
+	if (vpp_i2c_lock)
+		DBG_ERR("in lock\n");
+
+	vpp_i2c_lock = 1;
+
+	id = id & VPP_DVI_I2C_ID_MASK;
+	buf2[0] = 0x1;
+	buf2[1] = 0x0;
+	msg[0].addr = (0x60 >> 1);
+	msg[0].flags = 0 ;
+	msg[0].flags &= ~(I2C_M_RD);
+	msg[0].len = 1;
+	msg[0].buf = buf2;
+
+	addr = (addr >> 1);
+	memset(buf, 0x55, len + 1);
+	buf[0] = index;
+	buf[1] = 0x0;
+
+	msg[1].addr = addr;
+	msg[1].flags = 0 ;
+	msg[1].flags &= ~(I2C_M_RD);
+	msg[1].len = 1;
+	msg[1].buf = buf;
+
+	msg[2].addr = addr;
+	msg[2].flags = 0 ;
+	msg[2].flags |= (I2C_M_RD);
+	msg[2].len = len;
+	msg[2].buf = buf;
+
+	ret = vpp_i2c_xfer(msg, 3, id);
+	memcpy(pdata, buf, len);
+	vpp_i2c_lock = 0;
+	vpp_i2c_set_lock(0);
+	return ret;
+} /* End of vpp_i2c_enhanced_ddc_read */
+EXPORT_SYMBOL(vpp_i2c_enhanced_ddc_read);
+
+int vpp_i2c_read(int id, unsigned int addr,
+			unsigned int index, char *pdata, int len)
+{
+	int ret = 0;
+
+	DBG_DETAIL("(%d,0x%x,%d,%d)\n", id, addr, index, len);
+	vpp_i2c_set_lock(1);
+	if (vpp_i2c_lock)
+		DBG_ERR("in lock\n");
+
+	vpp_i2c_lock = 1;
+
+	id = id & VPP_DVI_I2C_ID_MASK;
+	switch (id) {
+	case 0 ... 0xF:	/* hw i2c */
+		{
+#ifdef CONFIG_KERNEL
+		struct i2c_msg msg[2];
+#else
+		struct i2c_msg_s msg[2] ;
+#endif
+		unsigned char buf[len + 1];
+
+		addr = (addr >> 1);
+
+		buf[0] = index;
+		buf[1] = 0x0;
+
+		msg[0].addr = addr; /* slave address */
+		msg[0].flags = 0 ;
+		msg[0].flags &= ~(I2C_M_RD);
+		msg[0].len = 1;
+		msg[0].buf = buf;
+
+		msg[1].addr = addr;
+		msg[1].flags = I2C_M_RD;
+		msg[1].len = len;
+		msg[1].buf = buf;
+		ret = vpp_i2c_xfer(msg, 2, id);
+		memcpy(pdata, buf, len);
+		}
+		break;
+	default:
+#ifdef CONFIG_KERNEL
+		ret = vo_i2c_proc((id & 0xF), (addr | BIT0), index, pdata, len);
+#endif
+		break;
+	}
+#ifdef DEBUG
+	{
+	int i;
+
+	DBGMSG("vpp_i2c_read(addr 0x%x,index 0x%x,len %d\n", addr, index, len);
+	for (i = 0; i < len; i += 8) {
+		DBGMSG("%d : 0x%02x 0x%02x 0x%02x 0x%02x",
+			i, pdata[i], pdata[i + 1], pdata[i + 2], pdata[i + 3]);
+		DBGMSG(" 0x%02x 0x%02x 0x%02x 0x%02x\n",
+			pdata[i + 4], pdata[i + 5], pdata[i + 6], pdata[i + 7]);
+	}
+	}
+#endif
+	vpp_i2c_lock = 0;
+	vpp_i2c_set_lock(0);
+	return ret;
+}
+EXPORT_SYMBOL(vpp_i2c_read);
+
+int vpp_i2c_write(int id, unsigned int addr, unsigned int index,
+				char *pdata, int len)
+{
+	int ret = 0;
+
+	DBG_DETAIL("(%d,0x%x,%d,%d)\n", id, addr, index, len);
+	vpp_i2c_set_lock(1);
+	if (vpp_i2c_lock)
+		DBG_ERR("in lock\n");
+
+	vpp_i2c_lock = 1;
+
+	id = id & VPP_DVI_I2C_ID_MASK;
+	switch (id) {
+	case 0 ... 0xF:	/* hw i2c */
+		{
+#ifdef CONFIG_KERNEL
+		struct i2c_msg msg[1];
+#else
+		struct i2c_msg_s msg[1] ;
+#endif
+		unsigned char buf[len + 1];
+
+		addr = (addr >> 1);
+		buf[0] = index;
+		memcpy(&buf[1], pdata, len);
+		msg[0].addr = addr; /* slave address */
+		msg[0].flags = 0 ;
+		msg[0].flags &= ~(I2C_M_RD);
+		msg[0].len = len + 1;
+		msg[0].buf = buf;
+		ret = vpp_i2c_xfer(msg, 1, id);
+		}
+		break;
+	default:
+#ifdef CONFIG_KERNEL
+		vo_i2c_proc((id & 0xF), (addr & ~BIT0), index, pdata, len);
+#endif
+		break;
+	}
+
+#ifdef DEBUG
+	{
+	int i;
+
+	DBGMSG("vpp_i2c_write(addr 0x%x,index 0x%x,len %d\n", addr, index, len);
+	for (i = 0; i < len; i += 8) {
+		DBGMSG("%d : 0x%02x 0x%02x 0x%02x 0x%02x",
+			i, pdata[i], pdata[i + 1], pdata[i + 2], pdata[i + 3]);
+		DBGMSG(" 0x%02x 0x%02x 0x%02x 0x%02x\n",
+			pdata[i + 4], pdata[i + 5], pdata[i + 6], pdata[i + 7]);
+	}
+	}
+#endif
+	vpp_i2c_lock = 0;
+	vpp_i2c_set_lock(0);
+	return ret;
+}
+EXPORT_SYMBOL(vpp_i2c_write);
+
+void DelayMS(int ms)
+{
+	mdelay(ms);
+}
+EXPORT_SYMBOL(DelayMS);
+
+/*----------------------- VPP debug --------------------------------------*/
+#define VPP_DEBUG_FUNC
+#ifdef VPP_DEBUG_FUNC
+#define VPP_DBG_TMR_NUM		3
+/* #define VPP_DBG_DIAG_NUM	100 */
+#ifdef VPP_DBG_DIAG_NUM
+char vpp_dbg_diag_str[VPP_DBG_DIAG_NUM][100];
+int vpp_dbg_diag_index;
+int vpp_dbg_diag_delay;
+#endif
+
+int vpp_check_dbg_level(enum vpp_dbg_level_t level)
+{
+	if (level == VPP_DBGLVL_ALL)
+		return 1;
+
+	switch (g_vpp.dbg_msg_level) {
+	case VPP_DBGLVL_DISABLE:
+		break;
+	case VPP_DBGLVL_ALL:
+		return 1;
+	default:
+		if (g_vpp.dbg_msg_level == level)
+			return 1;
+		break;
+	}
+	return 0;
+}
+
+void vpp_dbg_show(int level, int tmr, char *str)
+{
+#ifdef __KERNEL__
+	static struct timeval pre_tv[VPP_DBG_TMR_NUM];
+	struct timeval tv;
+	unsigned int tm_usec = 0;
+
+	if (vpp_check_dbg_level(level) == 0)
+		return;
+
+	if (tmr && (tmr <= VPP_DBG_TMR_NUM)) {
+		do_gettimeofday(&tv);
+		if (pre_tv[tmr - 1].tv_sec)
+			tm_usec = (tv.tv_sec == pre_tv[tmr - 1].tv_sec) ?
+			(tv.tv_usec - pre_tv[tmr - 1].tv_usec) :
+			(1000000 + tv.tv_usec - pre_tv[tmr - 1].tv_usec);
+		pre_tv[tmr - 1] = tv;
+	}
+
+#ifdef VPP_DBG_DIAG_NUM
+	if (level == VPP_DBGLVL_DIAG) {
+		if (str) {
+			char *ptr = &vpp_dbg_diag_str[vpp_dbg_diag_index][0];
+			sprintf(ptr, "%s (%d,%d)(T%d %d usec)", str,
+				(int)tv.tv_sec, (int)tv.tv_usec, tmr,
+				(int) tm_usec);
+			vpp_dbg_diag_index = (vpp_dbg_diag_index + 1)
+						% VPP_DBG_DIAG_NUM;
+		}
+
+		if (vpp_dbg_diag_delay) {
+			vpp_dbg_diag_delay--;
+			if (vpp_dbg_diag_delay == 0) {
+				int i;
+
+				DPRINT("----- VPP DIAG -----\n");
+				for (i = 0; i < VPP_DBG_DIAG_NUM; i++) {
+					DPRINT("%02d : %s\n", i,
+				&vpp_dbg_diag_str[vpp_dbg_diag_index][0]);
+				vpp_dbg_diag_index = (vpp_dbg_diag_index + 1)
+					% VPP_DBG_DIAG_NUM;
+				}
+			}
+		}
+		return;
+	}
+#endif
+
+	if (str) {
+		if (tmr)
+			DPRINT("[VPP] %s (T%d period %d usec)\n", str,
+					tmr - 1, (int) tm_usec);
+		else
+			DPRINT("[VPP] %s\n", str);
+	}
+#else
+	if (vpp_check_dbg_level(level) == 0)
+		return;
+
+	if (str)
+		DPRINT("[VPP] %s\n", str);
+#endif
+} /* End of vpp_dbg_show */
+
+void vpp_dbg_show_val1(int level, int tmr, char *str, int val)
+{
+	if (vpp_check_dbg_level(level)) {
+		char buf[50];
+
+		sprintf(buf, "%s 0x%x", str, val);
+		vpp_dbg_show(level, tmr, buf);
+	}
+}
+
+#ifdef __KERNEL__
+static DECLARE_WAIT_QUEUE_HEAD(vpp_dbg_wq);
+void vpp_dbg_wait(char *str)
+{
+	DPRINT("[VPP] vpp_dbg_wait(%s)\n", str);
+	wait_event_interruptible(vpp_dbg_wq, (g_vpp.dbg_wait));
+	g_vpp.dbg_wait = 0;
+	DPRINT("[VPP] Exit vpp_dbg_wait\n");
+}
+
+void vpp_dbg_wake_up(void)
+{
+	wake_up(&vpp_dbg_wq);
+}
+
+int vpp_dbg_get_period_usec(struct vpp_dbg_period_t *p, int cmd)
+{
+	struct timeval tv;
+	int tm_usec = 0;
+
+	if (p == 0)
+		return 0;
+
+	do_gettimeofday(&tv);
+	if (p->pre_tv.tv_sec)
+		tm_usec = (tv.tv_sec == p->pre_tv.tv_sec) ?
+		(tv.tv_usec - p->pre_tv.tv_usec) :
+		(1000000 + tv.tv_usec - p->pre_tv.tv_usec);
+	p->pre_tv = tv;
+	if (cmd == 0) { /* reset */
+		p->index = 0;
+		memset(&p->period_us, 0, VPP_DBG_PERIOD_NUM);
+	} else if (p->index < VPP_DBG_PERIOD_NUM) {
+		p->period_us[p->index] = tm_usec;
+		p->index++;
+	}
+
+	if (cmd == 2) { /* show */
+		int i, sum = 0;
+
+		DPRINT("[VPP] period");
+		for (i = 0; i < VPP_DBG_PERIOD_NUM; i++) {
+			DPRINT(" %d", p->period_us[i]);
+			sum += p->period_us[i];
+		}
+		DPRINT(",sum %d\n", sum);
+	}
+	return tm_usec;
+}
+
+void vpp_dbg_timer(struct vpp_dbg_timer_t *p, char *str, int cmd)
+{
+	struct timeval tv;
+	int tm_usec = 0;
+	int initial = 0;
+
+	if (p == 0)
+		return;
+
+	if (p->reset == 0) { /* default */
+		p->reset = 150;
+		initial = 1;
+	}
+
+	do_gettimeofday(&tv);
+	if (p->pre_tv.tv_sec)
+		tm_usec = (tv.tv_sec == p->pre_tv.tv_sec) ?
+			(tv.tv_usec - p->pre_tv.tv_usec) :
+			(1000000 + tv.tv_usec - p->pre_tv.tv_usec);
+	p->pre_tv = tv;
+	switch (cmd) {
+	case 0: /* initial */
+		initial = 1;
+		break;
+	case 1: /* start */
+		break;
+	case 2: /* end */
+		p->cnt++;
+		p->sum += tm_usec;
+		if (p->min > tm_usec)
+			p->min = tm_usec;
+		if (p->max < tm_usec)
+			p->max = tm_usec;
+		if (p->threshold && (tm_usec >= p->threshold))
+			MSG("%s tmr %d over %d\n", str, tm_usec, p->threshold);
+		if (p->cnt >= p->reset) {
+			int us_1t;
+
+			us_1t = p->sum / p->cnt;
+			MSG("%s(Cnt %d)Sum %d us,Avg %d,Min %d,Max %d,",
+				str, p->cnt, p->sum, us_1t, p->min, p->max);
+			MSG("fps %d.%02d\n", 1000000 / us_1t,
+				(100000000 / us_1t) % 100);
+			initial = 1;
+		}
+		break;
+	default:
+		break;
+	}
+
+	if (initial) {
+		p->cnt = 0;
+		p->sum = 0;
+		p->min = ~0;
+		p->max = 0;
+	}
+}
+#endif
+#else
+void vpp_dbg_show(int level, int tmr, char *str) {}
+static void vpp_dbg_show_val1(int level, int tmr, char *str, int val) {}
+void vpp_dbg_wait(char *str) {}
+#endif
+
+#if 0
+static void load_regs(struct pt_regs *ptr)
+{
+	asm volatile(
+	"stmia %0, {r0 - r15}\n\t"
+	:
+	: "r" (ptr)
+	: "memory"
+	);
+}
+
+void vpp_dbg_back_trace(void)
+{
+	struct pt_regs *ptr;
+	unsigned int fp;
+	unsigned long flags;
+
+	ptr = kmalloc(sizeof(struct pt_regs), GFP_KERNEL);
+
+	local_irq_save(flags);
+
+	MSG("\n\nstart back trace...\n");
+	load_regs(ptr);
+	fp = ptr->ARM_fp;
+	c_backtrace(fp, 0x1f);
+	MSG("back trace end...\n\n");
+
+	local_irq_restore(flags);
+
+	kfree(ptr);
+}
+EXPORT_SYMBOL(vpp_dbg_back_trace);
+#endif
+
+void vpp_reg_dump(unsigned int addr, int size)
+{
+	int i;
+
+	for (i = 0; i < size; i += 16) {
+		DPRINT("0x%8x : 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			addr + i, inl(addr + i),
+			inl(addr + i + 4),
+			inl(addr + i + 8),
+			inl(addr + i + 12));
+	}
+}
+
+unsigned int *vpp_backup_reg(unsigned int addr, unsigned int size)
+{
+	unsigned int *ptr;
+	int i;
+
+	size += 4;
+	ptr = kmalloc(size, GFP_KERNEL);
+	if (ptr == 0) {
+		DPRINT("[VPP] *E* malloc backup fail\n");
+		return 0;
+	}
+
+	for (i = 0; i < size; i += 4)
+		ptr[i / 4] = inl(addr + i);
+	return ptr;
+}
+
+int vpp_restore_reg(unsigned int addr, unsigned int size,
+					unsigned int *reg_ptr)
+{
+	int i;
+
+	if (reg_ptr == NULL)
+		return 0;
+
+	size += 4;
+	for (i = 0; i < size; i += 4)
+		outl(reg_ptr[i / 4], addr + i);
+	kfree(reg_ptr);
+	reg_ptr = 0;
+	return 0;
+}
+
diff --git a/drivers/video/wmt/vpp-osif.h b/drivers/video/wmt/vpp-osif.h
new file mode 100755
index 00000000..ddc561e7
--- /dev/null
+++ b/drivers/video/wmt/vpp-osif.h
@@ -0,0 +1,263 @@
+/*++
+ * linux/drivers/video/wmt/vpp-osif.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#ifndef VPP_OSIF_H
+#define VPP_OSIF_H
+
+/*-------------------- DEPENDENCY -------------------------------------*/
+#ifdef CFG_LOADER
+	#define CONFIG_UBOOT
+
+	#ifdef __KERNEL__
+	#undef __KERNEL__
+	#endif
+#elif defined(__KERNEL__)
+	#define CONFIG_KERNEL
+#else
+	#define CONFIG_VPOST
+#endif
+
+/* -------------------------------------------------- */
+#ifdef DEBUG
+  #define DBG_MSG(fmt, args...)	DPRINT("{%s} " fmt, __func__, ## args)
+#else
+  #define DBG_MSG(fmt, args...)
+#endif
+
+#ifdef DEBUG_DETAIL
+#define DBG_DETAIL(fmt, args...) DPRINT("{%s} " fmt, __func__, ## args)
+#else
+#define DBG_DETAIL(fmt, args...)
+#endif
+#define MSG(fmt, args...)     DPRINT("" fmt, ## args)
+#define DBG_ERR(fmt, args...) \
+	DPRINT(KERN_ERR "*E* {%s} " fmt, __func__, ## args)
+#define DMSG(fmt, args...) \
+	DPRINT("{%s,%d} " fmt, __func__, __LINE__, ## args)
+
+#ifdef DEBUG
+#define DBGMSG(fmt, args...)  DPRINT("{%s} " fmt, __func__, ## args)
+#else
+#define DBGMSG(fmt, args...)
+#endif
+
+#if 0	/* disable all msg */
+#undef MSG
+#undef DBGMSG
+
+#define MSG(fmt, args...)
+#define DBGMSG(fmt, args...)
+#endif
+
+#define HW_REG volatile
+
+/* -------------------------------------------------- */
+#ifdef CONFIG_KERNEL
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/wmt-mb.h>
+#include <linux/netlink.h>
+#include <linux/switch.h>
+#include <net/sock.h>
+#include <mach/hardware.h>
+#include <mach/wmt_mmap.h>
+
+#define SA_INTERRUPT IRQF_DISABLED
+#endif
+
+/* -------------------------------------------------- */
+#ifdef CONFIG_UBOOT
+#define CONFIG_WMT_EDID
+#define CONFIG_WMT_EXT_DEV_PLUG_DISABLE
+
+#include <linux/types.h>
+#include "../../board/wmt/include/common_def.h"
+#include <common.h>
+#include <malloc.h>
+#include "hw_devices.h"
+#include "hw/wmt_mmap.h"
+#include "hw/wmt-pwm.h"
+#include "hw/wmt-ost.h"
+#include "hw/wmt_gpio.h"
+#include "wmt_display.h"
+#include "../../board/wmt/include/wmt_clk.h"
+#include "../../board/wmt/include/i2c.h"
+
+#define abs(a)  ((a >= 0) ? a : (-1 * a))
+#endif
+
+/* -------------------------------------------------- */
+#ifdef CONFIG_VPOST
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "global.h"
+#define __ASM_ARCH_HARDWARE_H
+#include "../include/wmt_mmap.h"
+#include "../pmc/wmt_clk.h"
+#include "../i2c/i2c.h"
+#include "linux/wmt-mb.h"
+#endif
+
+/*	following is the C++ header	*/
+#ifdef	__cplusplus
+extern	"C" {
+#endif
+
+/*-------------------- EXPORTED PRIVATE CONSTANTS ----------------------------*/
+#ifdef CONFIG_KERNEL
+#define THE_MB_USER "VPP-MB"
+#define DPRINT printk
+/* -------------------------------------------------- */
+#endif
+
+#ifdef CONFIG_UBOOT
+#define IRQ_GPIO	0
+
+#define mdelay(x) wmt_delayus(1000 * x)
+#define udelay(x) wmt_delayus(x)
+
+#define mb_alloc(a)	malloc(a)
+#define kmalloc(a, b)	malloc(a)
+#define kfree(a)	free(a)
+#define GFP_KERNEL	0
+#define module_init(a)
+
+#define DPRINT printf
+#define mb_phys_to_virt(a)	(a)
+#define mb_virt_to_phys(a)	(a)
+#define EXPORT_SYMBOL(a)
+
+#define IRQF_SHARED	0
+#define IRQF_DISABLED	0
+#define SA_INTERRUPT	0
+
+#define KERN_ALERT
+#define KERN_ERR
+#define KERN_DEBUG
+#define KERN_WARNING
+#define KERN_INFO
+
+#define printk printf
+#endif
+
+/*-------------------- EXPORTED PRIVATE TYPES---------------------------------*/
+/* typedef  void  hdmi_xxx_t;  *//*Example*/
+
+/*-------------------- EXPORTED PRIVATE VARIABLES ----------------------------*/
+#ifdef VPP_OSIF_C
+#define EXTERN
+#else
+#define EXTERN   extern
+#endif /* ifdef VPP_OSIF_C */
+
+/* EXTERN int      hdmi_xxx; *//*Example*/
+
+#undef EXTERN
+
+/*--------------------- EXPORTED PRIVATE MACROS ------------------------------*/
+/* #define HDMI_XXX_YYY   xxxx *//*Example*/
+
+/*--------------------- EXPORTED PRIVATE FUNCTIONS  --------------------------*/
+/* extern void  hdmi_xxx(void); *//*Example*/
+#ifdef CONFIG_KERNEL
+extern void wmt_i2c_xfer_continue_if(struct i2c_msg *msg,
+					unsigned int num);
+extern void wmt_i2c_xfer_if(struct i2c_msg *msg);
+extern int wmt_i2c_xfer_continue_if_4(struct i2c_msg *msg,
+					unsigned int num, int bus_id);
+#else
+inline unsigned int inl(unsigned int offset);
+inline void outl(unsigned int val, unsigned int offset);
+inline unsigned short inw(unsigned int offset);
+inline void outw(unsigned short val, unsigned int offset);
+inline unsigned char inb(unsigned int offset);
+inline void outb(unsigned char val, unsigned int offset);
+#endif
+
+#ifdef CONFIG_UBOOT
+extern int wmt_getsyspara(char *varname, char *varval, int *varlen);
+extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd,
+				int unit, int freq);
+extern struct fb_var_screeninfo vfb_var;
+#endif
+
+#ifdef CONFIG_VPOST
+void vpp_initialization(int FunctionNumber);
+void udelay(int us);
+void mdelay(int ms);
+extern int auto_pll_divisor(enum dev_id dev, enum clk_cmd cmd,
+					int unit, int freq);
+extern void vpp_post_delay(U32 tmr);
+extern int get_num(unsigned int min, unsigned int max,
+				char *message, unsigned int retry);
+#endif
+
+extern unsigned int wmt_read_oscr(void);
+int wmt_getsyspara(char *varname, char *varval, int *varlen);
+int vpp_request_irq(unsigned int irq_no, void *routine,
+				unsigned int flags, char *name, void *arg);
+void vpp_free_irq(unsigned int irq_no, void *arg);
+int vpp_parse_param(char *buf, unsigned int *param,
+				int cnt, unsigned int hex_mask);
+void vpp_lock_l(void);
+void vpp_unlock(void);
+
+#define vpp_lock() vpp_lock_l(); \
+	/* DPRINT("vpp_lock %s %d\n",__FUNCTION__,__LINE__); */
+
+int vpp_i2c_write(int id, unsigned int addr, unsigned int index,
+				char *pdata, int len);
+int vpp_i2c_read(int id, unsigned int addr, unsigned int index,
+				char *pdata, int len);
+int vpp_i2c_enhanced_ddc_read(int id, unsigned int addr,
+			unsigned int index, char *pdata, int len);
+int vpp_i2c_init(int i2c_id, unsigned short addr);
+int vpp_i2c_release(void);
+void vpp_set_clock_enable(enum dev_id dev, int enable, int force);
+void vpp_udelay(unsigned int us);
+unsigned int vppif_reg32_write(unsigned int offset,
+	unsigned int mask, unsigned int shift, unsigned int val);
+unsigned int vppif_reg32_read(unsigned int offset,
+	unsigned int mask, unsigned int shift);
+unsigned int vppif_reg32_mask(unsigned int offset,
+	unsigned int mask, unsigned int shift);
+void vpp_reg_dump(unsigned int addr, int size);
+unsigned int *vpp_backup_reg(unsigned int addr, unsigned int size);
+int vpp_restore_reg(unsigned int addr,
+	unsigned int size, unsigned int *reg_ptr);
+
+#ifdef	__cplusplus
+}
+#endif
+#endif /* VPP_OSIF_H */
+
diff --git a/drivers/video/wmt/vpp.c b/drivers/video/wmt/vpp.c
new file mode 100755
index 00000000..544d9dbf
--- /dev/null
+++ b/drivers/video/wmt/vpp.c
@@ -0,0 +1,1413 @@
+/*++
+ * linux/drivers/video/wmt/vpp.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VPP_C
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "vpp.h"
+
+struct vpp_mod_base_t *vpp_mod_base_list[VPP_MOD_MAX];
+
+unsigned int vpp_get_chipid(void)
+{
+	/* byte 3,2: chip id, byte 1:ver id, byte 0:sub id */
+	/* ex: 0x34290101 (0x3429 A0), 0x34290102 (0x3429 A1) */
+	return inl(SYSTEM_CFG_CTRL_BASE_ADDR);
+}
+
+inline void vpp_cache_sync(void)
+{
+	/* TODO */
+}
+
+void vpp_set_clock_enable(enum dev_id dev, int enable, int force)
+{
+#ifdef CONFIG_VPP_DISABLE_PM
+	return;
+#else
+	int cnt;
+
+	do {
+		cnt = auto_pll_divisor(dev,
+			(enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0);
+		if (enable) {
+			if (cnt)
+				break;
+		} else {
+			if (cnt == 0)
+				break;
+		}
+	} while (force);
+/*	MSG("%s(%d,%d,%d)\n", __FUNCTION__, dev, enable, cnt); */
+#endif
+}
+
+/*----------------------- vpp module --------------------------------------*/
+void vpp_mod_unregister(vpp_mod_t mod)
+{
+	struct vpp_mod_base_t *mod_p;
+
+	if (mod >= VPP_MOD_MAX)
+		return;
+
+	mod_p = vpp_mod_base_list[mod];
+	if (!mod_p)
+		return;
+
+	kfree(mod_p->fb_p);
+	kfree(mod_p);
+	vpp_mod_base_list[mod] = 0;
+}
+
+struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod,
+					int size, unsigned int flags)
+{
+	struct vpp_mod_base_t *mod_p;
+
+	if (mod >= VPP_MOD_MAX)
+		return 0;
+
+	if (vpp_mod_base_list[mod])
+		vpp_mod_unregister(mod);
+
+	mod_p = kmalloc(size, GFP_KERNEL);
+	if (!mod_p)
+		return 0;
+
+	vpp_mod_base_list[mod] = mod_p;
+	memset(mod_p, 0, size);
+	mod_p->mod = mod;
+
+	if (flags & VPP_MOD_FLAG_FRAMEBUF) {
+		mod_p->fb_p = kmalloc(sizeof(struct vpp_fb_base_t), GFP_KERNEL);
+		if (!mod_p->fb_p)
+			goto error;
+		memset(mod_p->fb_p, 0, sizeof(struct vpp_fb_base_t));
+	}
+	DBG_DETAIL(" %d,0x%x,0x%x\n", mod, (int)mod_p, (int)mod_p->fb_p);
+	return mod_p;
+error:
+	vpp_mod_unregister(mod);
+	DPRINT("vpp mod register NG %d\n", mod);
+	return 0;
+}
+
+struct vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod)
+{
+	if (mod >= VPP_MOD_MAX)
+		return 0;
+	return vpp_mod_base_list[mod];
+}
+
+struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod)
+{
+	struct vpp_mod_base_t *mod_p;
+	mod_p = vpp_mod_get_base(mod);
+	if (mod_p)
+		return mod_p->fb_p;
+	return 0;
+}
+
+vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod)
+{
+	struct vpp_mod_base_t *mod_p;
+
+	mod_p = vpp_mod_get_base(mod);
+	if (mod_p && mod_p->fb_p)
+		return &mod_p->fb_p->fb;
+	return 0;
+}
+
+void vpp_mod_set_clock(vpp_mod_t mod, vpp_flag_t enable, int force)
+{
+	struct vpp_mod_base_t *base;
+	enum dev_id pll_dev;
+	int cur_sts;
+	int ret;
+
+#ifdef CONFIG_VPP_DISABLE_PM
+	return;
+#endif
+
+	base = vpp_mod_get_base(mod);
+	if (base == 0)
+		return;
+
+	pll_dev = (base->pm & 0xFF);
+	if (pll_dev == 0)
+		return;
+
+	enable = (enable) ? VPP_FLAG_ENABLE : VPP_FLAG_DISABLE;
+	if (force) {
+		ret = auto_pll_divisor(pll_dev,
+			(enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0);
+		DBG_DETAIL("[VPP] clk force(%s,%d),ret %d\n",
+			vpp_mod_str[mod], enable, ret);
+		return;
+	}
+
+	cur_sts = (base->pm & VPP_MOD_CLK_ON) ? 1 : 0;
+	if (cur_sts != enable) {
+		ret = auto_pll_divisor(pll_dev,
+			(enable) ? CLK_ENABLE : CLK_DISABLE, 0, 0);
+		base->pm = (enable) ? (base->pm | VPP_MOD_CLK_ON)
+			: (base->pm & ~VPP_MOD_CLK_ON);
+		DBG_MSG("[VPP] clk enable(%s,%d,cur %d),ret %d\n",
+			vpp_mod_str[mod], enable, cur_sts, ret);
+	}
+}
+
+vpp_display_format_t vpp_get_fb_field(vdo_framebuf_t *fb)
+{
+	if (fb->flag & VDO_FLAG_INTERLACE)
+		return VPP_DISP_FMT_FIELD;
+	return VPP_DISP_FMT_FRAME;
+}
+
+unsigned int vpp_get_base_clock(vpp_mod_t mod)
+{
+	unsigned int clock = 0;
+
+	switch (mod) {
+	default:
+		clock = auto_pll_divisor(DEV_VPP, GET_FREQ, 0, 0);
+		break;
+	case VPP_MOD_GOVRH:
+		clock = (p_govrh->vo_clock == 0) ?
+			auto_pll_divisor(DEV_HDMILVDS, GET_FREQ, 0, 0) :
+			p_govrh->vo_clock;
+		break;
+	case VPP_MOD_GOVRH2:
+		clock = (p_govrh2->vo_clock == 0) ?
+			auto_pll_divisor(DEV_DVO, GET_FREQ, 0, 0) :
+			p_govrh2->vo_clock;
+		break;
+	}
+	DBG_DETAIL("%d %d\n", mod, clock);
+	return clock;
+}
+
+void vpp_show_timing(char *str, struct fb_videomode *vmode,
+					vpp_clock_t *clk)
+{
+	DPRINT("----- %s timing -----\n", str);
+	if (vmode) {
+		int pixclk;
+
+		pixclk = (vmode->pixclock) ? PICOS2KHZ(vmode->pixclock) : 0;
+		pixclk *= 1000;
+
+		DPRINT("res(%d,%d),fps %d\n",
+			vmode->xres, vmode->yres, vmode->refresh);
+		DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", vmode->pixclock,
+			pixclk, vmode->hsync_len, vmode->vsync_len);
+		DPRINT("left %d,right %d,upper %d,lower %d\n",
+			vmode->left_margin, vmode->right_margin,
+			vmode->upper_margin, vmode->lower_margin);
+		DPRINT("vmode 0x%x,sync 0x%x\n", vmode->vmode, vmode->sync);
+	}
+
+	if (clk) {
+		DPRINT("H beg %d,end %d,total %d\n", clk->begin_pixel_of_active,
+			clk->end_pixel_of_active, clk->total_pixel_of_line);
+		DPRINT("V beg %d,end %d,total %d\n", clk->begin_line_of_active,
+			clk->end_line_of_active, clk->total_line_of_frame);
+		DPRINT("Hsync %d, Vsync %d\n", clk->hsync, clk->vsync);
+		DPRINT("VBIE %d,PVBI %d\n", clk->line_number_between_VBIS_VBIE,
+			clk->line_number_between_PVBI_VBIS);
+	}
+	DPRINT("-----------------------\n");
+}
+
+void vpp_show_framebuf(char *str, vdo_framebuf_t *fb)
+{
+	if (fb == 0)
+		return;
+	DPRINT("----- %s framebuf -----\n", str);
+	DPRINT("Y addr 0x%x, size %d\n", fb->y_addr, fb->y_size);
+	DPRINT("C addr 0x%x, size %d\n", fb->c_addr, fb->c_size);
+	DPRINT("W %d, H %d, FB W %d, H %d\n", fb->img_w, fb->img_h,
+						fb->fb_w, fb->fb_h);
+	DPRINT("bpp %d, color fmt %s\n", fb->bpp, vpp_colfmt_str[fb->col_fmt]);
+	DPRINT("H crop %d, V crop %d, flag 0x%x\n",
+		fb->h_crop, fb->v_crop, fb->flag);
+	DPRINT("-----------------------\n");
+}
+
+void vpp_show_videomode(char *str, struct fb_videomode *v)
+{
+	if (v == 0)
+		return;
+	DPRINT("----- %s videomode -----\n", str);
+	DPRINT("%dx%d@%d,%d\n", v->xres, v->yres, v->refresh, v->pixclock);
+	DPRINT("h sync %d,bp %d,fp %d\n", v->hsync_len,
+		v->left_margin, v->right_margin);
+	DPRINT("v sync %d,bp %d,fp %d\n", v->vsync_len,
+		v->upper_margin, v->lower_margin);
+	DPRINT("sync 0x%x,vmode 0x%x,flag 0x%x\n", v->sync, v->vmode, v->flag);
+	DPRINT("hsync %s,vsync %s\n",
+		(v->sync & FB_SYNC_HOR_HIGH_ACT) ? "hi" : "lo",
+		(v->sync & FB_SYNC_VERT_HIGH_ACT) ? "hi" : "lo");
+	DPRINT("interlace %d,double %d\n",
+		(v->vmode & FB_VMODE_INTERLACED) ? 1 : 0,
+		(v->vmode & FB_VMODE_DOUBLE) ? 1 : 0);
+	DPRINT("-----------------------\n");
+}
+
+vpp_csc_t vpp_check_csc_mode(vpp_csc_t mode, vdo_color_fmt src_fmt,
+				vdo_color_fmt dst_fmt, unsigned int flags)
+{
+	if (mode >= VPP_CSC_MAX)
+		return VPP_CSC_BYPASS;
+
+	mode = (mode >= VPP_CSC_RGB2YUV_MIN) ?
+		(mode - VPP_CSC_RGB2YUV_MIN) : mode;
+	if (src_fmt >= VDO_COL_FMT_ARGB) {
+		mode = VPP_CSC_RGB2YUV_MIN + mode;
+		src_fmt = VDO_COL_FMT_ARGB;
+	} else {
+		src_fmt = VDO_COL_FMT_YUV444;
+	}
+	dst_fmt = (dst_fmt >= VDO_COL_FMT_ARGB) ?
+		VDO_COL_FMT_ARGB : VDO_COL_FMT_YUV444;
+	if (flags == 0)
+		mode = (src_fmt != dst_fmt) ? mode : VPP_CSC_BYPASS;
+	return mode;
+}
+
+int vpp_get_gcd(int A, int B)
+{
+	while (A != B) {
+		if (A > B)
+			A = A - B;
+		else
+			B = B - A;
+	}
+	return A;
+}
+
+int vpp_set_recursive_scale(vdo_framebuf_t *src_fb,
+					vdo_framebuf_t *dst_fb)
+{
+#ifdef WMT_FTBLK_SCL
+	int ret;
+
+	ret = p_scl->scale(src_fb, dst_fb);
+	return ret;
+#else
+	DBG_ERR("No scale\n");
+	return 0;
+#endif
+}
+
+unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data)
+{
+	unsigned int r, g, b;
+	unsigned int y, u, v;
+	unsigned int alpha;
+
+	alpha = data & 0xff000000;
+	if (yuv2rgb) {
+		y = (data & 0xff0000) >> 16;
+		u = (data & 0xff00) >> 8;
+		v = (data & 0xff) >> 0;
+
+		r = ((1000 * y) + 1402 * (v - 128)) / 1000;
+		if (r > 0xFF)
+			r = 0xFF;
+		g = ((100000 * y) - (71414 * (v - 128))
+			- (34414 * (u - 128))) / 100000;
+		if (g > 0xFF)
+			g = 0xFF;
+		b = ((1000 * y) + (1772 * (u - 128))) / 1000;
+		if (b > 0xFF)
+			b = 0xFF;
+
+		data = ((r << 16) + (g << 8) + b);
+	} else {
+		r = (data & 0xff0000) >> 16;
+		g = (data & 0xff00) >> 8;
+		b = (data & 0xff) >> 0;
+
+		y = ((2990 * r) + (5870 * g) + (1440 * b)) / 10000;
+		if (y > 0xFF)
+			y = 0xFF;
+		u = (1280000 - (1687 * r) - (3313 * g) + (5000 * b)) / 10000;
+		if (u > 0xFF)
+			u = 0xFF;
+		v = (1280000 + (5000 * r) - (4187 * g) - (813 * b)) / 10000;
+		if (v > 0xFF)
+			v = 0xFF;
+
+		data = ((y << 16) + (v << 8) + u);
+	}
+	data = data + alpha;
+	return data;
+}
+
+void vpp_get_sys_parameter(void)
+{
+#ifndef CONFIG_VPOST
+	char buf[40];
+	int varlen = 40;
+#else
+	struct env_para_def param;
+#endif
+
+	/* vpp attribute by default */
+	g_vpp.dbg_msg_level = 0;
+	g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF;
+	g_vpp.hdmi_cp_enable = 1;
+
+#ifdef CONFIG_KERNEL
+	if (govrh_get_MIF_enable(p_govrh))
+		g_vpp.govrh_preinit = 1;
+	if (govrh_get_MIF_enable(p_govrh2))
+		g_vpp.govrh_preinit = 1;
+	MSG("[VPP] govrh preinit %d\n", g_vpp.govrh_preinit);
+#else
+	g_vpp.govrh_preinit = 0;
+	p_scl->scale_sync = 1;
+#endif
+
+#ifndef CONFIG_VPOST
+	if (wmt_getsyspara("wmt.display.hdmi_audio_inf", buf, &varlen) == 0) {
+		if (memcmp(buf, "i2s", 3) == 0)
+			g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_I2S;
+		else if (memcmp(buf, "spdif", 5) == 0)
+			g_vpp.hdmi_audio_interface = VPP_HDMI_AUDIO_SPDIF;
+	}
+
+	g_vpp.mb_colfmt = VPP_UBOOT_COLFMT;
+	/* [uboot parameter] fb param : no:xresx:yres:xoffset:yoffset */
+	if (wmt_getsyspara("wmt.gralloc.param", buf, &varlen) == 0) {
+		unsigned int parm[1];
+
+		vpp_parse_param(buf, (unsigned int *)parm, 1, 0x1);
+		if (parm[0] == 32)
+			g_vpp.mb_colfmt = VDO_COL_FMT_ARGB;
+		MSG("mb colfmt : %s,%s\n", buf,
+			vpp_colfmt_str[g_vpp.mb_colfmt]);
+	}
+	p_govrh->fb_p->fb.col_fmt = g_vpp.mb_colfmt;
+	p_govrh2->fb_p->fb.col_fmt = g_vpp.mb_colfmt;
+
+	if (wmt_getsyspara("wmt.display.hdmi", buf, &varlen) == 0) {
+		unsigned int parm[1];
+
+		MSG("hdmi sp mode : %s\n", buf);
+		vpp_parse_param(buf, (unsigned int *)parm, 1, 0);
+		g_vpp.hdmi_sp_mode = (parm[0]) ? 1 : 0;
+	}
+
+	if (wmt_getsyspara("wmt.hdmi.disable", buf, &varlen) == 0)
+		g_vpp.hdmi_disable = 1;
+
+	/* [uboot parameter] reg operation : addr op val */
+	if (wmt_getsyspara("wmt.display.regop", buf, &varlen) == 0) {
+		unsigned int addr;
+		unsigned int val;
+		char op;
+		char *p, *endp;
+
+		p = buf;
+		while (1) {
+			addr = simple_strtoul(p, &endp, 16);
+			if (*endp == '\0')
+				break;
+
+			op = *endp;
+			if (endp[1] == '~') {
+				val = simple_strtoul(endp + 2, &endp, 16);
+				val = ~val;
+			} else
+				val = simple_strtoul(endp + 1, &endp, 16);
+
+			DBG_DETAIL("  reg op: 0x%X %c 0x%X\n", addr, op, val);
+			switch (op) {
+			case '|':
+				outl(inl(addr) | val, addr);
+				break;
+			case '=':
+				outl(val, addr);
+				break;
+			case '&':
+				outl(inl(addr) & val, addr);
+				break;
+			default:
+				DBG_ERR("Error, Unknown operator %c\n", op);
+			}
+
+			if (*endp == '\0')
+				break;
+			p = endp + 1;
+		}
+	}
+#else
+	if (env_read_para("wmt.display.hdmi", &param) == 0) {
+		g_vpp.hdmi_sp_mode = strtoul(param.value, 0, 16);
+		free(param.value);
+	}
+#endif
+} /* End of vpp_get_sys_parameter */
+
+void vpp_init(void)
+{
+	struct vpp_mod_base_t *mod_p;
+	unsigned int mod_mask;
+	int i;
+
+	auto_pll_divisor(DEV_NA12, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_VPP, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_HDCE, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_HDMII2C, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_HDMI, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_GOVRHD, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_DVO, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_LVDS, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_HDMILVDS, CLK_ENABLE, 0, 0);
+	auto_pll_divisor(DEV_SCL444U, CLK_ENABLE, 0, 0);
+
+	vpp_get_sys_parameter();
+
+	/* init video out module first */
+	if (g_vpp.govrh_preinit == 0) {
+		mod_mask = BIT(VPP_MOD_GOVRH2) | BIT(VPP_MOD_GOVRH)
+			| BIT(VPP_MOD_DISP) | BIT(VPP_MOD_LCDC);
+		for (i = 0; i < VPP_MOD_MAX; i++) {
+			if (!(mod_mask & (0x01 << i)))
+				continue;
+			mod_p = vpp_mod_get_base(i);
+			if (mod_p && mod_p->init)
+				mod_p->init(mod_p);
+		}
+	}
+
+#ifdef CONFIG_UBOOT
+	mod_mask =  BIT(VPP_MOD_SCL) | BIT(VPP_MOD_SCLW);
+#else
+	/* init other module */
+	mod_mask =  BIT(VPP_MOD_GOVW) | BIT(VPP_MOD_GOVM) | BIT(VPP_MOD_SCL)
+		| BIT(VPP_MOD_SCLW) | BIT(VPP_MOD_VPU) | BIT(VPP_MOD_VPUW)
+		| BIT(VPP_MOD_PIP) | BIT(VPP_MOD_VPPM);
+#endif
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		if (!(mod_mask & (0x01 << i)))
+			continue;
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->init)
+			mod_p->init(mod_p);
+	}
+
+#ifdef WMT_FTBLK_LVDS
+	if (!g_vpp.govrh_preinit)
+		lvds_init();
+#endif
+#ifdef WMT_FTBLK_VOUT_HDMI
+	hdmi_init();
+#endif
+
+#ifndef CONFIG_VPOST
+	/* init vout device & get default resolution */
+	vout_init();
+#endif
+	vpp_set_clock_enable(DEV_SCL444U, 0, 1);
+	vpp_set_clock_enable(DEV_HDMII2C, 0, 0);
+	vpp_set_clock_enable(DEV_HDMI, 0, 0);
+	vpp_set_clock_enable(DEV_HDCE, 0, 0);
+	vpp_set_clock_enable(DEV_LVDS, 0, 0);
+}
+
+void vpp_get_colfmt_bpp(vdo_color_fmt colfmt, int *y_bpp, int *c_bpp)
+{
+	switch (colfmt) {
+	case VDO_COL_FMT_YUV420:
+		*y_bpp = 8;
+		*c_bpp = 4;
+		break;
+	case VDO_COL_FMT_YUV422H:
+	case VDO_COL_FMT_YUV422V:
+		*y_bpp = 8;
+		*c_bpp = 8;
+		break;
+	case VDO_COL_FMT_RGB_565:
+	case VDO_COL_FMT_RGB_1555:
+	case VDO_COL_FMT_RGB_5551:
+		*y_bpp = 16;
+		*c_bpp = 0;
+		break;
+	case VDO_COL_FMT_YUV444:
+		*y_bpp = 8;
+		*c_bpp = 16;
+		break;
+	case VDO_COL_FMT_RGB_888:
+	case VDO_COL_FMT_RGB_666:
+		*y_bpp = 24;
+		*c_bpp = 0;
+		break;
+	case VDO_COL_FMT_ARGB:
+		*y_bpp = 32;
+		*c_bpp = 0;
+		break;
+	default:
+		break;
+	}
+}
+
+int vpp_calc_refresh(int pixclk, int xres, int yres)
+{
+	int refresh = 60;
+	int temp;
+
+	temp = xres * yres;
+	if (temp) {
+		refresh = pixclk / temp;
+		if (pixclk % temp)
+			refresh += 1;
+	}
+	return refresh;
+}
+
+int vpp_calc_align(int value, int align)
+{
+	if (value % align) {
+		value &= ~(align - 1);
+		value += align;
+	}
+	return value;
+}
+
+int vpp_calc_fb_width(vdo_color_fmt colfmt, int width)
+{
+	int y_bpp, c_bpp;
+
+	vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+	return vpp_calc_align(width, VPP_FB_WIDTH_ALIGN / (y_bpp / 8));
+}
+
+void vpp_set_NA12_hiprio(int type)
+{
+#if 0
+	static int reg1, reg2;
+
+	switch (type) {
+	case 0: /* restore NA12 priority */
+		outl(reg1, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+		outl(reg2, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+		break;
+	case 1:	/* set NA12 to high priority */
+		reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+		reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+		outl(0x600000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+		outl(0x0ff00000, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+		break;
+	case 2:
+		reg1 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+		reg2 = inl(MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+		outl(0x20003f, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0x8);
+		outl(0x00ffff00, MEMORY_CTRL_V4_CFG_BASE_ADDR + 0xC);
+		break;
+	default:
+		break;
+	}
+#endif
+}
+
+#ifdef __KERNEL__
+int vpp_set_audio(int format, int sample_rate, int channel)
+{
+	struct vout_audio_t info;
+
+	MSG("set audio(fmt %d,rate %d,ch %d)\n",
+		format, sample_rate, channel);
+	info.fmt = format;
+	info.sample_rate = sample_rate;
+	info.channel = channel;
+	return vout_set_audio(&info);
+}
+#endif
+
+/*----------------------- vpp mb for stream ---------------------------------*/
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+#ifdef CONFIG_VPP_STREAM_BLOCK
+DECLARE_WAIT_QUEUE_HEAD(vpp_mb_event);
+#endif
+
+unsigned int vpp_mb_get_mask(unsigned int phy)
+{
+	int i;
+	unsigned int mask;
+
+	for (i = 0; i < g_vpp.stream_mb_cnt; i++) {
+		if (g_vpp.stream_mb[i] == phy)
+			break;
+	}
+	if (i >= g_vpp.stream_mb_cnt)
+		return 0;
+	mask = 0x1 << i;
+	return mask;
+}
+
+int vpp_mb_get(unsigned int phy)
+{
+	unsigned int mask;
+	int i, cnt;
+
+#ifdef CONFIG_VPP_STREAM_BLOCK
+	vpp_unlock();
+	if (g_vpp.stream_mb_sync_flag)
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "mb_get wait");
+
+	i = wait_event_interruptible_timeout(vpp_mb_event,
+		(g_vpp.stream_mb_sync_flag != 1), HZ / 20);
+	vpp_lock();
+#else /* non-block */
+	if (g_vpp.stream_mb_sync_flag) { /* not new mb updated */
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 0,
+			"*W* mb_get addr not update");
+		return -1;
+	}
+#endif
+	g_vpp.stream_mb_sync_flag = 1;
+	for (i = 0, cnt = 0; i < g_vpp.stream_mb_cnt; i++) {
+		if (g_vpp.stream_mb_lock & (0x1 << i))
+			cnt++;
+	}
+
+#if 0
+	if (cnt >= (g_vpp.stream_mb_cnt - 2)) {
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get addr not free");
+		return -1;
+	}
+#endif
+
+	mask = vpp_mb_get_mask(phy);
+	if (mask == 0) {
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get invalid addr");
+		return -1;
+	}
+	if (g_vpp.stream_mb_lock & mask) {
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 0, "*W* mb_get lock addr");
+		return -1;
+	}
+	g_vpp.stream_mb_lock |= mask;
+	if (vpp_check_dbg_level(VPP_DBGLVL_STREAM)) {
+		char buf[50];
+
+		sprintf(buf, "stream mb get 0x%x,mask 0x%x(0x%x)",
+			phy, mask, g_vpp.stream_mb_lock);
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 1, buf);
+	}
+	return 0;
+}
+
+int vpp_mb_put(unsigned int phy)
+{
+	unsigned int mask;
+
+	if (phy == 0) {
+		g_vpp.stream_mb_lock = 0;
+		g_vpp.stream_mb_index = 0;
+		return 0;
+	}
+
+	mask = vpp_mb_get_mask(phy);
+	if (mask == 0) {
+		DPRINT("[VPP] *W* mb_put addr 0x%x\n", phy);
+		return 1;
+	}
+	if (!(g_vpp.stream_mb_lock & mask))
+		DPRINT("[VPP] *W* mb_put nonlock addr 0x%x\n", phy);
+	g_vpp.stream_mb_lock &= ~mask;
+	if (vpp_check_dbg_level(VPP_DBGLVL_STREAM)) {
+		char buf[50];
+
+		sprintf(buf, "stream mb put 0x%x,mask 0x%x(0x%x)",
+			phy, mask, g_vpp.stream_mb_lock);
+		vpp_dbg_show(VPP_DBGLVL_STREAM, 2, buf);
+	}
+	return 0;
+}
+
+int vpp_mb_irqproc_sync(int arg)
+{
+	if (!g_vpp.stream_enable)
+		return 0;
+
+	g_vpp.stream_sync_cnt++;
+	if ((g_vpp.stream_sync_cnt % 2) == 0) {
+		g_vpp.stream_mb_sync_flag = 0;
+#ifdef CONFIG_VPP_STREAM_BLOCK
+		wake_up_interruptible(&vpp_mb_event);
+#endif
+	}
+	return 0;
+}
+
+/*----------------------- irq proc --------------------------------------*/
+struct vpp_irqproc_t *vpp_irqproc_array[32];
+struct list_head vpp_irqproc_free_list;
+struct vpp_proc_t vpp_proc_array[VPP_PROC_NUM];
+static void vpp_irqproc_do_tasklet(unsigned long data);
+
+void vpp_irqproc_init(void)
+{
+	int i;
+
+	INIT_LIST_HEAD(&vpp_irqproc_free_list);
+
+	for (i = 0; i < VPP_PROC_NUM; i++)
+		list_add_tail(&vpp_proc_array[i].list, &vpp_irqproc_free_list);
+}
+
+struct vpp_irqproc_t *vpp_irqproc_get_entry(enum vpp_int_t vpp_int)
+{
+	int no;
+
+	if (vpp_int == 0)
+		return 0;
+
+	for (no = 0; no < 32; no++) {
+		if (vpp_int & (0x1 << no))
+			break;
+	}
+
+	if (vpp_irqproc_array[no] == 0) { /* will create in first use */
+		struct vpp_irqproc_t *irqproc;
+
+		irqproc = kmalloc(sizeof(struct vpp_irqproc_t), GFP_KERNEL);
+		vpp_irqproc_array[no] = irqproc;
+		INIT_LIST_HEAD(&irqproc->list);
+		tasklet_init(&irqproc->tasklet,
+			vpp_irqproc_do_tasklet, vpp_int);
+		irqproc->ref = 0;
+	}
+	return vpp_irqproc_array[no];
+} /* End of vpp_irqproc_get_entry */
+
+void vpp_irqproc_set_ref(struct vpp_irqproc_t *irqproc,
+				enum vpp_int_t type, int enable)
+{
+	if (enable) {
+		irqproc->ref++;
+		if (vppm_get_int_enable(type) == 0)
+			vppm_set_int_enable(1, type);
+	} else {
+		irqproc->ref--;
+		if (irqproc->ref == 0)
+			vppm_set_int_enable(0, type);
+	}
+}
+
+static void vpp_irqproc_do_tasklet
+(
+	unsigned long data		/*!<; // tasklet input data */
+)
+{
+	struct vpp_irqproc_t *irqproc;
+
+	vpp_lock();
+	irqproc = vpp_irqproc_get_entry(data);
+	if (irqproc) {
+		struct list_head *cur;
+		struct list_head *next;
+		struct vpp_proc_t *entry;
+
+		next = (&irqproc->list)->next;
+		while (next != &irqproc->list) {
+			cur = next;
+			next = cur->next;
+			entry = list_entry(cur, struct vpp_proc_t, list);
+			if (entry->func) {
+				if (entry->func(entry->arg))
+					continue;
+			}
+
+			if (entry->work_cnt == 0)
+				continue;
+
+			entry->work_cnt--;
+			if (entry->work_cnt == 0) {
+				if (entry->wait_ms == 0)
+					vpp_irqproc_set_ref(irqproc, data, 0);
+				else
+					up(&entry->sem);
+				list_del_init(cur);
+				list_add_tail(&entry->list,
+					&vpp_irqproc_free_list);
+			}
+		}
+	}
+	vpp_unlock();
+} /* End of vpp_irqproc_do_tasklet */
+
+int vpp_irqproc_work(
+	enum vpp_int_t type,		/* interrupt type */
+	int (*func)(void *argc),    /* proc function pointer */
+	void *arg,                  /* proc argument */
+	int wait_ms,                /* wait complete timeout (ms) */
+	int work_cnt                /* 0 - forever */
+)
+{
+	int ret;
+	struct vpp_proc_t *entry;
+	struct list_head *ptr;
+	struct vpp_irqproc_t *irqproc;
+
+#if 0
+	DPRINT("[VPP] vpp_irqproc_work(type 0x%x,wait %d,cnt %d)\n",
+		type, wait_ms, work_cnt);
+#endif
+	if ((vpp_irqproc_free_list.next == 0) ||
+		list_empty(&vpp_irqproc_free_list)) {
+		if (func)
+			func(arg);
+		return 0;
+	}
+
+	ret = 0;
+	vpp_lock();
+
+	ptr = vpp_irqproc_free_list.next;
+	entry = list_entry(ptr, struct vpp_proc_t, list);
+	list_del_init(ptr);
+	entry->func = func;
+	entry->arg = arg;
+	entry->type = type;
+	entry->wait_ms = wait_ms;
+	entry->work_cnt = work_cnt;
+	sema_init(&entry->sem, 1);
+	down(&entry->sem);
+
+	irqproc = vpp_irqproc_get_entry(type);
+	if (irqproc) {
+		list_add_tail(&entry->list, &irqproc->list);
+	} else {
+		irqproc = vpp_irqproc_array[31];
+		list_add_tail(&entry->list, &irqproc->list);
+	}
+	vpp_irqproc_set_ref(irqproc, type, 1);
+	vpp_unlock();
+
+	if (wait_ms) {
+		unsigned int tmr_cnt;
+
+		tmr_cnt = (wait_ms * HZ) / 1000;
+		ret = down_timeout(&entry->sem, tmr_cnt);
+		if (ret) {
+			DPRINT("*W* vpp_irqproc_work timeout(type 0x%x,%d)\n",
+				type, wait_ms);
+			vpp_lock();
+			list_del_init(ptr);
+			list_add_tail(ptr, &vpp_irqproc_free_list);
+			vpp_unlock();
+			if (func)
+				func(arg);
+		}
+	}
+
+	if ((work_cnt == 0) || (wait_ms == 0)) {
+		/* don't clear ref, forever will do in delete,
+		no wait will do in proc complete */
+	} else {
+		vpp_lock();
+		vpp_irqproc_set_ref(irqproc, type, 0);
+		vpp_unlock();
+	}
+	return ret;
+} /* End of vpp_irqproc_work */
+
+void vpp_irqproc_del_work(
+	enum vpp_int_t type,	/* interrupt type */
+	int (*func)(void *argc)	/* proc function pointer */
+)
+{
+	struct vpp_irqproc_t *irqproc;
+
+	vpp_lock();
+	irqproc = vpp_irqproc_get_entry(type);
+	if (irqproc) {
+		struct list_head *cur;
+		struct list_head *next;
+		struct vpp_proc_t *entry;
+
+		next = (&irqproc->list)->next;
+		while (next != &irqproc->list) {
+			cur = next;
+			next = cur->next;
+			entry = list_entry(cur, struct vpp_proc_t, list);
+			if (entry->func == func) {
+				vpp_irqproc_set_ref(irqproc, type, 0);
+				list_del_init(cur);
+				list_add_tail(&entry->list,
+					&vpp_irqproc_free_list);
+			}
+		}
+	}
+	vpp_unlock();
+}
+
+/*----------------------- Linux Netlink --------------------------------------*/
+#ifdef CONFIG_VPP_NOTIFY
+#define VPP_NETLINK_PROC_MAX	2
+
+struct vpp_netlink_proc_t {
+	__u32 pid;
+	rwlock_t lock;
+};
+
+struct switch_dev vpp_sdev = {
+	.name = "hdmi",
+};
+
+static struct switch_dev vpp_sdev_hdcp = {
+	.name = "hdcp",
+};
+
+static struct switch_dev vpp_sdev_audio = {
+	.name = "hdmi_audio",
+};
+
+struct vpp_netlink_proc_t vpp_netlink_proc[VPP_NETLINK_PROC_MAX];
+static struct sock *vpp_nlfd;
+static DEFINE_SEMAPHORE(vpp_netlink_receive_sem);
+
+struct vpp_netlink_proc_t *vpp_netlink_get_proc(int no)
+{
+	if (no == 0)
+		return 0;
+	if (no > VPP_NETLINK_PROC_MAX)
+		return 0;
+	return &vpp_netlink_proc[no - 1];
+}
+
+static void vpp_netlink_receive(struct sk_buff *skb)
+{
+	struct nlmsghdr *nlh = NULL;
+	struct vpp_netlink_proc_t *proc;
+
+	if (down_trylock(&vpp_netlink_receive_sem))
+		return;
+
+	if (skb->len >= sizeof(struct nlmsghdr)) {
+		nlh = nlmsg_hdr(skb);
+		if ((nlh->nlmsg_len >= sizeof(struct nlmsghdr))
+			&& (skb->len >= nlh->nlmsg_len)) {
+			proc = vpp_netlink_get_proc(nlh->nlmsg_type);
+			if (proc) {
+				write_lock_bh(&proc->lock);
+				proc->pid = nlh->nlmsg_pid;
+				write_unlock_bh(&proc->lock);
+				DPRINT("[VPP] rx user pid 0x%x\n", proc->pid);
+			}
+		}
+	}
+	up(&vpp_netlink_receive_sem);
+	wmt_enable_mmfreq(WMT_MMFREQ_HDMI_PLUG, hdmi_get_plugin());
+}
+
+void vpp_netlink_init(void)
+{
+	vpp_netlink_proc[0].pid = 0;
+	vpp_netlink_proc[1].pid = 0;
+	rwlock_init(&(vpp_netlink_proc[0].lock));
+	rwlock_init(&(vpp_netlink_proc[1].lock));
+	vpp_nlfd = netlink_kernel_create(&init_net, NETLINK_CEC_TEST, 0,
+		vpp_netlink_receive, NULL, THIS_MODULE);
+	if (!vpp_nlfd)
+		DPRINT(KERN_ERR "can not create a netlink socket\n");
+}
+
+static ssize_t attr_show_parsed_edid(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	ssize_t len = 0;
+	int i, j;
+	unsigned char audio_format, sample_freq, bitrate;
+	int sample_freq_num, bitrate_num;
+
+#ifdef DEBUG
+	DPRINT("------- EDID Parsed ------\n");
+	if(strlen(edid_parsed.tv_name.vendor_name) != 0)
+		DPRINT("Vendor Name: %s\n", edid_parsed.tv_name.vendor_name);
+
+	if(strlen(edid_parsed.tv_name.monitor_name) != 0)
+		DPRINT("Monitor Name: %s\n", edid_parsed.tv_name.monitor_name);
+
+	for (i = 0; i < AUD_SAD_NUM; i++) {
+		if (edid_parsed.sad[i].flag == 0) {
+			if (i == 0)
+				DPRINT("No SAD Data\n");
+			break;
+		}
+		DPRINT("SAD %d: 0x%02X 0x%02X 0x%02X\n", i,
+			edid_parsed.sad[i].sad_byte[0],
+			edid_parsed.sad[i].sad_byte[1],
+			edid_parsed.sad[i].sad_byte[2]);
+	}
+	DPRINT("--------------------------\n");
+#endif
+	/* print Vendor Name */
+	if (strlen(edid_parsed.tv_name.vendor_name) != 0) {
+		len += sprintf(buf + len, "%-16s", "Vendor Name");
+		len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.vendor_name);
+	}
+
+	/* print Monitor Name */
+	if (strlen(edid_parsed.tv_name.monitor_name) != 0) {
+		len += sprintf(buf + len, "%-16s", "Monitor Name");
+		len += sprintf(buf + len, ": %s\n", edid_parsed.tv_name.monitor_name);
+	}
+
+	for (i = 0; i < AUD_SAD_NUM; i++) {
+		if (edid_parsed.sad[i].flag == 0)
+			break;
+		/*
+		SAD Byte 1 (format and number of channels):
+		bit 7: Reserved (0)
+		bit 6..3: Audio format code
+		1 = Linear Pulse Code Modulation (LPCM)
+		2 = AC-3
+		3 = MPEG1 (Layers 1 and 2)
+		4 = MP3
+		5 = MPEG2
+		6 = AAC
+		7 = DTS
+		8 = ATRAC
+		0, 15: Reserved
+		9 = One-bit audio aka SACD
+		10 = DD+
+		11 = DTS-HD
+		12 = MLP/Dolby TrueHD
+		13 = DST Audio
+		14 = Microsoft WMA Pro
+		bit 2..0: number of channels minus 1
+		(i.e. 000 = 1 channel; 001 = 2 channels; 111 =
+		     8 channels)
+		*/
+		audio_format = (edid_parsed.sad[i].sad_byte[0] & 0x78) >> 3;
+		if (audio_format == 0 || audio_format == 15)
+			continue;
+
+		/* print header */
+		len += sprintf(buf + len, "%-16s", "Audio Format");
+		len += sprintf(buf + len, ": ");
+
+		switch (audio_format) {
+		case 1:
+			len += sprintf(buf + len, "pcm");
+			break;
+		case 2:
+			len += sprintf(buf + len, "ac3");
+			break;
+		case 3:
+			len += sprintf(buf + len, "mpeg1");
+			break;
+		case 4:
+			len += sprintf(buf + len, "mp3");
+			break;
+		case 5:
+			len += sprintf(buf + len, "mpeg2");
+			break;
+		case 6:
+			len += sprintf(buf + len, "aac");
+			break;
+		case 7:
+			len += sprintf(buf + len, "dts");
+			break;
+		case 8:
+			len += sprintf(buf + len, "atrac");
+			break;
+		case 9:
+			len += sprintf(buf + len, "one_bit_audio");
+			break;
+		case 10:
+			len += sprintf(buf + len, "eac3");
+			break;
+		case 11:
+			len += sprintf(buf + len, "dts-hd");
+			break;
+		case 12:
+			len += sprintf(buf + len, "mlp");
+			break;
+		case 13:
+			len += sprintf(buf + len, "dst");
+			break;
+		case 14:
+			len += sprintf(buf + len, "wmapro");
+			break;
+		default:
+			break;
+		}
+
+		/* separator */
+		len += sprintf(buf + len, ",");
+
+		/* number of channels */
+		len += sprintf(buf + len, "%d",
+			(edid_parsed.sad[i].sad_byte[0] & 0x7) + 1);
+
+		/* separator */
+		len += sprintf(buf + len, ",");
+
+		/*
+		SAD Byte 2 (sampling frequencies supported):
+		   bit 7: Reserved (0)
+		   bit 6: 192kHz
+		   bit 5: 176kHz
+		   bit 4: 96kHz
+		   bit 3: 88kHz
+		   bit 2: 48kHz
+		   bit 1: 44kHz
+		   bit 0: 32kHz
+		*/
+		sample_freq = edid_parsed.sad[i].sad_byte[1];
+		sample_freq_num = 0;
+		for (j = 0; j < 7; j++) {
+			if (sample_freq & (1 << j)) {
+				if (sample_freq_num != 0)
+					len += sprintf(buf + len,
+					"|"); /* separator */
+				switch (j) {
+				case 0:
+					len += sprintf(buf + len, "32KHz");
+					break;
+				case 1:
+					len += sprintf(buf + len, "44KHz");
+					break;
+				case 2:
+					len += sprintf(buf + len, "48KHz");
+					break;
+				case 3:
+					len += sprintf(buf + len, "88KHz");
+					break;
+				case 4:
+					len += sprintf(buf + len, "96KHz");
+					break;
+				case 5:
+					len += sprintf(buf + len, "176KHz");
+					break;
+				case 6:
+					len += sprintf(buf + len, "192KHz");
+					break;
+				default:
+					break;
+				}
+				sample_freq_num++;
+			}
+		}
+
+		if (sample_freq_num == 0)
+			len += sprintf(buf + len, "0");
+
+		/* separator */
+		len += sprintf(buf + len, ",");
+
+		/*
+		SAD Byte 3 (bitrate):
+		For LPCM, bits 7:3 are reserved and the remaining bits
+		define bit depth
+		bit 2: 24 bit
+		bit 1: 20 bit
+		bit 0: 16 bit
+		For all other sound formats, bits 7..0 designate the maximum
+		supported bitrate divided by 8 kbit/s.
+		*/
+		bitrate = edid_parsed.sad[i].sad_byte[2];
+		bitrate_num = 0;
+		if (audio_format == 1) { /* for LPCM */
+			for (j = 0; j < 3; j++) {
+				if (bitrate & (1 << j)) {
+					if (bitrate_num != 0)
+						len += sprintf(buf + len,
+						"|"); /* separator */
+					switch (j) {
+					case 0:
+						len += sprintf(buf + len,
+							"16bit");
+						break;
+					case 1:
+						len += sprintf(buf + len,
+							"20bit");
+						break;
+					case 2:
+						len += sprintf(buf + len,
+							"24bit");
+						break;
+					default:
+						break;
+					}
+					bitrate_num++;
+				}
+			}
+		} else if (audio_format >= 2 &&
+				audio_format <= 8) /* From AC3 to ATRAC */
+			len += sprintf(buf + len, "%dkbps", bitrate * 8);
+		else /* From One-bit-audio to WMA Pro*/
+			len += sprintf(buf + len, "%d", bitrate);
+
+		len += sprintf(buf + len, "\n");
+	}
+
+	if (len == 0)
+		len += sprintf(buf + len, "\n");
+
+	return len;
+}
+
+static DEVICE_ATTR(edid_parsed, 0444, attr_show_parsed_edid, NULL);
+
+void vpp_switch_state_init(void)
+{
+	/* /sys/class/switch/hdmi/state */
+	switch_dev_register(&vpp_sdev);
+	switch_set_state(&vpp_sdev, hdmi_get_plugin() ? 1 : 0);
+	switch_dev_register(&vpp_sdev_hdcp);
+	switch_set_state(&vpp_sdev_hdcp, 0);
+	switch_dev_register(&vpp_sdev_audio);
+	device_create_file(vpp_sdev.dev, &dev_attr_edid_parsed);
+}
+
+void vpp_netlink_notify(int no, int cmd, int arg)
+{
+	int ret;
+	int size;
+	unsigned char *old_tail;
+	struct sk_buff *skb;
+	struct nlmsghdr *nlh;
+	struct vpp_netlink_proc_t *proc;
+
+	proc = vpp_netlink_get_proc(no);
+	if (!proc)
+		return;
+
+	MSG("[VPP] netlink notify %d,cmd %d,0x%x\n", no, cmd, arg);
+
+	switch (cmd) {
+	case DEVICE_RX_DATA:
+		size = NLMSG_SPACE(sizeof(struct wmt_cec_msg));
+		break;
+	case DEVICE_PLUG_IN:
+	case DEVICE_PLUG_OUT:
+	case DEVICE_STREAM:
+		size = NLMSG_SPACE(sizeof(struct wmt_cec_msg));
+		break;
+	default:
+		return;
+	}
+
+	skb = alloc_skb(size, GFP_ATOMIC);
+	if (skb == NULL)
+		return;
+	old_tail = skb->tail;
+	nlh = NLMSG_PUT(skb, 0, 0, 0, size-sizeof(*nlh));
+	nlh->nlmsg_len = skb->tail - old_tail;
+
+	switch (cmd) {
+	case DEVICE_RX_DATA:
+		nlh->nlmsg_type = DEVICE_RX_DATA;
+		memcpy(NLMSG_DATA(nlh), (struct wmt_cec_msg *)arg,
+			sizeof(struct wmt_cec_msg));
+		break;
+	case DEVICE_PLUG_IN:
+	case DEVICE_PLUG_OUT:
+		{
+			static int cnt;
+			struct wmt_cec_msg *msg;
+
+			msg = (struct wmt_cec_msg *)NLMSG_DATA(nlh);
+			msg->msgdata[0] = cnt;
+			cnt++;
+		}
+		if (arg) {
+			nlh->nlmsg_type = DEVICE_PLUG_IN;
+			nlh->nlmsg_flags = edid_get_hdmi_phy_addr();
+		} else {
+			nlh->nlmsg_type = DEVICE_PLUG_OUT;
+		}
+		size = NLMSG_SPACE(sizeof(0));
+		break;
+	case DEVICE_STREAM:
+		nlh->nlmsg_type = cmd;
+		nlh->nlmsg_flags = arg;
+		break;
+	default:
+		return;
+	}
+
+	NETLINK_CB(skb).pid = 0;
+	NETLINK_CB(skb).dst_group = 0;
+
+	if (proc->pid != 0) {
+		ret = netlink_unicast(vpp_nlfd, skb, proc->pid, MSG_DONTWAIT);
+		return;
+	}
+nlmsg_failure: /* NLMSG_PUT go to */
+	if (skb != NULL)
+		kfree_skb(skb);
+	return;
+}
+
+void vpp_netlink_notify_plug(int vo_num, int plugin)
+{
+	/* set unplug flag for check_var */
+	if (plugin == 0) {
+		int mask = 0;
+
+		if (vo_num == VPP_VOUT_ALL)
+			mask = ~0;
+		else {
+			struct vout_info_t *vo_info;
+			vo_info = vout_get_info_entry(vo_num);
+			if (vo_info)
+				mask = 0x1 << (vo_info->num);
+		}
+		g_vpp.fb_recheck |= mask;
+	}
+
+	if ((vpp_netlink_proc[0].pid == 0) && (vpp_netlink_proc[1].pid == 0))
+		return;
+
+	/* if hdmi unplug, clear edid_parsed */
+	if (hdmi_get_plugin() == 0)
+		memset(&edid_parsed, 0, sizeof(struct edid_parsed_t));
+
+	vpp_netlink_notify(USER_PID, DEVICE_PLUG_IN, plugin);
+	vpp_netlink_notify(WP_PID, DEVICE_PLUG_IN, plugin);
+
+	/* hdmi plugin/unplug */
+	plugin = hdmi_get_plugin();
+	switch_set_state(&vpp_sdev, plugin ? 1 : 0);
+	wmt_enable_mmfreq(WMT_MMFREQ_HDMI_PLUG, plugin);
+}
+
+void vpp_netlink_notify_cp(int enable)
+{
+	switch_set_state(&vpp_sdev_hdcp, enable);
+}
+EXPORT_SYMBOL(vpp_netlink_notify_cp);
+
+#endif /* CONFIG_VPP_NOTIFY */
+#endif /* __KERNEL__ */
diff --git a/drivers/video/wmt/vpp.h b/drivers/video/wmt/vpp.h
new file mode 100755
index 00000000..b35f8db1
--- /dev/null
+++ b/drivers/video/wmt/vpp.h
@@ -0,0 +1,679 @@
+/*++
+ * linux/drivers/video/wmt/vpp.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp-osif.h"
+#include "./hw/wmt-vpp-hw.h"
+#include "com-vpp.h"
+#ifdef CONFIG_KERNEL
+#include "com-cec.h"
+#endif
+#include "vout.h"
+
+#ifndef VPP_H
+#define VPP_H
+
+#define CONFIG_VPP_SHENZHEN  /* for ShenZhen code */
+
+/* VPP feature config */
+/* #define CONFIG_VPP_DEMO */ /* HDMI EDID, CP disable */
+#ifdef CONFIG_KERNEL
+#define CONFIG_VPP_STREAM_CAPTURE /* stream capture current video display */
+#define CONFIG_VPP_STREAM_BLOCK
+/* #define CONFIG_VPP_DISABLE_PM */ /* disable power management */
+#define CONFIG_VPP_VIRTUAL_DISPLAY /* virtual fb dev */
+#define CONFIG_VPP_NOTIFY
+#endif
+/* #define CONFIG_VPP_DYNAMIC_ALLOC */ /* frame buffer dynamic allocate */
+
+/* VPP constant define */
+#define VPP_MB_ALLOC_NUM 3
+#define VPP_STREAM_MB_ALLOC_NUM (VPP_MB_ALLOC_NUM * 2)
+
+enum vpp_int_t {
+	VPP_INT_NULL = 0,
+	VPP_INT_ALL = 0xffffffff,
+
+	VPP_INT_GOVRH_PVBI = BIT0,
+	VPP_INT_GOVRH_VBIS = BIT1,	/* write done */
+	VPP_INT_GOVRH_VBIE = BIT2,
+
+	VPP_INT_GOVW_PVBI = BIT3,
+	VPP_INT_GOVW_VBIS = BIT4,
+	VPP_INT_GOVW_VBIE = BIT5,
+
+	VPP_INT_DISP_PVBI = BIT6,
+	VPP_INT_DISP_VBIS = BIT7,
+	VPP_INT_DISP_VBIE = BIT8,
+
+	VPP_INT_LCD_EOF = BIT9,
+
+	VPP_INT_SCL_PVBI = BIT12,
+	VPP_INT_SCL_VBIS = BIT13,
+	VPP_INT_SCL_VBIE = BIT14,
+
+	VPP_INT_VPU_PVBI = BIT15,
+	VPP_INT_VPU_VBIS = BIT16,
+	VPP_INT_VPU_VBIE = BIT17,
+
+	VPP_INT_GOVRH2_PVBI = BIT18,
+	VPP_INT_GOVRH2_VBIS = BIT19,	/* write done */
+	VPP_INT_GOVRH2_VBIE = BIT20,
+
+	VPP_INT_MAX = BIT31,
+
+};
+
+enum vpp_int_err_t {
+	/* SCL */
+	VPP_INT_ERR_SCL_TG = BIT0,
+	VPP_INT_ERR_SCLR1_MIF = BIT1,
+	VPP_INT_ERR_SCLR2_MIF = BIT2,
+	VPP_INT_ERR_SCLW_MIFRGB = BIT3,
+	VPP_INT_ERR_SCLW_MIFY = BIT4,
+	VPP_INT_ERR_SCLW_MIFC = BIT5,
+
+	/* GOVRH2 */
+	VPP_INT_ERR_GOVRH2_MIF = BIT19,
+
+	/* GOVRH */
+	VPP_INT_ERR_GOVRH_MIF = BIT20,
+
+};
+
+/* VPP FB capability flag */
+#define VPP_FB_FLAG_COLFMT		0xFFFF
+#define VPP_FB_FLAG_SCALE		BIT(16)
+#define VPP_FB_FLAG_CSC			BIT(17)
+#define VPP_FB_FLAG_MEDIA		BIT(18)
+#define VPP_FB_FLAG_FIELD		BIT(19)
+
+struct vpp_fb_base_t {
+	vdo_framebuf_t fb;
+	vpp_csc_t csc_mode;
+	int framerate;
+	vpp_media_format_t media_fmt;
+	int wait_ready;
+	unsigned int capability;
+
+	void (*set_framebuf)(vdo_framebuf_t *fb);
+	void (*get_framebuf)(vdo_framebuf_t *fb);
+	void (*set_addr)(unsigned int yaddr, unsigned int caddr);
+	void (*get_addr)(unsigned int *yaddr, unsigned int *caddr);
+	void (*set_csc)(vpp_csc_t mode);
+	vdo_color_fmt(*get_color_fmt)(void);
+	void (*set_color_fmt)(vdo_color_fmt colfmt);
+	void (*fn_view)(int read, vdo_view_t *view);
+};
+
+#define VPP_MOD_BASE \
+	vpp_mod_t mod; /* module id*/\
+	void *mmio;	/* regs base address */\
+	unsigned int int_catch; /* interrupt catch */\
+	struct vpp_fb_base_t *fb_p; /* framebuf base pointer */\
+	unsigned int pm; /* power dev id,bit31-0:power off */\
+	unsigned int *reg_bk; /* register backup pointer */\
+	void  (*init)(void *base); /* module initial */\
+	void (*dump_reg)(void); /* dump hardware register */\
+	void (*set_enable)(vpp_flag_t enable); /* module enable/disable */\
+	void (*set_colorbar)(vpp_flag_t enable, int mode, int inv); \
+		/* hw colorbar enable/disable & mode */\
+	void (*set_tg)(vpp_clock_t *tmr, unsigned int pixel_clock); /*set tg*/\
+	void (*get_tg)(vpp_clock_t *tmr); /* get timing */\
+	unsigned int (*get_sts)(void); /* get interrupt or error status */\
+	void (*clr_sts)(unsigned int sts); /* clear interrupt or err status */\
+	void (*suspend)(int sts); /* module suspend */\
+	void (*resume)(int sts) /* module resume */
+/* End of vpp_mod_base_t */
+
+struct vpp_mod_base_t {
+	VPP_MOD_BASE;
+};
+
+#define VPP_MOD_FLAG_FRAMEBUF	BIT(0)
+#define VPP_MOD_CLK_ON		BIT(31)
+
+enum vpp_scale_mode_t {
+	VPP_SCALE_MODE_REC_TABLE, /* old design but 1/32 limit */
+	VPP_SCALE_MODE_RECURSIVE, /*no rec table,not smooth than bilinear mode*/
+	VPP_SCALE_MODE_BILINEAR,/*more smooth but less than 1/2 will drop line*/
+	VPP_SCALE_MODE_ADAPTIVE,/* scl dn 1-1/2 bilinear mode, other rec mode */
+	VPP_SCALE_MODE_MAX
+};
+
+enum vpp_hdmi_audio_inf_t {
+	VPP_HDMI_AUDIO_I2S,
+	VPP_HDMI_AUDIO_SPDIF,
+	VPP_HDMI_AUDIO_MAX
+};
+
+enum vpp_filter_mode_t {
+	VPP_FILTER_SCALE,
+	VPP_FILTER_DEBLOCK,
+	VPP_FILTER_FIELD_DEFLICKER,
+	VPP_FILTER_FRAME_DEFLICKER,
+	VPP_FILTER_MODE_MAX
+};
+
+#define VPP_DBG_PERIOD_NUM	10
+struct vpp_dbg_period_t {
+	int index;
+	int period_us[VPP_DBG_PERIOD_NUM];
+	struct timeval pre_tv;
+};
+
+struct vpp_dbg_timer_t {
+	struct timeval pre_tv;
+	unsigned int threshold;
+	unsigned int reset;
+	unsigned int cnt;
+	unsigned int sum;
+	unsigned int min;
+	unsigned int max;
+};
+
+#ifdef __KERNEL__
+#define VPP_PROC_NUM		10
+struct vpp_proc_t {
+	int (*func)(void *arg); /* function pointer */
+	void *arg; /* function argument */
+	struct list_head list;
+	enum vpp_int_t type; /* interrupt type */
+	struct semaphore sem; /* wait sem */
+	int wait_ms; /* wait complete timout (ms) */
+	int work_cnt; /* work counter if 0 then forever */
+};
+
+struct vpp_irqproc_t {
+	struct list_head list;
+	struct tasklet_struct tasklet;
+	int ref;
+};
+#endif
+
+#ifndef CFG_LOADER
+#include "vppm.h"
+#endif
+#include "lcd.h"
+
+/* #ifdef WMT_FTBLK_SCL */
+#include "scl.h"
+/* #endif */
+/*
+#ifdef WMT_FTBLK_GE
+#include "ge.h"
+#endif
+*/
+#ifdef WMT_FTBLK_GOVRH
+#include "govrh.h"
+#endif
+#ifdef WMT_FTBLK_LVDS
+#include "lvds.h"
+#endif
+/* #ifdef WMT_FTBLK_HDMI */
+#include "hdmi.h"
+#ifndef CFG_LOADER
+#include "cec.h"
+#endif
+/* #endif */
+#ifdef CONFIG_WMT_EDID
+#include "edid.h"
+#endif
+
+enum vpp_dbg_level_t {
+	VPP_DBGLVL_DISABLE = 0x0,
+	VPP_DBGLVL_SCALE = 1,
+	VPP_DBGLVL_DISPFB = 2,
+	VPP_DBGLVL_INT = 3,
+	VPP_DBGLVL_FPS = 4,
+	VPP_DBGLVL_IOCTL = 5,
+	VPP_DBGLVL_DIAG = 6,
+	VPP_DBGLVL_STREAM = 7,
+	VPP_DBGLVL_ALL = 0xFF,
+};
+
+struct vpp_info_t {
+	/* internal parameter */
+	int govrh_preinit;
+	int virtual_display;
+	int fb0_bitblit;
+	int fb_manual; /* not check var & internel timing */
+	int fb_recheck; /* recheck for plug but no change res */
+	int govrh_init_yres;
+	int stream_fb;
+
+	/* hdmi */
+	enum vpp_hdmi_audio_inf_t hdmi_audio_interface; /* 0-I2S, 1-SPDIF */
+	int hdmi_cp_enable; /* 0-off, 1-on */
+	int hdmi_audio_channel;
+	int hdmi_audio_freq;
+	unsigned int hdmi_ctrl;
+	unsigned int hdmi_audio_pb1;
+	unsigned int hdmi_audio_pb4;
+	unsigned int hdmi_i2c_freq;
+	unsigned int hdmi_i2c_udelay;
+	int hdmi_init;
+	unsigned int hdmi_bksv[2];
+	char *hdmi_cp_p;
+	int hdmi_3d_type;
+	unsigned int hdmi_pixel_clock;
+	int hdmi_certify_flag;
+	int hdmi_sp_mode;
+	int hdmi_disable;
+	int hdmi_ch_change;
+
+	/* alloc frame buffer */
+	int mb_colfmt;
+
+	/* debug */
+	int dbg_msg_level; /* debug message level */
+	int dbg_wait;
+	int dbg_flag;
+
+	/* dvi */
+	int dvi_int_disable;
+	int dvi_int_no; /* DVO external board interrupt use GPIOxx */
+	int dvi_i2c_no; /* DVO external board i2c bus id */
+
+#if 0
+	/* HDMI DDC debug */
+	int dbg_hdmi_ddc_ctrl_err;
+	int dbg_hdmi_ddc_read_err;
+	int dbg_hdmi_ddc_crc_err;
+#endif
+
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+	/* stream capture current video display */
+	int stream_enable;
+	unsigned int stream_mb_lock;
+	int stream_mb_sync_flag;
+	int stream_mb_index;
+	unsigned int stream_mb[VPP_STREAM_MB_ALLOC_NUM];
+	int stream_mb_cnt;
+	unsigned int stream_sync_cnt;
+#endif
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef VPP_C
+#define EXTERN
+
+const unsigned int vpp_csc_parm[VPP_CSC_MAX][7] = {
+	/* C1,C2        C3,C4       C5,C6       C7,C8       C9,I
+	J,K      b0:YC2RGB,b8:clamp */
+	{0x000004a8, 0x04a80662, 0x1cbf1e70, 0x081204a8, 0x00010000,
+	0x00010001, 0x00000101}, /* YUV2RGB_SDTV_0_255 */
+	{0x00000400, 0x0400057c, 0x1d351ea8, 0x06ee0400, 0x00010000,
+	0x00010001, 0x00000001}, /* YUV2RGB_SDTV_16_235 */
+	{0x000004a8, 0x04a8072c, 0x1ddd1f26, 0x087604a8, 0x00010000,
+	0x00010001, 0x00000101}, /* YUV2RGB_HDTV_0_255 */
+	{0x00000400, 0x04000629, 0x1e2a1f45, 0x07440400, 0x00010000,
+	0x00010001, 0x00000001}, /* YUV2RGB_HDTV_16_235 */
+	{0x00000400, 0x0400059c, 0x1d251ea0, 0x07170400, 0x00010000,
+	0x00010001, 0x00000001}, /* YUV2RGB_JFIF_0_255 */
+	{0x00000400, 0x0400057c, 0x1d351ea8, 0x06ee0400, 0x00010000,
+	0x00010001, 0x00000001}, /* YUV2RGB_SMPTE170M */
+	{0x00000400, 0x0400064d, 0x1e001f19, 0x074f0400, 0x00010000,
+	0x00010001, 0x00000001}, /* YUV2RGB_SMPTE240M */
+	{0x02040107, 0x1f680064, 0x01c21ed6, 0x1e8701c2, 0x00211fb7,
+	0x01010101, 0x00000000}, /* RGB2YUV_SDTV_0_255 */
+	{0x02590132, 0x1f500075, 0x020b1ea5, 0x1e4a020b, 0x00011fab,
+	0x01010101, 0x00000000}, /* RGB2YUV_SDTV_16_235 */
+	{0x027500bb, 0x1f99003f, 0x01c21ea6, 0x1e6701c2, 0x00211fd7,
+	0x01010101, 0x00000000}, /* RGB2YUV_HDTV_0_255 */
+	{0x02dc00da, 0x1f88004a, 0x020b1e6d, 0x1e25020b, 0x00011fd0,
+	0x01010101, 0x00000000}, /* RGB2YUV_HDTV_16_235 */
+	{0x02590132, 0x1f530075, 0x02001ead, 0x1e530200, 0x00011fad,
+	0x01010101, 0x00000000}, /* RGB2YUV_JFIF_0_255 */
+	{0x02590132, 0x1f500075, 0x020b1ea5, 0x1e4a020b, 0x00011fab,
+	0x01010101, 0x00000000}, /* RGB2YUV_SMPTE170M */
+	{0x02ce00d9, 0x1f890059, 0x02001e77, 0x1e380200, 0x00011fc8,
+	0x01010101, 0x00000000}, /* RGB2YUV_SMPTE240M */
+	{0x02780142, 0x1e80007a, 0x04711d0e, 0x1c470471, 0x00001f46,
+	0x01010101, 0x00000000} /* RGB2YUV_JFIF_VT1625 */
+};
+
+const struct fb_videomode vpp_videomode[] = {
+	/* 640x480@60 DMT/CEA861 */
+	{ NULL, 60, 640, 480, KHZ2PICOS(25175), 48, 16, 33, 10, 96, 2,
+	  0, FB_VMODE_NONINTERLACED, 0},
+#if 0
+	/* 640x480@60 CVT */
+	{ NULL, 60, 640, 480, KHZ2PICOS(23750), 80, 16, 13, 3, 64, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 640x480@75 DMT */
+	{ NULL, 75, 640, 480, KHZ2PICOS(31500), 120, 16, 16, 1, 64, 3,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 640x480@75 CVT */
+	{ NULL, 75, 640, 480, KHZ2PICOS(30750), 88, 24, 17, 3, 64, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 720x480@60 CEA861 */
+	{ NULL, 60, 720, 480, KHZ2PICOS(27027), 60, 16, 30, 9, 62, 6,
+	  0, FB_VMODE_NONINTERLACED, 0},
+	/* 720x480i@60 CEA861 */
+	{ NULL, 60, 720, 480, KHZ2PICOS(27000), 114, 38, 30, 8, 124, 6,
+	  0, FB_VMODE_INTERLACED + FB_VMODE_DOUBLE, 0},
+	/* 720x576@50 CEA861 */
+	{ NULL, 50, 720, 576, KHZ2PICOS(27000), 68, 12, 39, 5, 64, 5,
+	  0, FB_VMODE_NONINTERLACED, 0},
+	/* 720x576i@50 CEA861 */
+	{ NULL, 50, 720, 576, KHZ2PICOS(27000), 138, 24, 38, 4, 126, 6,
+	  0, FB_VMODE_INTERLACED + FB_VMODE_DOUBLE, 0},
+	/* 800x480@60 CVT */
+	{ NULL, 60, 800, 480, KHZ2PICOS(29500), 96, 24, 10, 3, 72, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 800x480@75 CVT */
+	{ NULL, 75, 800, 480, KHZ2PICOS(38500), 112, 32, 14, 3, 80, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 800x600@60 DMT */
+	{ NULL, 60, 800, 600, KHZ2PICOS(40000), 88, 40, 23, 1, 128, 4,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 800x600@60 CVT */
+	{ NULL, 60, 800, 600, KHZ2PICOS(38250), 112, 32, 17, 3, 80, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 800x600@75 DMT */
+	{ NULL, 75, 800, 600, KHZ2PICOS(49500), 160, 16, 21, 1, 80, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 800x600@75 CVT */
+	{ NULL, 75, 800, 600, KHZ2PICOS(49000), 120, 40, 22, 3, 80, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 848x480@60 DMT */
+	{ NULL, 60, 848, 480, KHZ2PICOS(33750), 112, 16, 23, 6, 112, 8,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1024x600@60 DMT */
+	{ NULL, 60, 1024, 600, KHZ2PICOS(49000), 144, 40, 11, 3, 104, 10,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1024x768@60 DMT */
+	{ NULL, 60, 1024, 768, KHZ2PICOS(65000), 160, 24, 29, 3, 136, 6,
+	  0, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1024x768@60 CVT */
+	{ NULL, 60, 1024, 768, KHZ2PICOS(63500), 152, 48, 23, 3, 104, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1024x768@75 DMT */
+	{ NULL, 75, 1024, 768, KHZ2PICOS(78750), 176, 16, 28, 1, 96, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 1024x768@75 CVT */
+	{ NULL, 75, 1024, 768, KHZ2PICOS(82000), 168, 64, 30, 3, 104, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 1152x864@60 CVT */
+	{ NULL, 60, 1152, 864, KHZ2PICOS(81750), 184, 64, 26, 3, 120, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1152x864@75 DMT */
+	{ NULL, 75, 1152, 864, KHZ2PICOS(108000), 256, 64, 32, 1, 128, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1152x864@75 CVT */
+	{ NULL, 75, 1152, 864, KHZ2PICOS(104000), 192, 72, 34, 3, 120, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1280x720@50 CEA861,HDMI_1280x720p50_16x9 */
+	{ NULL, 50, 1280, 720, KHZ2PICOS(74250), 220, 440, 20, 5, 40, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1280x720@60 CEA861,HDMI_1280x720p60_16x9 */
+	{ NULL, 60, 1280, 720, KHZ2PICOS(74250), 220, 110, 20, 5, 40, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+#if 0
+	/* 1280x720@60 CVT */
+	{ NULL, 60, 1280, 720, KHZ2PICOS(74500), 192, 64, 20, 3, 128, 5,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 1280x720@75 CVT */
+	{ NULL, 75, 1280, 720, KHZ2PICOS(95750), 208, 80, 27, 3, 128, 5,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1280x768@60 DMT/CVT */
+	{ NULL, 60, 1280, 768, KHZ2PICOS(79500), 192, 64, 20, 3, 128, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1280x768@75 DMT/CVT */
+	{ NULL, 75, 1280, 768, KHZ2PICOS(102250), 208, 80, 27, 3, 128, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1280x800@60 DMT/CVT */
+	{ NULL, 60, 1280, 800, KHZ2PICOS(83500), 200, 72, 22, 3, 128, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1280x800@75 DMT/CVT */
+	{ NULL, 75, 1280, 800, KHZ2PICOS(106500), 208, 80, 29, 3, 128, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1280x960@60 DMT */
+	{ NULL, 60, 1280, 960, KHZ2PICOS(108000), 312, 96, 36, 1, 112, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 1280x960@60 CVT */
+	{ NULL, 60, 1280, 960, KHZ2PICOS(101250), 208, 80, 29, 3, 128, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 1280x960@75 CVT */
+	{ NULL, 75, 1280, 960, KHZ2PICOS(130000), 224, 88, 38, 3, 136, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+	/* 1280x1024@60 DMT */
+	{ NULL, 60, 1280, 1024, KHZ2PICOS(108000), 248, 48, 38, 1, 112, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 1280x1024@60 CVT */
+	{ NULL, 60, 1280, 1024, KHZ2PICOS(109000), 216, 80, 29, 3, 136, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 1280x1024@75 DMT */
+	{ NULL, 75, 1280, 1024, KHZ2PICOS(135000), 248, 16, 38, 1, 144, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 1280x1024@75 CVT */
+	{ NULL, 75, 1280, 1024, KHZ2PICOS(138750), 224, 88, 38, 3, 136, 7,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, 0},
+#endif
+	/* 1360x768@60 */
+	{ NULL, 60, 1360, 768, KHZ2PICOS(85500), 256, 64, 18, 3, 112, 6,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1366x768@60 */
+	{ NULL, 60, 1366, 768, KHZ2PICOS(85500), 213, 70, 24, 3, 143, 3,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1400x1050@60 DMT/CVT */
+	{ NULL, 60, 1400, 1050, KHZ2PICOS(121750), 232, 88, 32, 3, 144, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#if 0
+	/* 1400x1050@60+R DMT/CVT */
+	{ NULL, 60, 1400, 1050, KHZ2PICOS(101000), 80, 48, 23, 3, 32, 4,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+#endif
+	/* 1440x480p@60 CEA861 */
+	{ NULL, 60, 1400, 480, KHZ2PICOS(54054), 120, 32, 30, 9, 124, 6,
+	  0, FB_VMODE_NONINTERLACED, 0},
+	/* 1440x900@60 DMT/CVT */
+	{ NULL, 60, 1440, 900, KHZ2PICOS(106500), 232, 80, 25, 3, 152, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1440x900@75 DMT/CVT */
+	{ NULL, 75, 1440, 900, KHZ2PICOS(136750), 248, 96, 33, 3, 152, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1600x1200@60 DMT/CVT */
+	{ NULL, 60, 1600, 1200, KHZ2PICOS(162000), 304, 64, 46, 1, 192, 3,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1680x1050@60 DMT/CVT */
+	{ NULL, 60, 1680, 1050, KHZ2PICOS(146250), 280, 104, 30, 3, 176, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1920x1080@25,HDMI_1920x1080p25_16x9 */
+	{ NULL, 25, 1920, 1080, KHZ2PICOS(74250), 148, 528, 36, 4, 44, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1920x1080@30,HDMI_1920x1080p30_16x9 */
+	{ NULL, 30, 1920, 1080, KHZ2PICOS(74250), 148, 88, 36, 4, 44, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1920x1080@50,HDMI_1920x1080p50_16x9 */
+	{ NULL, 50, 1920, 1080, KHZ2PICOS(148500), 148, 528, 36, 4, 44, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1920x1080i@50 */
+	{ NULL, 50, 1920, 1080, KHZ2PICOS(74250), 148, 528, 30, 4, 44, 10,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_INTERLACED, 0},
+	/* 1920x1080@60 */
+	{ NULL, 60, 1920, 1080, KHZ2PICOS(148500), 148, 88, 36, 4, 44, 5,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_NONINTERLACED, 0},
+	/* 1920x1080i@60 */
+	{ NULL, 60, 1920, 1080, KHZ2PICOS(74250), 148, 88, 30, 4, 44, 10,
+	  FB_SYNC_VERT_HIGH_ACT + FB_SYNC_HOR_HIGH_ACT,
+	  FB_VMODE_INTERLACED, 0},
+	/* 1920x1200@60+R DMT/CVT */
+	{ NULL, 60, 1920, 1200, KHZ2PICOS(154000), 80, 48, 26, 3, 32, 6,
+	  FB_SYNC_HOR_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	/* 1920x1200@60 DMT/CVT */
+	{ NULL, 60, 1920, 1200, KHZ2PICOS(193250), 336, 136, 36, 3, 200, 6,
+	  FB_SYNC_VERT_HIGH_ACT, FB_VMODE_NONINTERLACED, FB_MODE_IS_VESA},
+	{ NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	  0, 0, 0 },
+};
+
+char *vpp_colfmt_str[] = {"YUV420", "YUV422H", "YUV422V", "YUV444", "YUV411",
+			"GRAY", "ARGB", "AUTO", "RGB888", "RGB666", "RGB565",
+			"RGB1555", "RGB5551"};
+const char *vpp_mod_str[] = {"GOVRH2", "GOVRH", "DISP", "GOVW", "GOVM", "SCL",
+	"SCLW", "VPU", "VPUW", "PIP", "VPPM", "LCDC", "CUR", "MAX"};
+
+#else
+#define EXTERN extern
+
+extern const unsigned int vpp_csc_parm[VPP_CSC_MAX][7];
+extern char *vpp_colfmt_str[];
+extern const struct fb_videomode vpp_videomode[];
+extern char *vpp_mod_str[];
+#ifdef CONFIG_VPP_NOTIFY
+extern struct switch_dev vpp_sdev;
+#endif
+#endif
+
+EXTERN struct vpp_info_t g_vpp;
+#ifdef VPP_C
+EXPORT_SYMBOL(g_vpp);
+#endif
+
+static inline int vpp_get_hdmi_spdif(void)
+{
+	return (g_vpp.hdmi_audio_interface == VPP_HDMI_AUDIO_SPDIF) ? 1 : 0;
+}
+
+/* Internal functions */
+EXTERN int get_key(void);
+EXTERN unsigned int vpp_get_chipid(void);
+
+/* Export functions */
+EXTERN void vpp_mod_unregister(vpp_mod_t mod);
+EXTERN struct vpp_mod_base_t *vpp_mod_register(vpp_mod_t mod, int size,
+	unsigned int flags);
+EXTERN struct vpp_mod_base_t *vpp_mod_get_base(vpp_mod_t mod);
+EXTERN struct vpp_fb_base_t *vpp_mod_get_fb_base(vpp_mod_t mod);
+EXTERN vdo_framebuf_t *vpp_mod_get_framebuf(vpp_mod_t mod);
+EXTERN void vpp_mod_init(void);
+EXTERN void vpp_mod_set_clock(vpp_mod_t mod,
+	vpp_flag_t enable, int force);
+
+EXTERN unsigned int vpp_get_base_clock(vpp_mod_t mod);
+EXTERN void vpp_set_video_scale(vdo_view_t *vw);
+EXTERN int vpp_set_recursive_scale(vdo_framebuf_t *src_fb,
+	vdo_framebuf_t *dst_fb);
+EXTERN vpp_display_format_t vpp_get_fb_field(vdo_framebuf_t *fb);
+EXTERN void vpp_wait_vsync(int no, int cnt);
+EXTERN int vpp_get_gcd(int A, int B);
+EXTERN vpp_csc_t vpp_check_csc_mode(vpp_csc_t mode,
+	vdo_color_fmt src_fmt, vdo_color_fmt dst_fmt, unsigned int flags);
+EXTERN inline void vpp_cache_sync(void);
+EXTERN int vpp_calc_refresh(int pixclk, int xres, int yres);
+EXTERN int vpp_calc_align(int value, int align);
+EXTERN int vpp_calc_fb_width(vdo_color_fmt colfmt, int width);
+EXTERN void vpp_get_colfmt_bpp(vdo_color_fmt colfmt,
+	int *y_bpp, int *c_bpp);
+EXTERN int vpp_irqproc_work(enum vpp_int_t type, int (*func)(void *argc),
+	void *arg, int wait_ms, int work_cnt);
+EXTERN int vpp_check_dbg_level(enum vpp_dbg_level_t level);
+
+#ifdef __KERNEL__
+EXTERN void vpp_dbg_show(int level, int tmr, char *str);
+EXTERN void vpp_dbg_wake_up(void);
+EXTERN int vpp_dbg_get_period_usec(struct vpp_dbg_period_t *p,
+	int cmd);
+EXTERN void vpp_dbg_timer(struct vpp_dbg_timer_t *p, char *str, int cmd);
+EXTERN void vpp_dbg_back_trace(void);
+EXTERN void vpp_dbg_show_val1(int level, int tmr, char *str, int val);
+EXTERN void vpp_dbg_wait(char *str);
+EXTERN void vpp_irqproc_init(void);
+EXTERN void vpp_irqproc_del_work(enum vpp_int_t type,
+	int (*func)(void *argc));
+EXTERN struct vpp_irqproc_t *vpp_irqproc_get_entry(
+	enum vpp_int_t vpp_int);
+
+/* dev-vpp.c */
+EXTERN int vpp_get_info(int fbn, struct fb_var_screeninfo *var);
+EXTERN int vpp_set_par(struct fb_info *info);
+EXTERN void vpp_backup_reg2(unsigned int addr,
+	unsigned int size, unsigned int *ptr);
+EXTERN void vpp_restore_reg2(unsigned int addr,
+	unsigned int size, unsigned int *reg_ptr);
+EXTERN int vpp_pan_display(struct fb_var_screeninfo *var,
+			struct fb_info *info);
+EXTERN void vpp_netlink_init(void);
+EXTERN void vpp_netlink_notify(int no, int cmd, int arg);
+EXTERN void vpp_netlink_notify_plug(int vout_num, int plugin);
+EXTERN void vpp_netlink_notify_cp(int enable);
+EXTERN void vpp_switch_state_init(void);
+EXTERN int vpp_set_blank(struct fb_info *info, int blank);
+#endif
+
+EXTERN unsigned int vpp_convert_colfmt(int yuv2rgb, unsigned int data);
+EXTERN void vpp_init(void);
+
+/* EXTERN void vpp_set_power_mgr(int arg); */
+EXTERN void vpp_show_timing(char *str,
+	struct fb_videomode *vmode, vpp_clock_t *clk);
+EXTERN void vpp_show_framebuf(char *str, vdo_framebuf_t *fb);
+EXTERN void vpp_show_videomode(char *str, struct fb_videomode *v);
+EXTERN void vpp_set_NA12_hiprio(int type);
+
+EXTERN int vpp_mb_get(unsigned int phy);
+EXTERN int vpp_mb_put(unsigned int phy);
+EXTERN int vpp_mb_irqproc_sync(int arg);
+
+#undef EXTERN
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* VPP_H */
diff --git a/drivers/video/wmt/vppm.c b/drivers/video/wmt/vppm.c
new file mode 100755
index 00000000..25882356
--- /dev/null
+++ b/drivers/video/wmt/vppm.c
@@ -0,0 +1,284 @@
+/*++
+ * linux/drivers/video/wmt/vppm.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define VPPM_C
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+#include "vppm.h"
+HW_REG struct vppm_base_regs *vppm_regs = (void *) VPP_BASE_ADDR;
+
+void vppm_set_int_enable(vpp_flag_t enable, enum vpp_int_t int_bit)
+{
+#ifdef WMT_FTBLK_SCL
+	if (int_bit & VPP_INT_SCL_VBIE)
+		vppm_regs->int_en.b.scl_vbie = enable;
+	if (int_bit & VPP_INT_SCL_VBIS)
+		vppm_regs->int_en.b.scl_vbis = enable;
+	if (int_bit & VPP_INT_SCL_PVBI)
+		vppm_regs->int_en.b.scl_pvbi = enable;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_bit & VPP_INT_GOVRH_VBIE)
+		vppm_regs->int_en.b.govrh_vbie = enable;
+	if (int_bit & VPP_INT_GOVRH_VBIS)
+		vppm_regs->int_en.b.govrh_vbis = enable;
+	if (int_bit & VPP_INT_GOVRH_PVBI)
+		vppm_regs->int_en.b.govrh_pvbi = enable;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_bit & VPP_INT_GOVRH2_VBIE)
+		vppm_regs->int_en.b.govrh2_vbie = enable;
+	if (int_bit & VPP_INT_GOVRH2_VBIS)
+		vppm_regs->int_en.b.govrh2_vbis = enable;
+	if (int_bit & VPP_INT_GOVRH2_PVBI)
+		vppm_regs->int_en.b.govrh2_pvbi = enable;
+#endif
+}
+
+int vppm_get_int_enable(enum vpp_int_t int_bit)
+{
+	int ret = 0;
+
+#ifdef WMT_FTBLK_SCL
+	if (int_bit & VPP_INT_SCL_VBIE)
+		ret = vppm_regs->int_en.b.scl_vbie;
+	if (int_bit & VPP_INT_SCL_VBIS)
+		ret = vppm_regs->int_en.b.scl_vbis;
+	if (int_bit & VPP_INT_SCL_PVBI)
+		ret = vppm_regs->int_en.b.scl_pvbi;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_bit & VPP_INT_GOVRH_VBIE)
+		ret = vppm_regs->int_en.b.govrh_vbie;
+	if (int_bit & VPP_INT_GOVRH_VBIS)
+		ret = vppm_regs->int_en.b.govrh_vbis;
+	if (int_bit & VPP_INT_GOVRH_PVBI)
+		ret = vppm_regs->int_en.b.govrh_pvbi;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_bit & VPP_INT_GOVRH2_VBIE)
+		ret = vppm_regs->int_en.b.govrh2_vbie;
+	if (int_bit & VPP_INT_GOVRH2_VBIS)
+		ret = vppm_regs->int_en.b.govrh2_vbis;
+	if (int_bit & VPP_INT_GOVRH2_PVBI)
+		ret = vppm_regs->int_en.b.govrh2_pvbi;
+#endif
+	return ret;
+}
+
+enum vpp_int_t vppm_get_int_status(void)
+{
+	unsigned int int_enable_reg;
+	unsigned int int_sts_reg;
+	enum vpp_int_t int_sts = 0;
+
+	int_enable_reg = vppm_regs->int_en.val;
+	int_sts_reg = vppm_regs->int_sts.val;
+
+#ifdef WMT_FTBLK_SCL
+	if (vppm_regs->int_en.b.scl_vbie && vppm_regs->int_sts.b.scl_vbie)
+		int_sts |= VPP_INT_SCL_VBIE;
+	if (vppm_regs->int_en.b.scl_vbis && vppm_regs->int_sts.b.scl_vbis)
+		int_sts |= VPP_INT_SCL_VBIS;
+	if (vppm_regs->int_en.b.scl_pvbi && vppm_regs->int_sts.b.scl_pvbi)
+		int_sts |= VPP_INT_SCL_PVBI;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (vppm_regs->int_en.b.govrh_pvbi && vppm_regs->int_sts.b.govrh_pvbi)
+		int_sts |= VPP_INT_GOVRH_PVBI;
+	if (vppm_regs->int_en.b.govrh_vbis && vppm_regs->int_sts.b.govrh_vbis)
+		int_sts |= VPP_INT_GOVRH_VBIS;
+	if (vppm_regs->int_en.b.govrh_vbie && vppm_regs->int_sts.b.govrh_vbie)
+		int_sts |= VPP_INT_GOVRH_VBIE;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (vppm_regs->int_en.b.govrh2_pvbi && vppm_regs->int_sts.b.govrh2_pvbi)
+		int_sts |= VPP_INT_GOVRH2_PVBI;
+	if (vppm_regs->int_en.b.govrh2_vbis && vppm_regs->int_sts.b.govrh2_vbis)
+		int_sts |= VPP_INT_GOVRH2_VBIS;
+	if (vppm_regs->int_en.b.govrh2_vbie && vppm_regs->int_sts.b.govrh2_vbie)
+		int_sts |= VPP_INT_GOVRH2_VBIE;
+#endif
+	return int_sts;
+}
+
+void vppm_clean_int_status(enum vpp_int_t int_sts)
+{
+#ifdef WMT_FTBLK_SCL
+	if (int_sts & VPP_INT_SCL_VBIE)
+		vppm_regs->int_sts.val = BIT18;
+	if (int_sts & VPP_INT_SCL_VBIS)
+		vppm_regs->int_sts.val = BIT17;
+	if (int_sts & VPP_INT_SCL_PVBI)
+		vppm_regs->int_sts.val = BIT16;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_sts & VPP_INT_GOVRH_VBIE)
+		vppm_regs->int_sts.val = BIT10;
+	if (int_sts & VPP_INT_GOVRH_VBIS)
+		vppm_regs->int_sts.val = BIT9;
+	if (int_sts & VPP_INT_GOVRH_PVBI)
+		vppm_regs->int_sts.val = BIT8;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (int_sts & VPP_INT_GOVRH2_VBIE)
+		vppm_regs->int_sts.val = BIT14;
+	if (int_sts & VPP_INT_GOVRH2_VBIS)
+		vppm_regs->int_sts.val = BIT13;
+	if (int_sts & VPP_INT_GOVRH2_PVBI)
+		vppm_regs->int_sts.val = BIT12;
+#endif
+}
+
+void vppm_set_module_reset(vpp_mod_t mod)
+{
+	unsigned int value1 = 0x00, value2 = 0x00;
+	unsigned int value3 = 0x00;
+
+#ifdef WMT_FTBLK_SCL
+	if (mod == VPP_MOD_SCL)
+		value1 |= BIT0;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	if (mod == VPP_MOD_GOVRH)
+		value2 |= (BIT0 | BIT8 | BIT9);
+#endif
+	vppm_regs->sw_reset1.val = ~value1;
+	vppm_regs->sw_reset1.val = 0x1010101;
+	vppm_regs->sw_reset2.val = ~value2;
+	vppm_regs->sw_reset2.val = 0x1011311;
+	vppm_regs->sw_reset3.val = ~value3;
+	vppm_regs->sw_reset3.val = 0x10101;
+}
+
+void vppm_reg_dump(void)
+{
+	unsigned int reg1, reg2;
+
+	DPRINT("========== VPPM register dump ==========\n");
+	vpp_reg_dump(REG_VPP_BEGIN, REG_VPP_END - REG_VPP_BEGIN);
+
+	DPRINT("---------- VPP Interrupt ----------\n");
+	reg1 = vppm_regs->int_sts.val;
+	reg2 = vppm_regs->int_en.val;
+	DPRINT("GOVRH PVBI(En %d,%d),VBIS(En %d,%d),VBIE(En %d,%d)\n",
+		vppm_regs->int_en.b.govrh_pvbi,
+		vppm_regs->int_sts.b.govrh_pvbi,
+		vppm_regs->int_en.b.govrh_vbis,
+		vppm_regs->int_sts.b.govrh_vbis,
+		vppm_regs->int_en.b.govrh_vbie,
+		vppm_regs->int_sts.b.govrh_vbie);
+
+	DPRINT("GOVRH2 PVBI(En %d,%d),VBIS(En %d,%d),VBIE(En %d,%d)\n",
+		vppm_regs->int_en.b.govrh2_pvbi,
+		vppm_regs->int_sts.b.govrh2_pvbi,
+		vppm_regs->int_en.b.govrh2_vbis,
+		vppm_regs->int_sts.b.govrh2_vbis,
+		vppm_regs->int_en.b.govrh2_vbie,
+		vppm_regs->int_sts.b.govrh2_vbie);
+
+	DPRINT("SCL PVBI(En %d,%d),VBIS(En %d,%d),VBIE(En %d,%d)\n",
+		vppm_regs->int_en.b.scl_pvbi,
+		vppm_regs->int_sts.b.scl_pvbi,
+		vppm_regs->int_en.b.scl_vbis,
+		vppm_regs->int_sts.b.scl_vbis,
+		vppm_regs->int_en.b.scl_vbie,
+		vppm_regs->int_sts.b.scl_vbie);
+}
+
+#ifdef CONFIG_PM
+void vppm_suspend(int sts)
+{
+	switch (sts) {
+	case 0:	/* disable module */
+		break;
+	case 1: /* disable tg */
+		break;
+	case 2:	/* backup register */
+		p_vppm->reg_bk = vpp_backup_reg(REG_VPP_BEGIN,
+			(REG_VPP_END - REG_VPP_BEGIN));
+		break;
+	default:
+		break;
+	}
+}
+
+void vppm_resume(int sts)
+{
+	switch (sts) {
+	case 0:	/* restore register */
+		vpp_restore_reg(REG_VPP_BEGIN, (REG_VPP_END - REG_VPP_BEGIN),
+			p_vppm->reg_bk);
+		p_vppm->reg_bk = 0;
+		break;
+	case 1:	/* enable module */
+		break;
+	case 2: /* enable tg */
+		break;
+	default:
+		break;
+	}
+}
+#else
+#define vppm_suspend NULL
+#define vppm_resume NULL
+#endif
+
+void vppm_init(void *base)
+{
+	struct vppm_mod_t *mod_p;
+
+	mod_p = (struct vppm_mod_t *) base;
+
+	vppm_set_module_reset(0);
+	vppm_set_int_enable(VPP_FLAG_ENABLE, mod_p->int_catch);
+	vppm_clean_int_status(~0);
+}
+
+int vppm_mod_init(void)
+{
+	struct vppm_mod_t *mod_p;
+
+	mod_p = (struct vppm_mod_t *) vpp_mod_register(VPP_MOD_VPPM,
+		sizeof(struct vppm_mod_t), 0);
+	if (!mod_p) {
+		DPRINT("*E* VPP module register fail\n");
+		return -1;
+	}
+
+	/* module member variable */
+	mod_p->int_catch = VPP_INT_NULL;
+
+	/* module member function */
+	mod_p->init = vppm_init;
+	mod_p->dump_reg = vppm_reg_dump;
+	mod_p->get_sts = vppm_get_int_status;
+	mod_p->clr_sts = vppm_clean_int_status;
+	mod_p->suspend = vppm_suspend;
+	mod_p->resume = vppm_resume;
+
+	p_vppm = mod_p;
+	return 0;
+}
+module_init(vppm_mod_init);
diff --git a/drivers/video/wmt/vppm.h b/drivers/video/wmt/vppm.h
new file mode 100755
index 00000000..5fe26521
--- /dev/null
+++ b/drivers/video/wmt/vppm.h
@@ -0,0 +1,63 @@
+/*++
+ * linux/drivers/video/wmt/vppm.h
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#include "vpp.h"
+
+/* #ifdef WMT_FTBLK_VPP */
+
+#ifndef VPPM_H
+#define VPPM_H
+
+struct vppm_mod_t {
+	VPP_MOD_BASE;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef VPPM_C
+#define EXTERN
+#else
+#define EXTERN extern
+#endif
+
+EXTERN struct vppm_mod_t *p_vppm;
+
+EXTERN void vppm_set_int_enable(vpp_flag_t enable,
+	enum vpp_int_t int_bit);
+EXTERN int vppm_get_int_enable(enum vpp_int_t int_bit);
+EXTERN enum vpp_int_t vppm_get_int_status(void);
+EXTERN void vppm_clean_int_status(enum vpp_int_t int_sts);
+EXTERN void vppm_set_module_reset(vpp_mod_t mod_bit);
+EXTERN int vppm_mod_init(void);
+EXTERN void vppm_set_DVO_select(int govr1);
+EXTERN void vppm_set_NA_mode(int hi_prio);
+
+#undef EXTERN
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* VPP_H */
+/* #endif */ /* WMT_FTBLK_VPP */
diff --git a/drivers/video/wmt/wmt-mb.c b/drivers/video/wmt/wmt-mb.c
new file mode 100755
index 00000000..61bc6855
--- /dev/null
+++ b/drivers/video/wmt/wmt-mb.c
@@ -0,0 +1,3154 @@
+/*++
+ * WonderMedia Memory Block driver
+ *
+ * Copyright c 2010  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+/*----------------------------------------------------------------------------
+ * MODULE       : driver/video/wmt/memblock.c
+ * DATE         : 2008/12/08
+ * DESCRIPTION  : Physical memory management driver
+ * HISTORY      :
+ * Version 1.0.0.2 , 2013/11/12
+*----------------------------------------------------------------------------*/
+#ifndef MEMBLOCK_C
+#define MEMBLOCK_C
+#endif
+
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/mman.h>
+#include <linux/list.h>
+#include <linux/proc_fs.h>
+#include <asm/page.h>
+#include <asm/uaccess.h>
+#include <asm/cacheflush.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/major.h>
+#include <linux/sched.h>
+#include <linux/swap.h>
+#include <mach/wmt_env.h>
+
+#include "com-mb.h"
+#include <linux/wmt-mb.h>
+
+#define THE_MB_USER "WMT-MB"
+#define MB_VERSION_MAJOR 1
+#define MB_VERSION_MINOR 0
+#define MB_VERSION_MICRO 0
+#define MB_VERSION_BUILD 6
+
+#define MB_DEBUG
+#define MB_INFO(fmt, args...)  \
+	printk(KERN_INFO "["THE_MB_USER"] " fmt , ## args)
+#define MB_WARN(fmt, args...)  \
+	printk(KERN_WARNING "["THE_MB_USER" *W*] " fmt, ## args)
+#define MB_ERROR(fmt, args...) \
+	printk(KERN_ERR "["THE_MB_USER" *E*] " fmt , ## args)
+
+#ifdef MB_DEBUG
+#define MB_OPDBG(fmt, args...) { /* FILE OPERATION DBG */ \
+	if (MBMSG_LEVEL) { \
+		printk("\t" KERN_DEBUG "["THE_MB_USER"] %s: " fmt, \
+			__func__ , ## args); \
+	} \
+}
+#define MB_DBG(fmt, args...) { \
+	if (MBMSG_LEVEL > 1) { \
+		printk("\t" KERN_DEBUG "["THE_MB_USER"] %s: " fmt, \
+			__func__ , ## args); \
+	} \
+}
+#define MB_WDBG(fmt, args...) { \
+	if (MBMSG_LEVEL > 2) { \
+		printk("\t" KERN_DEBUG "["THE_MB_USER"] %s: " fmt, \
+			__func__ , ## args); \
+	} \
+}
+#else
+#define MB_OPDBG(fmt, args...) do {} while (0)
+#define MB_DBG(fmt, args...) do {} while (0)
+#define MB_WDBG(fmt, args...) do {} while (0)
+#endif
+
+#ifdef CONFIG_WMT_MB_RESERVE_FROM_IO
+#include <linux/fb.h>
+#define MBIO_FSCREENINFO   FBIOGET_FSCREENINFO
+#define MBA_MAX_ORDER      20 /* 2^20 pages = 4 GB */
+#else
+#define MBA_MAX_ORDER      (MAX_ORDER - 1) /* 2^10 pages = 4 MB */
+#endif
+#define MBA_MIN_ORDER      (MAX_ORDER - 5) /* 2^6  pages = 256 KB */
+
+#define MBAFLAG_STATIC     0x80000000 /* static, without release if empty */
+
+#define MBFLAG_CACHED      0x00000001 /* MB mapping as cachable */
+
+#define MBFIND_VIRT        0x00000000 /* search virt address */
+#define MBFIND_PHYS        0x00000001 /* search phys address */
+
+#define MBUFIND_USER       0x00000001 /* search user address */
+#define MBUFIND_VIRT       0x00000002 /* search kernel virt address */
+#define MBUFIND_PHYS       0x00000004 /* search kernel phys address */
+#define MBUFIND_ALL        0x00000010 /* search all mbu */
+#define MBUFIND_CREATOR    0x00000020 /* search creator */
+#define MBUFIND_MMAP       0x00000040 /* search mbu which mapping from user */
+#define MBUFIND_GETPUT     0x00000080 /* search mbu which came from get/put */
+#define MBUFIND_ADDRMASK   (MBUFIND_USER|MBUFIND_VIRT|MBUFIND_PHYS)
+
+#define MBPROC_BUFSIZE     (16*1024)
+#define MBA_SHOW_BUFSIZE   (8*1024)
+#define MB_SHOW_BUFSIZE    (4*1024)
+
+#define MB_COUNT(mb)       atomic_read(&(mb)->count)
+#define MB_IN_USE(mb)      (MB_COUNT(mb)) /* count != 0 */
+#define PAGE_KB(a)         ((a)*(PAGE_SIZE/1024))
+#define MB_COMBIND_MBA(h, t) { \
+	(h)->pgi.pfn_end = (t)->pgi.pfn_end; \
+	(h)->pages += (t)->pages; \
+	(h)->tot_free_pages += (t)->tot_free_pages; \
+	(h)->max_available_pages += (t)->max_available_pages; \
+	list_del(&((t)->mba_list)); \
+	wmt_mbah->nr_mba--; \
+	kmem_cache_free(wmt_mbah->mba_cachep, t); \
+}
+
+#define list_loop list_for_each_entry
+struct mb_user;
+
+struct page_info {
+	unsigned long          pfn_start; /* start pfn of this block */
+	unsigned long          pfn_end; /* end pfn of this block */
+};
+
+struct mba_host_struct {
+	/* MB area link list link all MBAs */
+	struct list_head       mba_list;
+
+	/* page information of this MBA */
+	unsigned int           nr_mba;
+
+	/* total pages of all manager MBAs */
+	unsigned long          tot_pages;
+
+	/* total static pages of all manager MBAs */
+	unsigned long          tot_static_pages;
+
+	/* total free pages of all manager MBAs */
+	unsigned long          tot_free_pages;
+
+	/* max free pages of all manager MBAs */
+	unsigned long          max_available_pages;
+
+	/* allocator of MBA,
+	   use slab to prevent memory from fragment. */
+	struct kmem_cache      *mba_cachep;
+
+	/* allocator of MB,
+	   use slab to prevent memory from fragment. */
+	struct kmem_cache      *mb_cachep;
+
+	/* allocator of mb_user,
+	   use slab to prevent memory from fragment. */
+	struct kmem_cache      *mbu_cachep;
+
+	/* allocator of mb_task_info,
+	   use slab to prevent memory from fragment. */
+	struct kmem_cache      *mbti_cachep;
+};
+
+struct mb_area_struct {
+	/* MB area link list link all MBAs */
+	struct list_head       mba_list;
+
+	/* link list link to all MBs
+	   belong to this MBA */
+	struct list_head       mb_list;
+
+	/* pointer point to dedicated MBAH */
+	struct mba_host_struct *mbah;
+
+	/* flags of MBA */
+	unsigned int           flags;
+
+	/* prefech record task id */
+	pid_t                  tgid;
+
+	/* start physical address of this MBA */
+	unsigned long          phys;
+
+	/* start virtual address of this MBA */
+	void                   *virt;
+
+	/* size of this MB area. Normally,
+	   MAX kernel permitted size */
+	unsigned long          pages;
+
+	/* page information of this MBA */
+	struct page_info       pgi;
+
+	/* page information of this MBA */
+	unsigned int           nr_mb;
+
+	/* cur total free pages of this MBA */
+	unsigned long          tot_free_pages;
+
+	/* cur max free pages of this MBA */
+	unsigned long          max_available_pages;
+};
+
+struct mb_struct {
+	/* MB link list link all MBs
+	   in dedicated MBA */
+	struct list_head       mb_list;
+
+	/* pointer point to dedicated MBA */
+	struct mb_area_struct  *mba;
+
+	/* MB kernel page information */
+	struct page_info       pgi;
+
+	/* start physical address of this MB */
+	unsigned long          phys;
+
+	/* start virtual address of this MB */
+	void                   *virt;
+
+	/* allocate size */
+	unsigned long          size;
+
+	/* current MB use count,
+	   release until zero */
+	atomic_t               count;
+
+	/* flags of MB */
+	unsigned int           flags;
+
+	/* point to owner created the mb.
+	   this enlisted in mbu_list */
+	struct mb_user         *creator;
+
+	/* use for trace the user of mb */
+	struct list_head       mbu_list;
+};
+
+struct mb_user {
+	/* user link list link all users
+	   (include creator) of belonged MB */
+	struct list_head       mbu_list;
+
+	/* the mb to which this user belong */
+	struct mb_struct       *mb;
+
+	/* task id to which user belonged,
+	   user space user only */
+	pid_t                  tgid;
+
+	/* mb_mmap and MBIO_GET   : user address
+	   mb_get and mb->creator : physical address */
+	unsigned long          addr;
+
+	/* kernel space user:  mb size
+	 * user space user:    mmap size
+	 * zero:               owner - user space allocate but not mapped yet
+	 *                     not owner -come from get/put */
+	unsigned long          size;
+
+	/* user name for recoder */
+	char                   the_user[TASK_COMM_LEN+1];
+};
+
+struct mb_task_info {
+	/* task link list link all tasks which use MBDev */
+	struct list_head       mbti_list;
+	pid_t                  tgid; /* task pid */
+	atomic_t               count; /* multi open record */
+	char                   task_name[TASK_COMM_LEN+1];
+	struct task_struct     *task;
+};
+
+#ifdef CONFIG_WMT_MB_SIZE
+static int MB_TOTAL_SIZE = CONFIG_WMT_MB_SIZE * 1024;
+#else
+static int MB_TOTAL_SIZE = 32 * 1024;
+#endif
+static struct mba_host_struct *wmt_mbah;
+static struct mb_task_info wmt_mbti;
+const struct file_operations mb_fops;
+static unsigned char MBMSG_LEVEL;
+static unsigned char MBMAX_ORDER;
+static unsigned char MBMIN_ORDER;
+static unsigned char USR2PRDT_METHOD;
+
+/* read/write spinlock for multientry protection. */
+static spinlock_t mb_do_lock;
+static spinlock_t mb_search_lock;
+static spinlock_t mb_ioctl_lock;
+static spinlock_t mb_task_mm_lock;
+static spinlock_t mb_task_lock;
+static char show_mb_buffer[MB_SHOW_BUFSIZE];
+static char show_mba_buffer[MBA_SHOW_BUFSIZE];
+
+static inline uint64_t checkSum(unsigned long phys, int size, int type)
+{
+	char *d = (type) ? __va(phys) : mb_phys_to_virt(phys);
+	int i, pageSize, len, offset;
+	uint64_t sum, cs = 0;
+
+	len = size;
+	offset = (unsigned long)d % PAGE_SIZE;
+	while (len > 0) {
+		sum = 0;
+		pageSize = min((int)(PAGE_SIZE - offset), len);
+		for (i = 0; i < pageSize; i++)
+			sum += d[i];
+		MB_WDBG("[CS] addr %#lx ~ %#lx size %#x cs %#llx\n",
+			phys, phys + size, size, sum);
+		MB_WDBG("[CS:DATA] %02x %02x %02x %02x %02x %02x %02x %02x\n",
+			d[0] & 0xff, d[1] & 0xff, d[2] & 0xff, d[3] & 0xff,
+			d[4] & 0xff, d[5] & 0xff, d[6] & 0xff, d[7] & 0xff);
+		d += pageSize;
+		len -= pageSize;
+		cs += sum;
+	}
+
+	return cs;
+}
+
+unsigned long user_to_phys(unsigned long user)
+{
+	unsigned long par, phys, offset;
+	offset = user % PAGE_SIZE;
+
+	asm volatile(
+		"mcr p15, 0, %[user], c7, c8, 0\n"
+		"isb\n"
+		"mrc p15, 0,  %[par], c7, c4, 0\n"
+		: [par] "=r" (par)
+		: [user] "r" (user));
+
+	phys = (par & PAGE_MASK) + offset;
+	MB_DBG("%s: user %lx par %lx phys %lx\n",
+		__func__, user, par, phys);
+
+	return (par & 0x1) ? 0 : phys;
+}
+EXPORT_SYMBOL(user_to_phys);
+
+/* return address is guaranteeed only under page alignment */
+void *user_to_virt(unsigned long user)
+{
+	unsigned long phys;
+
+	phys = user_to_phys(user);
+	if (!phys) {
+		MB_WARN("user 0x%lx to virt fail.\n", user);
+		return 0;
+	}
+
+	return __va(phys);
+}
+EXPORT_SYMBOL(user_to_virt);
+
+struct prdt_info {
+	int index;
+	int items;
+	int offset;
+	int size;
+	struct prdt_struct *prdt;
+	struct prdt_struct *last;
+};
+
+static int prdt_proc(struct prdt_info *info, unsigned long phys)
+{
+	int len;
+
+	if (!info) {
+		MB_WARN("PRDT process fail. (NULL info)\n");
+		return -1;
+	}
+
+	/* PRDT has done or no PRDT space */
+	if (info->size <= 0 ||
+		(info->last && info->last->EDT))
+		return 0;
+
+	len = PAGE_SIZE - info->offset;
+	if (len > info->size) /* last page */
+		len = info->size;
+
+	/* Check it could combind with previous one */
+	if (info->last &&
+		/* prd size boundary check, MAX 60K */
+		(info->last->size <= ((1 << 16) - (2 * PAGE_SIZE))) &&
+		/* page continuity check */
+		((info->last->addr + info->last->size) == phys))
+		info->last->size += len;
+	else { /* create new one */
+		if (!info->items) {
+			MB_WARN("PRD table full (ptr %p # %d left %d).\n",
+				info->last+1, info->index+1, info->size);
+			if (info->last)
+				info->last->EDT = 1;
+			return -1;
+		}
+		if (info->last == NULL)
+			info->last = info->prdt;
+		else
+			info->last++;
+		info->last->addr = phys + info->offset;
+		info->last->size = len;
+		info->index++;
+		info->items--;
+		info->offset = 0;
+	}
+	info->size -= len;
+	info->last->reserve = 0;
+	info->last->EDT = (info->size) ? 0 : 1;
+	MB_WDBG("\t[PRD %3d] %p (0x%x ~ 0x%x, 0x%x, %x) phys 0x%lx offset 0x%x len 0x%x left %x\n",
+		info->index, info->last, info->last->addr, info->last->addr + info->last->size,
+		info->last->size, info->last->EDT, phys, info->offset, len, info->size);
+
+	return 0;
+}
+
+static inline void show_prdt(struct prdt_struct *next)
+{
+	int idx = 1;
+
+	while (!next->EDT) {
+		MB_INFO("PRDT %d-th item: addr %x size %d EDT %d\n",
+			idx, next->addr, next->size, next->EDT);
+		idx++;
+		next++;
+	}
+	MB_INFO("PRDT last(%d-th) item: addr %x size %d EDT %d\n",
+		idx, next->addr, next->size, next->EDT);
+}
+
+int user_to_prdt(
+	unsigned long user,
+	unsigned int size,
+	struct prdt_struct *prdt,
+	unsigned int items)
+{
+	struct prdt_info info = {0};
+	unsigned long addr;
+	int idx;
+
+	if (!prdt || ((size / PAGE_SIZE) + 2) > items) {
+		MB_WARN("PRD table space not enough (ptr %p at least %lu but %d).\n",
+			prdt, (size/PAGE_SIZE)+2, items);
+		return -EINVAL;
+	}
+
+	MB_DBG("Memory(%#lx,%#x) PRDT(%p,%d)\n", user, size, prdt, items);
+	info.items = items;
+	info.offset = user % PAGE_SIZE;
+	info.size = size;
+	info.prdt = prdt;
+	addr = user & PAGE_MASK;
+	while (info.size > 0) {
+		unsigned long phys = user_to_phys(addr);
+		if (!phys) {
+			MB_WARN("user to prdt fail: unknown addr %lx (%lx, %x)\n",
+				addr, user, size);
+			return -EINVAL;
+		}
+		prdt_proc(&info, phys);
+		addr += PAGE_SIZE;
+	}
+
+	/* flush cache */
+	MB_WDBG("flush PRDT %p, from %lx size %d\n", prdt, user, size);
+	dmac_flush_range((const void *)user, (const void *)(user + size));
+	for (idx = 0;; idx++) {
+		MB_WDBG("PRDT[%d] %p addr %x( ~ %x) size %d EDT %d (%p ~ %p)\n",
+			idx, &prdt[idx], prdt[idx].addr, prdt[idx].addr + prdt[idx].size, prdt[idx].size,
+			prdt[idx].EDT, __va(prdt[idx].addr), __va(prdt[idx].addr + prdt[idx].size));
+		outer_flush_range(prdt[idx].addr,
+			prdt[idx].addr + prdt[idx].size);
+		if (prdt[idx].EDT)
+			break;
+	}
+
+	/* show_prdt(prdt); */
+	return 0;
+}
+EXPORT_SYMBOL(user_to_prdt);
+
+int mb_to_prdt(
+	unsigned long phys,
+	unsigned int size,
+	struct prdt_struct *prdt,
+	unsigned int items)
+{
+	struct prdt_info info = {0};
+	unsigned long addr;
+	void *virt = NULL;
+	int idx;
+
+	if (!prdt || ((size / PAGE_SIZE) + 2) > items) {
+		MB_WARN("PRD table space not enough (ptr %p at least %lu but %d).\n",
+			prdt, (size/PAGE_SIZE)+2, items);
+		return -EINVAL;
+	}
+
+	MB_DBG("Memory(%#lx,%#x) PRDT(%p,%d)\n", phys, size, prdt, items);
+	info.items = items;
+	info.offset = phys % PAGE_SIZE;
+	info.size = size;
+	info.prdt = prdt;
+	addr = phys & PAGE_MASK;
+	while (info.size > 0) {
+		prdt_proc(&info, addr);
+		addr += PAGE_SIZE;
+	}
+
+	/* flush cache */
+	MB_WDBG("PRDT %p, from %lx size %d\n", prdt, phys, size);
+    virt = mb_phys_to_virt(phys);
+	dmac_flush_range(virt, virt + size);
+	for (idx = 0;; idx++) {
+		MB_WDBG("PRDT[%d] addr %x size %d EDT %d\n",
+			idx, prdt[idx].addr, prdt[idx].size, prdt[idx].EDT);
+		outer_flush_range(prdt[idx].addr,
+			prdt[idx].addr + prdt[idx].size);
+		if (prdt[idx].EDT)
+			break;
+	}
+
+	/* show_prdt(prdt); */
+	return 0;
+}
+EXPORT_SYMBOL(mb_to_prdt);
+
+unsigned int wmt_mmu_table_size(unsigned int size)
+{
+	unsigned int nPte, nPde, need;
+
+	if (!size)
+		return 0;
+
+	nPte = (size / PAGE_SIZE) + 2; /* maybe cross page up and down boundary */
+	nPde = PAGE_ALIGN(nPte * 4) / PAGE_SIZE;
+	need = PAGE_ALIGN(nPde * 4);
+	need += nPte * 4;
+
+	MB_DBG("PDE %d PTE %d RequestSize %d\n", nPde, nPte, need);
+	return need;
+}
+EXPORT_SYMBOL(wmt_mmu_table_size);
+
+int wmt_mmu_table_check(
+	unsigned int mmuPhys,
+	unsigned int mmuSize,
+	unsigned int size)
+{
+	int request;
+
+	if (!size) {
+		MB_WARN("mmu table failure. NULL size\n");
+		return 0;
+	}
+
+	if (!mmuSize) {
+		MB_WARN("mmu table failure. NULL mmu size\n");
+		return 0;
+	}
+
+	if (mmuPhys % PAGE_SIZE) {
+		MB_WARN("mmu table failure. PDE Table not align\n");
+		return 0;
+	}
+
+	request = wmt_mmu_table_size(size);
+	if (mmuSize < request) {
+		MB_WARN("mmu table failure. size %d < %d (request)\n",
+			mmuSize, request);
+		return 0;
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(wmt_mmu_table_check);
+
+void wmt_mmu_table_dump(struct mmu_table_info *info)
+{
+	unsigned int size, iPde, iPte, addrOffset;
+	unsigned int *mmuVirt, *pte = NULL, *pde = NULL;
+
+	if (info == 0) {
+		MB_ERROR("[WMT_MMU_TABLE] Null input pointer\n");
+		return;
+	}
+
+	mmuVirt = (unsigned int *)mb_phys_to_virt(info->addr);
+
+	size = info->size;
+	iPte = (info->offset >> 12) % 1024;
+	iPde = (info->offset >> 22) % 1024;
+	addrOffset = info->offset % PAGE_SIZE;
+
+	MB_INFO("MMU (%x): offset pde %x pte %x addr %x\n",
+		info->offset, iPde, iPte, addrOffset);
+
+	pde = mmuVirt;
+	pte = mb_phys_to_virt(pde[iPde]);
+	while (size > 0) {
+		int pageSize = min((unsigned int)(PAGE_SIZE - addrOffset), size);
+		MB_INFO("PDE(%p/%#x @ %d) -> PTE(%p/%#x @ %d) -> %#x, s %#x # %#x\n",
+			pde + iPde, info->addr + iPde * sizeof(pde), iPde,
+			pte + iPte, pde[iPde] + iPte * sizeof(pte), iPte,
+			pte[iPte] + addrOffset, pageSize, size);
+		iPte++;
+		addrOffset = 0;
+		size -= pageSize;
+		if (!(iPte % 1024)) {
+			iPde++;
+			iPte = 0;
+			pte = mb_phys_to_virt(pde[iPde]);
+		}
+	}
+}
+EXPORT_SYMBOL(wmt_mmu_table_dump);
+
+/* parameter:
+   mmuPhys  [IN] mmu table phys address
+   mmuSize  [IN] mmu table size
+   addr     [IN] physical address of convert data
+   size     [IN] convert size */
+unsigned int wmt_mmu_table_from_phys(
+	unsigned int mmuPhys,
+	unsigned int mmuSize,
+	unsigned int addr,
+	unsigned int size)
+{
+	unsigned int iPde, iPte, nPte, nPde, virBufAddr;
+	unsigned int *pte, *pde, *mmuVirt;
+	int64_t len = size;
+	void *virt = NULL;
+
+	iPde = iPte = nPte = nPde = 0;
+	if (!wmt_mmu_table_check(mmuPhys, mmuSize, size)) {
+		MB_WARN("phys %x (size %d) to mmu fail\n", addr, size);
+		return 0xFFFFFFFF;
+	}
+
+	virt = mb_phys_to_virt(addr);
+	virBufAddr = addr % PAGE_SIZE;
+	nPte = size / PAGE_SIZE + 2;
+	nPde = PAGE_ALIGN(nPte * 4) / PAGE_SIZE;
+	pde = mmuVirt = mb_phys_to_virt(mmuPhys);
+	pte = pde + nPde * 1024;
+	*pde = mmuPhys + nPde * PAGE_SIZE;
+	MB_DBG("[%s] pde %p/%x # %d pte %p/%x # %d\n",
+		__func__, pde, mmuPhys, nPde, pte, *pde, nPte);
+
+	while (len > 0) {
+		pte[iPte] = addr & PAGE_MASK;
+		iPte++;
+		if (!(iPte % 1024)) {
+			pde[iPte + 1] = pde[iPte] + PAGE_SIZE;
+			iPte++;
+		}
+		addr += PAGE_SIZE;
+		len -= PAGE_SIZE;
+	}
+
+	dmac_flush_range(virt, virt + size);
+	outer_flush_range(addr, addr + size);
+
+	return virBufAddr;
+}
+EXPORT_SYMBOL(wmt_mmu_table_from_phys);
+
+struct mmu_info {
+	unsigned int size;
+	unsigned int iPte;
+	unsigned int *pte;
+	unsigned int *pde;
+};
+
+static inline int wmt_mmu_table_proc(struct mmu_info *info, unsigned long phys)
+{
+	int pageSize, offset;
+	if (!info) {
+		MB_WARN("WMT MMU process fail. (NULL info)\n");
+		return -1;
+	}
+
+	if (info->size <= 0) {
+		MB_WARN("WMT MMU process fail. (size %d)\n", info->size);
+		return -1;
+	}
+
+	offset = phys % PAGE_SIZE;
+	pageSize = min((unsigned int)(PAGE_SIZE - offset), info->size);
+	*info->pte = phys & PAGE_MASK;
+	info->size -= pageSize;
+	MB_WDBG("\t[PTE] PDE[%d](%p)=%x PTE[%d](%p)=%x size %#x left %#x\n",
+		info->iPte/1024, info->pde, *info->pde, info->iPte,
+		info->pte, *info->pte, pageSize, info->size);
+
+	info->pte++;
+	info->iPte++;
+	if (!(info->iPte % 1024)) {
+		*info->pde = mb_virt_to_phys(info->pte);
+		info->pde++;
+	}
+
+	return 0;
+}
+
+/* parameter:
+   mmuPhys  [IN] mmu table phys address
+   mmuSize  [IN] mmu table size
+   addr     [IN] physical address of convert data
+   size     [IN] convert size */
+unsigned int wmt_mmu_table_from_user(
+	unsigned int mmuPhys,
+	unsigned int mmuSize,
+	unsigned int user,
+	unsigned int size)
+{
+#ifndef __KERNEL__
+	return wmt_mmu_table_from_phys(mmuPhys, mmuSize, user, size);
+#else
+	struct mmu_info info = {0};
+	unsigned int nPte, nPde;
+	unsigned long addr = user;
+	int offset = user % PAGE_SIZE;
+
+	if (!wmt_mmu_table_check(mmuPhys, mmuSize, size)) {
+		printk(KERN_WARNING "user %x (size %d) to mmu fail\n",
+			user, size);
+		return 0xFFFFFFFF;
+	}
+
+	MB_DBG("[%s] Memory(%#x,%#x) MMU(%#x,%d)\n",
+		__func__, user, size, mmuPhys, mmuSize);
+	nPte = size / PAGE_SIZE + 2;
+	nPde = PAGE_ALIGN(nPte * 4) / PAGE_SIZE;
+	info.size = size;
+	info.pde = mb_phys_to_virt(mmuPhys);
+	info.pte = info.pde + nPde * 1024;
+	*info.pde = mmuPhys + nPde * PAGE_SIZE;
+	dmac_flush_range((const void *)user, (const void *)(user + size));
+	while (info.size > 0) {
+		unsigned long phys = user_to_phys(addr);
+		int pageSize = min((unsigned int)(PAGE_SIZE - offset), info.size);
+		if (!phys) {
+			MB_WARN("user to mmu fail: unknown addr %lx (%x # %x)\n",
+				addr, user, size);
+			return -EINVAL;
+		}
+		outer_flush_range(phys, phys + pageSize);
+		wmt_mmu_table_proc(&info, phys);
+		addr += pageSize;
+		offset = 0;
+	}
+
+	return user % PAGE_SIZE;
+#endif
+}
+EXPORT_SYMBOL(wmt_mmu_table_from_user);
+
+/* parameter:
+   addr      [IN] start address (user or phys depends on addr_type)
+   size      [IN] size of memory
+   addrType  [IN] address type (0: phys 1: user)
+   info      [out] pointer of mmu table info */
+unsigned int wmt_mmu_table_create(
+	unsigned int addr,
+	unsigned int size,
+	unsigned int addrType,
+	struct mmu_table_info *info)
+{
+	int i, nPde, nPte, *pde, mmuSize;
+	unsigned int *mmuAddr = NULL;
+
+	if (!addr || !size || !info || addrType > 1) {
+		MB_ERROR("[WMT_MMU_TABLE] invalid args:\n");
+		MB_ERROR("\t addr %x # %x type %x info %p\n",
+			addr, size, addrType, info);
+		return -EINVAL;
+	}
+
+	mmuSize = wmt_mmu_table_size(size);
+	info->addr = mb_alloc(mmuSize);
+	info->size = size;
+	MB_DBG("[%s] mmu table (%#x # %#x) addr %#x size %#x type %d\n",
+		__func__, info->addr, mmuSize, addr, size, addrType);
+	if (!info->addr) {
+		MB_ERROR("[%s] fail. Out of MB (%d)\n", __func__, mmuSize);
+		return -ENOMEM;
+	}
+
+	pde = mmuAddr = (unsigned int *)mb_phys_to_virt((unsigned long)info->addr);
+	memset(mmuAddr, 0x0, mmuSize);
+	nPte = (size / PAGE_SIZE) + 2; /* maybe cross page up and down boundary */
+	nPde = PAGE_ALIGN(nPte * 4) / PAGE_SIZE;
+	for (i = 1; i <= nPde; i++, pde++)
+		*pde = info->addr + i * PAGE_SIZE;
+	info->offset = (addrType) ?
+		wmt_mmu_table_from_user(info->addr, mmuSize, addr, size) :
+		wmt_mmu_table_from_phys(info->addr, mmuSize, addr, size);
+
+	if (info->offset == 0xFFFFFFFF) {
+		MB_ERROR("[WMT_MMU_TABLE] create fail:");
+		MB_ERROR("\ttype %x addr %x # %x mmuAddr %p/%x # %d\n",
+			addrType, addr, size, mmuAddr, info->addr, info->size);
+		mb_free(info->addr);
+		return -EFAULT;
+	}
+
+	MB_DBG("[%s] success! (addr %#x size %#x offset %#x)\n",
+		__func__, info->addr, info->size, info->offset);
+	return 0;
+}
+EXPORT_SYMBOL(wmt_mmu_table_create);
+
+unsigned int wmt_mmu_table_destroy(struct mmu_table_info *info)
+{
+	if (!info) {
+		MB_ERROR("[WMT_MMU_TABLE] destroy fail. NULL mmu table info");
+		return -EINVAL;
+	}
+	MB_DBG("[%s] success! addr %#x\n", __func__, info->addr);
+	mb_free(info->addr);
+	return 0;
+}
+EXPORT_SYMBOL(wmt_mmu_table_destroy);
+
+static int mb_show_mb(
+	struct mb_struct *mb,
+	char *msg,
+	char *str,
+	int size
+)
+{
+	struct mb_user *mbu;
+	char *p;
+
+	if (!str && MBMSG_LEVEL <= 1)
+		return 0;
+
+	if (!mb)
+		return 0;
+
+	memset(show_mb_buffer, 0x0, MB_SHOW_BUFSIZE);
+	p = show_mb_buffer;
+	p += sprintf(p, "%s%s[MB,%p] %p %08lx %4ldKB [%4lx,%4lx] %3x\n",
+		msg ? msg : "", msg ? " " : "", mb, mb->virt, mb->phys,
+		mb->size/1024, mb->pgi.pfn_start, mb->pgi.pfn_end,
+		MB_COUNT(mb));
+
+	if (!list_empty(&mb->mbu_list)) {
+		list_loop(mbu, &mb->mbu_list, mbu_list) {
+			char tmp[256], *p1 = tmp;
+			int expectLen = (int)(p - show_mb_buffer);
+			p1 += sprintf(tmp, "            [%s%s,%p] %08lx ",
+				(mbu == mb->creator) ? "O" : " ",
+				(mbu->tgid == MB_DEF_TGID) ? "K" : "U",
+				mbu, mbu->addr);
+			p1 += sprintf(p1, "# %4ldKB By %s(%d)\n",
+				mbu->size/1024, mbu->the_user, mbu->tgid);
+			expectLen += strlen(tmp) + 1;
+			if (expectLen > MB_SHOW_BUFSIZE) {
+				p += sprintf(p, "\n\n               .......\n");
+				break;
+			}
+			p += sprintf(p, "%s", tmp);
+		}
+	}
+	if (str) {
+		if (strlen(show_mb_buffer) < size)
+			size = strlen(show_mb_buffer);
+		strncpy(str, show_mb_buffer, size);
+	} else {
+		size = strlen(show_mb_buffer);
+		MB_DBG("%s", show_mb_buffer);
+	}
+
+	return size;
+}
+
+static int mb_show_mba(
+	struct mb_area_struct *mba,
+	char *msg,
+	char *str,
+	int size,
+	int follow
+)
+{
+	struct mb_struct *mb;
+	char *p;
+	int idx = 1;
+
+	if (!str && MBMSG_LEVEL <= 1)
+		return 0;
+
+	if (!mba)
+		return 0;
+
+	memset(show_mba_buffer, 0x0, MBA_SHOW_BUFSIZE);
+
+	p = show_mba_buffer;
+	if (msg)
+		p += sprintf(p, "%s ", msg);
+	p += sprintf(p, "[%p] %p %08lx %3ldMB [%5lx,%5lx] ",
+		mba, mba->virt, mba->phys, PAGE_KB(mba->pages)/1024,
+		mba->pgi.pfn_start, mba->pgi.pfn_end);
+	p += sprintf(p, "%3x %6ldKB/%6ldKB   %s\n", mba->nr_mb,
+		PAGE_KB(mba->max_available_pages),
+		PAGE_KB(mba->tot_free_pages),
+		(mba->flags | MBAFLAG_STATIC) ? "S" : "D");
+	if (follow) {
+		p += sprintf(p, "    index -    [MemBlock] VirtAddr PhysAddr");
+		p += sprintf(p, "    size [  zs,  ze] cnt\n");
+		list_loop(mb, &mba->mb_list, mb_list) {
+			if ((MBA_SHOW_BUFSIZE - (p - show_mba_buffer)) < 22) {
+				p += sprintf(p, "\n\n        more ...\n");
+				break;
+			}
+			p += sprintf(p, "    %5d - ", idx++);
+			/* -2 is for \n and zero */
+			p += mb_show_mb(mb, NULL, p,
+				MBA_SHOW_BUFSIZE - (p - show_mba_buffer) - 2);
+		}
+	}
+
+	p += sprintf(p, "\n");
+
+	if (str) {
+		if (strlen(show_mba_buffer) < size)
+			size = strlen(show_mba_buffer);
+		strncpy(str, show_mba_buffer, size);
+	} else {
+		size = strlen(show_mba_buffer);
+		MB_DBG("%s", show_mba_buffer);
+	}
+
+	return size;
+}
+
+/* return physical address */
+#ifdef CONFIG_WMT_MB_RESERVE_FROM_IO
+/* mb_do_lock locked */
+static void *mb_alloc_pages(unsigned long *phys, unsigned long *nr_pages)
+{
+	unsigned int order = get_order(num_physpages << PAGE_SHIFT);
+	unsigned int size = *nr_pages << PAGE_SHIFT;
+	unsigned long addr = ((1 << order) - *nr_pages) << PAGE_SHIFT;
+	void *virt = NULL;
+
+	if (!nr_pages || !phys) {
+		MB_WARN("mb_alloc_pages fail. unknown argument\n");
+		return NULL;
+	}
+
+	*phys = 0;
+	if (*nr_pages == 0) {
+		MB_WARN("mb_alloc_pages zero size\n");
+		return NULL;
+	}
+
+	if (!request_mem_region(addr, size, "memblock")) {
+		MB_WARN("request memory region fail. addr %#lx size %d(KB).\n",
+			addr, size/1024);
+		return NULL;
+	}
+
+	virt = ioremap(addr, size);
+	if (!virt) {
+		MB_WARN("cannot ioremap memory. addr %#lx size %d(KB).\n",
+			addr, size/1024);
+		release_mem_region(addr, size);
+		return NULL;
+	}
+
+	*phys = addr;
+	MB_DBG("allocate mem region. addr V %p P %#lx size %d(KB)\n",
+		virt, addr, size/1024);
+
+	return virt;
+}
+
+/* mb_do_lock locked */
+static void mb_free_pages(void *virt, unsigned long phys, unsigned int nr_pages)
+{
+	iounmap(virt);
+	MB_DBG("release mem region. addr V %p P %#lx size %d(KB)\n",
+		virt, phys, 4*nr_pages);
+	return release_mem_region(phys, nr_pages << PAGE_SHIFT);
+}
+
+#else
+/* mb_do_lock locked */
+static void *mb_alloc_pages(unsigned long *phys, unsigned long *nr_pages)
+{
+	unsigned int i, order;
+	unsigned long virt = 0;
+	struct zone *zone;
+
+	if (!nr_pages || !phys) {
+		MB_WARN("mb_alloc_pages fail. unknown argument\n");
+		return NULL;
+	}
+
+	*phys = 0;
+	if (*nr_pages == 0) {
+		MB_WARN("mb_alloc_pages zero size\n");
+		return NULL;
+	}
+
+	order = get_order(*nr_pages * PAGE_SIZE);
+	order = max(order, (unsigned int)(MBA_MIN_ORDER));
+	MB_DBG(" %ld/%d pages, order %d\n", *nr_pages, 1 << order, order);
+	if (order > MBMAX_ORDER) {
+		MB_WARN("mb_alloc_mba fail. page out of size, %ld/%d/%d\n",
+			*nr_pages, (1<<order), (1<<MBMAX_ORDER));
+		return NULL;
+	}
+
+	zone = (first_online_pgdat())->node_zones;
+	for (i = order; i < MAX_ORDER; i++) {
+		if (zone->free_area[i].nr_free) {
+			virt = __get_free_pages(GFP_ATOMIC | GFP_DMA, order);
+			break;
+		}
+	}
+
+	if (virt) {
+		*nr_pages = 1 << order;
+		*phys = __pa(virt);
+		for (i = 0; i < *nr_pages; i++)
+			SetPageReserved(virt_to_page(virt + i * PAGE_SIZE));
+		MB_DBG("allocate mem region. addr V %#lx P %#lx size %ld(KB)\n",
+			virt, *phys, PAGE_KB(*nr_pages));
+	} else {
+		struct free_area *fa;
+		char msg[256], *p = msg;
+		MB_WARN("__get_free_pages fail! (pages: %d free %lu)\n",
+			1 << order, (unsigned long)nr_free_pages());
+		zone = (first_online_pgdat())->node_zones;
+		fa = zone->free_area;
+		p += sprintf(msg, "DMA ZONE:");
+		for (i = 0; i < MAX_ORDER; i++)
+			p += sprintf(p, " %ld*%dKB", fa[i].nr_free, 4 << i);
+		MB_WARN("%s= %ldkB\n", msg, PAGE_KB(nr_free_pages()));
+	}
+
+	return (void *)virt;
+}
+
+/* mb_do_lock locked */
+static void mb_free_pages(void *virt, unsigned long phys, unsigned int nr_pages)
+{
+	unsigned int index;
+
+	if (!phys || !nr_pages) {
+		MB_WARN("mb_free_pages unknow addr V %p P %#lx size %d pages\n",
+			virt, phys, nr_pages);
+		return;
+	}
+
+	for (index = 0; index < nr_pages; index++) {
+		unsigned long addr = (unsigned long)virt + index * PAGE_SIZE;
+		ClearPageReserved(virt_to_page(addr));
+	}
+
+	free_pages((unsigned long)virt, get_order(nr_pages * PAGE_SIZE));
+}
+#endif
+
+/* mb_do_lock locked */
+static struct mb_area_struct *mb_alloc_mba(unsigned int pages)
+{
+	struct mba_host_struct *mbah = wmt_mbah;
+	struct mb_area_struct *mba;
+
+	if (!mbah || !pages) {
+		MB_WARN("mb_alloc_mba fail. mbah %p, pages %d\n", mbah, pages);
+		return NULL;
+	}
+
+	mba = kmem_cache_alloc(mbah->mba_cachep, GFP_ATOMIC);
+	if (!mba) {
+		MB_WARN("mb_alloc_mba fail. out of memory\n");
+		return NULL;
+	}
+
+	memset(mba, 0x0, sizeof(struct mb_area_struct));
+	mba->pages = pages;
+	mba->virt = mb_alloc_pages(&mba->phys, &mba->pages);
+	if (!mba->virt) {
+		MB_WARN("mb_alloc_mba fail. no available space\n");
+		kmem_cache_free(mbah->mba_cachep, mba);
+		return NULL;
+	}
+
+	/* initialization */
+	INIT_LIST_HEAD(&mba->mb_list);
+	INIT_LIST_HEAD(&mba->mba_list);
+	mba->mbah = mbah;
+	mba->tot_free_pages = mba->max_available_pages = mba->pages;
+	mba->pgi.pfn_start = mba->phys >> PAGE_SHIFT;
+	mba->pgi.pfn_end = mba->pgi.pfn_start + mba->pages;
+	list_add_tail(&mba->mba_list, &mbah->mba_list);
+
+	/* update MBA host */
+	mbah->nr_mba++;
+	mbah->tot_pages += mba->pages;
+	mbah->tot_free_pages += mba->tot_free_pages;
+	if (mbah->max_available_pages < mba->max_available_pages)
+		mbah->max_available_pages = mba->max_available_pages;
+	mb_show_mba(mba, "alloc", NULL, 0, 0);
+
+	return mba;
+}
+
+/* mb_do_lock locked */
+static int mb_free_mba(struct mb_area_struct *mba)
+{
+	struct mba_host_struct *mbah;
+	struct mb_area_struct *entry;
+
+	if (!mba || !mba->mbah || mba->nr_mb) {
+		MB_WARN("mb_free_mba fail. unknow arg.(%p,%p,%x)\n",
+			mba, mba ? mba->mbah : NULL, mba ? mba->nr_mb : 0);
+		return -EFAULT;
+	}
+
+	mbah = mba->mbah;
+	list_loop(entry, &mbah->mba_list, mba_list) {
+		if (entry == mba)
+			break;
+	}
+
+	if (entry != mba) {
+		MB_WARN("mb_free_mba fail. unknow MBA %p\n", mba);
+		return -EFAULT;
+	}
+	if (mba->flags & MBAFLAG_STATIC)
+		return 0;
+
+	mb_show_mba(mba, "ReleaseMBA", NULL, 0, 0);
+
+	/* free mba */
+	list_del(&mba->mba_list);
+	mb_free_pages(mba->virt, mba->phys, mba->pages);
+	mbah->nr_mba--;
+	mbah->tot_free_pages -= mba->tot_free_pages;
+	mbah->tot_pages -= mba->pages;
+	kmem_cache_free(mbah->mba_cachep, mba);
+	mba = NULL;
+
+	/* update max mb size */
+	mbah->max_available_pages = 0;
+	list_loop(entry, &mbah->mba_list, mba_list) {
+		if (mbah->max_available_pages < entry->max_available_pages)
+			mbah->max_available_pages = entry->max_available_pages;
+	}
+
+	return 0;
+}
+
+/* mb_do_lock locked */
+static struct mb_struct *mb_alloc_mb(
+	struct mb_area_struct *mba,
+	unsigned long size)
+{
+	struct mba_host_struct *mbah;
+	struct mb_struct *mb, *entry;
+	struct list_head *next;
+	unsigned long pages, zs, ze;
+
+	if (!mba || !mba->mbah || !size) {
+		MB_WARN("mb_alloc_mb fail. unknow arg.(%p,%p,%lx)\n",
+			mba, mba ? mba->mbah : NULL, size);
+		return NULL;
+	}
+
+	mbah = mba->mbah;
+	size = PAGE_ALIGN(size);
+	pages = size >> PAGE_SHIFT;
+
+	/* mb free size is not enough */
+	if (mba->max_available_pages < pages) {
+		MB_WARN("mb_alloc_mb fail. no space in MBA (%lx<%lx)\n",
+			pages, mba->max_available_pages);
+		return NULL;
+	}
+
+	/* search available zone
+	zone start from mba start */
+	ze = zs = mba->pgi.pfn_start;
+	next = &mba->mb_list;
+	list_loop(entry, &mba->mb_list, mb_list) {
+		next = &entry->mb_list;
+		ze = entry->pgi.pfn_start;
+		if ((ze - zs) >= pages)
+			break;
+		zs = entry->pgi.pfn_end;
+	}
+
+	if (zs >= ze) {
+		next = &mba->mb_list;
+		ze = mba->pgi.pfn_end;
+	}
+
+	/* impossible, something wrong */
+	if ((ze - zs) < pages) {
+		MB_WARN("something wrong in MBA %p when allocate MB.\n", mba);
+		return NULL;
+	}
+
+	MB_DBG("Zone finding start %lx end %lx size %lx for size %lx\n",
+		zs, ze, ze - zs, pages);
+
+	mb = kmem_cache_alloc(mbah->mb_cachep, GFP_ATOMIC);
+	if (!mb) {
+		MB_WARN("mb_alloc_mb mb_cachep out of memory\n");
+		return NULL;
+	}
+
+	memset(mb, 0x0, sizeof(struct mb_struct));
+	INIT_LIST_HEAD(&mb->mb_list);
+	INIT_LIST_HEAD(&mb->mbu_list);
+	mb->mba = mba;
+	mb->pgi.pfn_start = zs;
+	mb->pgi.pfn_end = mb->pgi.pfn_start + pages;
+	mb->size = size;
+	mb->phys = mba->phys + ((zs - mba->pgi.pfn_start) << PAGE_SHIFT);
+	mb->virt = mba->virt + (mb->phys - mba->phys);
+	list_add_tail(&mb->mb_list, next);
+
+	mba->nr_mb++;
+	mba->tot_free_pages -= pages;
+	mbah->tot_free_pages -= pages;
+
+	/* update mba */
+	zs = mba->pgi.pfn_start;
+	mba->max_available_pages = 0;
+	list_loop(entry, &mba->mb_list, mb_list) {
+		mba->max_available_pages =
+		max(entry->pgi.pfn_start - zs, mba->max_available_pages);
+		zs = entry->pgi.pfn_end;
+	}
+	mba->max_available_pages =
+	max(mba->pgi.pfn_end - zs, mba->max_available_pages);
+
+	/* update mbah */
+	mbah->max_available_pages = 0;
+	list_loop(mba, &mbah->mba_list, mba_list) {
+		if (mbah->max_available_pages < mba->max_available_pages)
+			mbah->max_available_pages = mba->max_available_pages;
+	}
+
+	mb_show_mb(mb, "alloc", NULL, 0);
+
+	return mb;
+}
+
+/* mb_do_lock locked */
+static int mb_free_mb(struct mb_struct *mb)
+{
+	unsigned long zs, nr_pages;
+	struct mba_host_struct *mbah;
+	struct mb_area_struct *mba;
+	struct mb_struct *entry;
+
+	if (!mb) {
+		MB_WARN("mb_free_mb fail. unknow MB %p.\n", mb);
+		return -EFAULT;
+	}
+
+	if (MB_IN_USE(mb)) {
+		MB_WARN("mb_free_mb fail. invalid arg.(%p,%x,%lx,%ldKB)\n",
+			mb, MB_COUNT(mb), mb->phys, mb->size/1024);
+		return -EINVAL;
+	}
+
+	mba = mb->mba;
+	if (!mba || !mba->mbah) {
+		MB_WARN("mb_free_mb fail. unknow para.(%p,%p)\n",
+			mba, mba ? mba->mbah : NULL);
+		return -EFAULT;
+	}
+
+	list_loop(entry, &mba->mb_list, mb_list) {
+		if (entry == mb)
+			break;
+	}
+
+	if (entry != mb) {
+		MB_WARN("mb_free_mb fail. unknow MB %p\n", mb);
+		return -EFAULT;
+	}
+
+	mbah = mba->mbah;
+
+	mb_show_mb(mb, "Retrieve unused MB", NULL, 0);
+
+	/* free mb */
+	list_del(&mb->mb_list);
+	kmem_cache_free(mbah->mb_cachep, mb);
+	mba->nr_mb--;
+	mb = NULL;
+
+	/* unused mba, release it */
+	if (!mba->nr_mb && !(mba->flags & MBAFLAG_STATIC))
+		return mb_free_mba(mba);
+
+	/* update max mb size and free mb size */
+	/* reduce old one and then increase new one */
+	mbah->tot_free_pages -= mba->tot_free_pages;
+	zs = mba->pgi.pfn_start;
+	mba->tot_free_pages = mba->max_available_pages = nr_pages = 0;
+	list_loop(entry, &mba->mb_list, mb_list) {
+		nr_pages = max(entry->pgi.pfn_start - zs, nr_pages);
+		mba->tot_free_pages += entry->pgi.pfn_start - zs;
+		zs = entry->pgi.pfn_end;
+	}
+	mba->tot_free_pages += mba->pgi.pfn_end - zs;
+	mba->max_available_pages = max(mba->pgi.pfn_end - zs, nr_pages);
+	mbah->tot_free_pages += mba->tot_free_pages; /* add new one */
+	mbah->max_available_pages =
+		max(mbah->max_available_pages, mba->max_available_pages);
+
+	return 0;
+}
+
+/* type 0 - virtual address
+ *      1 - physical address */
+static struct mb_struct *mb_find_mb(void *addr, int type)
+{
+	struct mba_host_struct *mbah = wmt_mbah;
+	struct mb_area_struct *mba;
+	struct mb_struct *mb;
+	unsigned long flags;
+
+	if (!addr || (type != MBFIND_PHYS && type != MBFIND_VIRT)) {
+		MB_WARN("mb_find_mb fail. unknow type %d addr %p\n",
+			type, addr);
+		return NULL;
+	}
+
+	MB_DBG("IN, type %x addr %p\n", type, addr);
+
+	spin_lock_irqsave(&mb_search_lock, flags);
+
+	list_loop(mba, &mbah->mba_list, mba_list) {
+		void *eaddr, *saddr = (void *)(mba->phys);
+		if (type != MBFIND_PHYS)
+			saddr = mba->virt;
+		eaddr = saddr + mba->pages*PAGE_SIZE;
+		if (addr < saddr || addr > eaddr)
+			continue; /* address out of mba range */
+		list_loop(mb, &mba->mb_list, mb_list) {
+			void *mbaddr = (void *)(mb->phys);
+			if (type != MBFIND_PHYS)
+				mbaddr = mb->virt;
+			if (addr >= mbaddr && addr < (mbaddr + mb->size)) {
+				spin_unlock_irqrestore(&mb_search_lock, flags);
+				MB_DBG("OUT, va %p pa %lx s %ld(KB) cnt %d\n",
+					mb->virt, mb->phys, mb->size/1024,
+					MB_COUNT(mb));
+				return mb;
+			}
+		}
+	}
+
+	spin_unlock_irqrestore(&mb_search_lock, flags);
+
+	MB_DBG("OUT, NULL mb\n");
+
+	return NULL;
+}
+
+/*
+ * addr - search address
+ * tgid - task pid
+ * st   - search type (MBUFIND_XXX)
+ *     MBUFIND_USER: user address
+ *     MBUFIND_VIRT: kernel virt address
+ *     MBUFIND_PHYS: kernel phys address
+ *     MBUFIND_ALL:
+ *         1. mbu->tgid == tgid
+ *         2. tgid == MB_DEF_TGID, address and
+ *                 one of MBUFIND_VIRT and MBUFIND_PHYS must be set
+ *            tgid != MB_DEF_TGID, address and MBUFIND_USER must be set
+ *     MBUFIND_CREATOR:
+ *         1. mbu->tgid == tgid
+ *         2. tgid == MB_DEF_TGID, address and
+ *                 one of MBUFIND_VIRT and MBUFIND_PHYS must be set
+ *            tgid != MB_DEF_TGID, address and MBUFIND_USER must be set
+ *         3. mbu == mb->creator
+ *         4. mbu->size == mb->size
+ *     MBUFIND_GETPUT:
+ *         1. mbu->tgid == tgid
+ *         2. tgid == MB_DEF_TGID, address and
+ *                 MBUFIND_PHYS must be set (mbu->addr == mb->phys)
+ *            tgid != MB_DEF_TGID, address and
+ *                 MBUFIND_USER must be set (mbu->addr == user address)
+ *         3. mbu->size == 0
+ *     MBUFIND_MMAP:
+ *         1. mbu->tgid == tgid
+ *         2. address and MBUFIND_USER must be set
+ *         3. mbu->size != 0
+ */
+static struct mb_user *mb_find_mbu(void *addr, pid_t tgid, int st)
+{
+	struct mba_host_struct *mbah = wmt_mbah;
+	struct mb_area_struct *mba = NULL;
+	struct mb_struct *mb = NULL;
+	struct mb_user *mbu = NULL;
+	unsigned long flags;
+
+	if (!addr || !(st & MBUFIND_ADDRMASK)) {
+		MB_WARN("mb_find_mbu fail. unknow addr %p\n", addr);
+		return NULL;
+	}
+
+	MB_DBG("IN, addr %p search type %x TGID %x CurTask %s\n",
+		addr, st, tgid, current->comm);
+
+	spin_lock_irqsave(&mb_search_lock, flags);
+	list_loop(mba, &mbah->mba_list, mba_list) {
+		if (st & (MBUFIND_VIRT | MBUFIND_PHYS)) {
+			void *eaddr, *saddr = (void *)mba->phys;
+			if (st & MBUFIND_VIRT)
+				saddr = mba->virt;
+			eaddr = saddr + mba->pages*PAGE_SIZE;
+			if (addr < saddr || addr > eaddr)
+				continue; /* address out of mba range */
+		}
+		list_loop(mb, &mba->mb_list, mb_list) {
+			if ((st & MBUFIND_PHYS) && (addr != (void *)mb->phys))
+				continue; /* physical address not match */
+			if ((st & MBUFIND_VIRT) && (addr != mb->virt))
+				continue; /* virtual address not match */
+			list_loop(mbu, &mb->mbu_list, mbu_list) {
+				if (mbu->tgid != tgid && tgid != MB_DEF_TGID)
+					continue; /* tgid not match */
+				if ((st & MBUFIND_USER) &&
+				    (addr != (void *)mbu->addr))
+					continue; /* user address not match */
+				if (st & MBUFIND_ALL)
+					goto leave; /* found */
+				if (st & MBUFIND_CREATOR) {
+					mbu = mb->creator;
+					goto leave; /* found */
+				}
+				/* found (if mmap, mbu->size has map size) */
+				if (st & MBUFIND_MMAP && mbu->size)
+					goto leave;
+				/* found (if get/put, mbu->size should be 0) */
+				if (st & MBUFIND_GETPUT &&
+				    mbu->addr && !mbu->size)
+					goto leave;
+			}
+		}
+	}
+	mbu = NULL;
+
+leave:
+	if (mbu == NULL)
+		MB_DBG("OUT, NULL mbu\n");
+
+	if (mbu)
+		MB_DBG("OUT, mbu %p (%p TGID %x a %#lx s %ld(KB) by %s)\n",
+			mbu, mbu->mb, mbu->tgid, mbu->addr,
+			mbu->size/1024, mbu->the_user);
+
+	spin_unlock_irqrestore(&mb_search_lock, flags);
+
+	return mbu;
+}
+
+static void mb_update_mbah(void)
+{
+	unsigned long mbah_free = 0, mbah_max = 0;
+	struct mba_host_struct *mbah = wmt_mbah;
+	struct mb_area_struct *mba = NULL;
+	struct mb_struct *mb = NULL;
+
+	if (!mbah) {
+		MB_WARN("mb_update_mbah fail. unknow mbah\n");
+		return;
+	}
+
+	list_loop(mba, &mbah->mba_list, mba_list) {
+		unsigned long mba_free = 0, mba_max = 0, nr_pages = 0;
+		unsigned long zs = mba->pgi.pfn_start; /* zone start */
+		list_loop(mb, &mba->mb_list, mb_list) {
+			nr_pages = max(mb->pgi.pfn_start - zs, nr_pages);
+			mba_free += mb->pgi.pfn_start - zs;
+			zs = mb->pgi.pfn_end;
+		}
+		mba_free += mba->pgi.pfn_end - zs;
+		mbah_free += mba_free;
+		mba_max = max(mba->pgi.pfn_end - zs, nr_pages);
+		mbah_max = max(mbah_max, mba_max);
+	}
+
+	mbah->tot_free_pages = mbah_free;
+	mbah->max_available_pages = mbah_max;
+
+	return;
+}
+
+/* called from kernel only, mb_do_lock isn't needed */
+void *mb_do_phys_to_virt(unsigned long phys, pid_t tgid, char *name)
+{
+	struct mb_struct *mb = NULL;
+	void *virt = NULL;
+
+	MB_DBG("IN, Phys %lx TGID %x NAME %s\n", phys, tgid, name);
+	mb = mb_find_mb((void *)phys, MBFIND_PHYS);
+	if (mb)
+		virt = mb->virt + (phys - mb->phys);
+	else {
+		virt = __va(phys);
+		MB_WARN("%s do phys to virt fail. addr %lx not found\n",
+			name, phys);
+	}
+
+	MB_DBG("OUT, Virt %p\n", virt);
+
+	return virt;
+}
+EXPORT_SYMBOL(mb_do_phys_to_virt);
+
+/* called from kernel only, mb_do_lock isn't needed */
+unsigned long mb_do_virt_to_phys(void *virt, pid_t tgid, char *name)
+{
+	struct mb_struct *mb = NULL;
+	unsigned long phys = 0x0;
+
+	MB_DBG("IN, Virt %p TGID %x NAME %s\n", virt, tgid, name);
+	mb = mb_find_mb(virt, MBFIND_VIRT);
+	if (mb)
+		phys = mb->phys + (virt - mb->virt);
+	else {
+		phys = __pa(virt);
+		MB_WARN("%s do virt to phys fail. addr %p not found\n",
+			name, virt);
+	}
+
+	MB_DBG("OUT, Phys %lx\n", phys);
+
+	return phys;
+}
+EXPORT_SYMBOL(mb_do_virt_to_phys);
+
+unsigned long mb_do_user_to_phys(unsigned long user, pid_t tgid, char *name)
+{
+	unsigned long flags, phys = 0;
+	struct mb_user *mbu = NULL;
+
+	MB_DBG("IN, usr %lx TGID %x name %s\n", user, tgid, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+	mbu = mb_find_mbu((void *)user, tgid, MBUFIND_USER|MBUFIND_ALL);
+	if (!mbu) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_WARN("%s do user to phys. unknow addr %lx\n", name, user);
+		return 0;
+	}
+
+	if (!mbu->mb)
+		MB_WARN("%s do user to phys fail. unknow block (addr %lx)\n",
+			name, user);
+	else
+		phys = mbu->mb->phys;
+
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("OUT, Phys %#lx\n", phys);
+
+	return phys;
+}
+EXPORT_SYMBOL(mb_do_user_to_phys);
+
+unsigned long mb_do_user_to_virt(unsigned long user, pid_t tgid, char *name)
+{
+	struct mb_user *mbu = NULL;
+	unsigned long flags;
+	void *virt = NULL;
+
+	MB_DBG("IN, usr %lx TGID %x name %s\n", user, tgid, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+	mbu = mb_find_mbu((void *)user, tgid, MBUFIND_USER|MBUFIND_ALL);
+	if (!mbu) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_WARN("%s user to virt fail. unknow addr %lx\n", name, user);
+		return 0;
+	}
+
+	if (!mbu->mb)
+		MB_WARN("%s user to virt fail. unknow block (addr %lx)\n",
+			name, user);
+	else
+		virt = mbu->mb->virt;
+
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("OUT, Virt %p\n", virt);
+
+	return (unsigned long)virt;
+}
+EXPORT_SYMBOL(mb_do_user_to_virt);
+
+/* physical address */
+int mb_do_counter(unsigned long addr, char *name)
+{
+	struct mb_struct *mb;
+	unsigned long flags;
+	int counter = -1;
+
+	MB_DBG("IN, addr %#lx name %s\n", addr, name);
+
+	if (!addr || !wmt_mbah) {
+		MB_WARN("%s do counter fail. invalid args %p/%lx\n",
+			name, wmt_mbah, addr);
+		return -EINVAL;
+	}
+	spin_lock_irqsave(&mb_do_lock, flags);
+	mb = mb_find_mb((void *)addr, MBFIND_PHYS);
+	counter = (mb) ? MB_COUNT(mb) : -1;
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("OUT, addr %#lx count %d\n", addr, counter);
+
+	return counter;
+}
+EXPORT_SYMBOL(mb_do_counter);
+
+unsigned long mb_do_alloc(unsigned long size, pid_t tgid, char *name)
+{
+	struct mb_area_struct *entry, *mba = NULL;
+	struct mb_struct *mb = NULL;
+	struct mb_user *mbu = NULL;
+	unsigned long flags, addr;
+	unsigned int pages;
+	size_t ns; /* name size */
+
+	if (!name) {
+		MB_WARN("mb_alloc fail. null user tgid %x\n", tgid);
+		return 0;
+	}
+
+	size = PAGE_ALIGN(size);
+	pages = size >> PAGE_SHIFT;
+
+	if (!pages) {
+		MB_WARN("%s alloc fail. unavailable size %x(KB)\n",
+			name, 4*pages);
+		return 0;
+	}
+
+	mbu = kmem_cache_alloc(wmt_mbah->mbu_cachep, GFP_ATOMIC);
+	if (!mbu) {
+		MB_WARN("%s alloc fail. mbu_cachep out of memory.\n", name);
+		return 0;
+	}
+	memset(mbu, 0x0, sizeof(struct mb_user));
+
+	MB_DBG("IN, TGID %x size %ld(KB) name %s\n", tgid, size/1024, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+
+	if (pages > wmt_mbah->max_available_pages) {
+#ifdef CONFIG_WMT_MB_DYNAMIC_ALLOCATE_SUPPORT
+		mba = mb_alloc_mba(pages);
+		if (mba == NULL)
+			MB_WARN("%s alloc %u page fail. [MBA %lu/%lu/%lu]\n",
+				name, pages, wmt_mbah->max_available_pages,
+				wmt_mbah->tot_free_pages, wmt_mbah->tot_pages);
+#else
+		MB_DBG("DYNAMIC ALLOCATED(%u) unsuported. [MBA %lu/%lu/%lu]\n",
+			pages, wmt_mbah->max_available_pages,
+			wmt_mbah->tot_free_pages, wmt_mbah->tot_pages);
+		goto error;
+#endif
+	} else {
+		list_loop(entry, &wmt_mbah->mba_list, mba_list) {
+			if (entry->max_available_pages >= pages) {
+				mba = entry;
+				break;
+			}
+		}
+	}
+
+	if (!mba) {
+		MB_WARN("%s alloc fail. dedicated MBA not found\n", name);
+		goto error;
+	}
+
+	mb = mb_alloc_mb(mba, size);
+	if (mb == NULL) {
+		MB_WARN("%s alloc fail. create MB\n", name);
+		goto error;
+	}
+
+	INIT_LIST_HEAD(&mbu->mbu_list);
+	mbu->mb = mb;
+	mbu->tgid = tgid;
+	mbu->size = mb->size;
+	/* mbu->addr = 0; // address of creator is 0 */
+	ns = strlen(name);
+	if (ns > TASK_COMM_LEN)
+		ns = TASK_COMM_LEN;
+	strncpy(mbu->the_user, name, ns);
+	mbu->the_user[ns] = 0;
+	list_add_tail(&mbu->mbu_list, &mb->mbu_list);
+	atomic_inc(&mb->count);
+	mb->creator = mbu;
+	addr = mb->phys;
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("OUT, Addr %lx TGID %x size %ld(KB) name %s\n",
+		addr, tgid, size/1024, name);
+
+	return addr;
+
+error:
+
+	kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+	return 0;
+}
+EXPORT_SYMBOL(mb_do_alloc);
+
+/* physical address */
+int mb_do_free(unsigned long addr, pid_t tgid, char *name)
+{
+	struct mb_struct *mb;
+	struct mb_user *mbu;
+	unsigned long flags;
+	size_t ns; /* name size */
+	int ret;
+
+	if (!addr || !name) {
+		MB_WARN("mb_free fail. invalid args %lx/%s\n",
+			addr, name);
+		return -EINVAL;
+	}
+
+	MB_DBG("IN, TGID %x addr %#lx name %s\n", tgid, addr, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+	mbu = mb_find_mbu((void *)addr, tgid, MBUFIND_PHYS|MBUFIND_CREATOR);
+	if (!mbu || !mbu->mb) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_WARN("%s free fail. unknow addr %lx\n", name, addr);
+		return -EINVAL;
+	}
+
+	ns = strlen(name);
+	if (ns > TASK_COMM_LEN)
+		ns = TASK_COMM_LEN;
+	if (strncmp(mbu->the_user, name, ns))
+		MB_DBG("Owner no match. (%s/%s)\n", mbu->the_user, name);
+
+	mb = mbu->mb;
+
+	list_del(&mbu->mbu_list);
+	kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+	mb->creator = NULL;
+	atomic_dec(&mb->count);
+	if (MB_IN_USE(mb)) {
+		MB_DBG("<mb_free, MB %8lx still in use. Cnt %d>\n",
+			mb->phys, MB_COUNT(mb));
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		return 0;
+	}
+
+	ret = mb_free_mb(mb);
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("OUT\n");
+
+	return ret;
+}
+EXPORT_SYMBOL(mb_do_free);
+
+int mb_do_get(unsigned long addr, pid_t tgid, char *name)
+{
+	struct mb_user *mbu = NULL, *newmbu;
+	struct mb_struct *mb = NULL;
+	unsigned long flags;
+	size_t ns; /* name size */
+	void *virt = (void *)addr;
+
+	if (!addr || !name) {
+		MB_WARN("mb_do_get fail. invalid args %lx/%s\n",
+			addr, name);
+		return -EINVAL;
+	}
+
+	newmbu = kmem_cache_alloc(wmt_mbah->mbu_cachep, GFP_ATOMIC);
+	if (!newmbu) {
+		MB_DBG("<mbu_cachep out of memory.>\n");
+		return -ENOMEM;
+	}
+
+	MB_DBG("IN, TGID %x addr %#lx name %s\n", tgid, addr, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+	if (tgid != MB_DEF_TGID) { /* find user address, only exist on MMAP */
+		mbu = mb_find_mbu(virt, tgid, MBUFIND_USER|MBUFIND_MMAP);
+		mb = (mbu) ? mbu->mb : NULL;
+	} else
+		mb = mb_find_mb(virt, MBFIND_PHYS);
+
+	if (!mb) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		kmem_cache_free(wmt_mbah->mbu_cachep, newmbu);
+		MB_WARN("%s mb_get fail. unknown addr %8lx\n", name, addr);
+		return -EFAULT;
+	}
+
+	memset(newmbu, 0x0, sizeof(struct mb_user));
+	INIT_LIST_HEAD(&newmbu->mbu_list);
+	newmbu->addr = addr;
+	newmbu->mb = mb;
+	newmbu->tgid = tgid;
+	ns = strlen(name);
+	if (ns > TASK_COMM_LEN)
+		ns = TASK_COMM_LEN;
+	strncpy(newmbu->the_user, name, ns);
+	newmbu->the_user[ns] = 0;
+	atomic_inc(&mb->count);
+	list_add_tail(&newmbu->mbu_list, &mb->mbu_list);
+
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	MB_DBG("out, [mbu] addr %lx %s [mb] addr %lx cnt %d\n",
+		addr, newmbu->the_user, mb->phys, MB_COUNT(mb));
+
+	return 0;
+}
+EXPORT_SYMBOL(mb_do_get);
+
+int mb_do_put(unsigned long addr, pid_t tgid, char *name)
+{
+	struct mb_struct *mb;
+	struct mb_user *mbu;
+	unsigned long flags;
+	void *virt = (void *)addr;
+
+	if (!addr || !name) {
+		MB_WARN("mb_do_put fail. invalid args %lx/%s\n", addr, name);
+		return -EINVAL;
+	}
+
+	MB_DBG("IN, TGID %x addr %#lx name %s\n", tgid, addr, name);
+
+	spin_lock_irqsave(&mb_do_lock, flags);
+	if (tgid == MB_DEF_TGID)
+		mbu = mb_find_mbu(virt, tgid, MBUFIND_PHYS|MBUFIND_GETPUT);
+	else
+		mbu = mb_find_mbu(virt, tgid, MBUFIND_USER|MBUFIND_GETPUT);
+
+	if (!mbu) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_WARN("%s mb_put fail. unknow addr %8lx\n", name, addr);
+		return -EINVAL;
+	}
+
+	mb = mbu->mb;
+	if (!MB_IN_USE(mb)) {
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_WARN("%s mb_put fail. block %p unbalance.\n", name, mb);
+		return -EPERM;
+	}
+
+	list_del_init(&mbu->mbu_list);
+	atomic_dec(&mb->count);
+	/* retrieve unused block */
+	if (!MB_IN_USE(mb))
+		mb_free_mb(mb);
+
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+	kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+
+	MB_DBG("out, [mbu] addr %lx %s [mb] addr %lx cnt %d\n",
+		addr, mbu->the_user, mb->phys, MB_COUNT(mb));
+
+	return 0;
+}
+EXPORT_SYMBOL(mb_do_put);
+
+#define DEVICE_NAME "Memory Block"
+
+static int mb_dev_major;
+static int mb_dev_minor;
+static int mb_dev_nr;
+static struct cdev *mb_cdev;
+static struct class *mb_dev_class;
+
+static int mb_open(struct inode *inode, struct file *filp)
+{
+	struct mb_task_info *mbti = NULL;
+	unsigned long flags;
+	int task_exist = 0;
+	size_t ns;
+
+	if (filp->private_data) {
+		MB_ERROR("none empty private data.\n");
+		return -EFAULT;
+	}
+
+	spin_lock_irqsave(&mb_task_lock, flags);
+	list_loop(mbti, &wmt_mbti.mbti_list, mbti_list) {
+		if (mbti->task && mbti->tgid == current->tgid) {
+			task_exist = 1;
+			break;
+		}
+	}
+	if (!task_exist) {
+		mbti = kmem_cache_alloc(wmt_mbah->mbti_cachep, GFP_ATOMIC);
+		if (!mbti) {
+			spin_unlock_irqrestore(&mb_task_lock, flags);
+			MB_ERROR("out of memory (mb_task_info).\n");
+			return -EFAULT;
+		}
+		memset(mbti, 0x0, sizeof(struct mb_task_info));
+		INIT_LIST_HEAD(&mbti->mbti_list);
+		mbti->task = current;
+		mbti->tgid = current->tgid;
+		ns = strlen(current->comm);
+		if (ns > TASK_COMM_LEN)
+			ns = TASK_COMM_LEN;
+		strncpy(mbti->task_name, current->comm, ns);
+		mbti->task_name[ns] = 0;
+		atomic_set(&mbti->count, 0);
+		list_add_tail(&mbti->mbti_list, &wmt_mbti.mbti_list);
+	}
+	atomic_inc(&mbti->count);
+	MB_DBG("mb driver is opened by task(%p) %s TGID %x count %d.\n",
+		current, current->comm, current->tgid,
+		atomic_read(&(mbti->count)));
+	filp->private_data = (void *)mbti;
+	spin_unlock_irqrestore(&mb_task_lock, flags);
+
+	return 0;
+}
+
+static int mb_release(struct inode *inode, struct file *filp)
+{
+	struct mb_area_struct *mba;
+	struct mb_struct *mb;
+	struct mb_user *mbu;
+	struct mb_task_info *cmbti = NULL, *mbti = NULL;
+	unsigned long flags, tflags;
+	int task_exist = 0;
+
+	cmbti = (struct mb_task_info *)(filp->private_data);
+	if (!cmbti) {
+		MB_ERROR("none empty private data.\n");
+		return -EFAULT;
+	}
+
+	spin_lock_irqsave(&mb_task_lock, tflags);
+	list_loop(mbti, &wmt_mbti.mbti_list, mbti_list) {
+		if (mbti->task && mbti->tgid == cmbti->tgid) {
+			atomic_dec(&mbti->count);
+			task_exist = 1;
+			break;
+		}
+	}
+	if (!task_exist) {
+		spin_unlock_irqrestore(&mb_task_lock, tflags);
+		MB_INFO("mb driver is closed by unknown task %s TGID %x.\n",
+		current->comm, current->tgid);
+		return 0;
+	}
+
+	MB_DBG("mb driver is closed by task %s TGID %x cnt %d.\n",
+		mbti->task_name, mbti->tgid, atomic_read(&mbti->count));
+	if (atomic_read(&mbti->count)) {
+		spin_unlock_irqrestore(&mb_task_lock, tflags);
+		return 0;
+	}
+
+	spin_lock_irqsave(&mb_ioctl_lock, flags);
+RESCAN_MBA:
+	/* munmap virtual memroy and retrieve unused MB */
+	list_loop(mba, &wmt_mbah->mba_list, mba_list) {
+#ifdef CONFIG_WMT_MB_DYNAMIC_ALLOCATE_SUPPORT
+		if (mba->tgid == mbti->tgid) { /* free prefetched mba marker */
+			wmt_mbah->tot_static_pages -= mba->pages;
+			mba->flags &= ~(MBAFLAG_STATIC);
+			mba->tgid = MB_DEF_TGID;
+			if (!mba->nr_mb) {
+				mb_free_mba(mba);
+				goto RESCAN_MBA;
+			}
+		}
+#endif
+		list_loop(mb, &mba->mb_list, mb_list) {
+RESCAN_MBU:
+			list_loop(mbu, &mb->mbu_list, mbu_list) {
+				if (mbu->tgid == mbti->tgid) {
+					char msg[128], *p = msg;
+					const char *opStr[3] = {
+						"\"ALLOC\"",
+						"\"MAP\"",
+						"\"GET\""};
+					int op = (mbu->size) ? 1 : 2;
+					if (mb->creator == mbu) {
+						op = 0;
+						mb->creator = NULL;
+					}
+					p += sprintf(p, "Stop mb operation %s",
+						opStr[op]);
+					p += sprintf(p, "(addr %lx # %lu(KB) ",
+						mb->phys, mbu->size/1024);
+					p += sprintf(p, "by %s) (Cnt %d)\n",
+						 mbu->the_user, MB_COUNT(mb)-1);
+					MB_INFO("%s", msg);
+					atomic_dec(&mb->count);
+					list_del_init(&mbu->mbu_list);
+					kmem_cache_free(
+						wmt_mbah->mbu_cachep, mbu);
+					if (MB_COUNT(mb))
+						goto RESCAN_MBU;
+					MB_INFO("Recycle mb addr %lx # %lu\n",
+						mb->phys, mb->size);
+					mb_free_mb(mb);
+					goto RESCAN_MBA;
+				}
+			}
+		}
+	}
+
+	mb_update_mbah();
+	list_del(&mbti->mbti_list);
+	kmem_cache_free(wmt_mbah->mbti_cachep, mbti);
+	filp->private_data = NULL;
+	spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+	spin_unlock_irqrestore(&mb_task_lock, tflags);
+
+	return 0;
+}
+
+static long mb_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct mb_task_info *mbti = NULL;
+	struct mb_area_struct *mba = NULL;
+	struct mb_struct *mb = NULL;
+	struct mb_user *mbu = NULL;
+	unsigned long value, flags, phys, virt, size;
+	pid_t tgid = MB_DEF_TGID;
+	int count, ret = 0, cmdSize;
+	size_t len;
+
+	/* check type and number, if fail return ENOTTY */
+#ifdef CONFIG_WMT_MB_RESERVE_FROM_IO
+	if (_IOC_TYPE(cmd) != MB_IOC_MAGIC && cmd != FBIOGET_FSCREENINFO)
+		return -ENOTTY;
+#else
+	if (_IOC_TYPE(cmd) != MB_IOC_MAGIC)
+		return -ENOTTY;
+#endif
+
+	/* check argument area */
+	cmdSize = _IOC_SIZE(cmd);
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ret = !access_ok(VERIFY_WRITE, (void __user *) arg, cmdSize);
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		ret = !access_ok(VERIFY_READ, (void __user *) arg, cmdSize);
+
+	if (ret)
+		return -EFAULT;
+
+	/* check task validation */
+	if (!filp || !filp->private_data) {
+		MB_ERROR("mmap with null file info or task.\n");
+		return -EFAULT;
+	}
+
+	mbti = (struct mb_task_info *)(filp->private_data);
+	tgid = mbti->tgid;
+	if (tgid != current->tgid) {
+		MB_WARN("ioctl within diff task.\n");
+		MB_WARN("Open: task %s TGID %x VS Curr: task %s TGID %x\n",
+			mbti->task_name, tgid, current->comm, current->tgid);
+	}
+
+	switch (cmd) {
+	/* _IOR (MB_IOC_MAGIC, 16, unsigned long) O: mb driver version */
+	case MBIO_GET_VERSION:
+		value = MB_VERSION_MAJOR << 24 |
+			MB_VERSION_MINOR << 16 |
+			MB_VERSION_MICRO << 8  |
+			MB_VERSION_BUILD;
+		put_user(value, (unsigned long *)arg);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 0, unsigned long)
+	 *  I: size
+	 *  O: physical address */
+	case MBIO_MALLOC:
+		get_user(value, (unsigned long *)arg);
+		phys = mb_do_alloc(value, tgid, mbti->task_name);
+		if (!phys) {
+			MB_WARN("MALLOC: size %ld fail.\n\n", value);
+			return -EFAULT;
+		}
+		MB_OPDBG("MALLOC: addr %lx size %ld\n\n", phys, value);
+		put_user(phys, (unsigned long *)arg);
+		break;
+
+	/* _IOW (MB_IOC_MAGIC, 17, unsigned long) O: property of MB */
+	case MBIO_SET_CACHABLE:
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_do_lock, flags);
+		mb = mb_find_mb((void *)value, MBFIND_PHYS);
+		if (!mb) {
+			spin_unlock_irqrestore(&mb_do_lock, flags);
+			MB_WARN("SET_CACHABLE: phys %8lx (name %s) fail\n",
+				value, mbti->task_name);
+			return -EFAULT;
+		}
+		mb->flags |= MBFLAG_CACHED;
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_OPDBG("SET_CACHABLE: phys %8lx\n\n", value);
+		break;
+
+	/* _IOW (MB_IOC_MAGIC,18, unsigned long) O: property of MB */
+	case MBIO_CLR_CACHABLE:
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_do_lock, flags);
+		mb = mb_find_mb((void *)value, MBFIND_PHYS);
+		if (!mb) {
+			spin_unlock_irqrestore(&mb_do_lock, flags);
+			MB_WARN("CLR_CACHABLE: phys %8lx (name %s) fail\n",
+				value, mbti->task_name);
+			return -EFAULT;
+		}
+		mb->flags &= ~MBFLAG_CACHED;
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_OPDBG("CLR_CACHABLE: phys %8lx\n\n", value);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 1, unsigned long)
+	 *  I: user address if map, physical address if not map
+	 *  O: ummap size */
+	case MBIO_FREE: /* if not unmap, unmap first */
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		size = value;
+		mbu = mb_find_mbu((void *)value, tgid,
+			MBUFIND_USER|MBUFIND_MMAP);
+		if (mbu != NULL) {
+			size = mbu->size;
+			value = mbu->mb->phys;
+			list_del(&mbu->mbu_list);
+			atomic_dec(&mbu->mb->count);
+			kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+		} else
+			MB_DBG("FREE: unknown MMAP addr %lx\n", value);
+		ret = mb_do_free(value, tgid, mbti->task_name);
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		if (ret < 0)
+			MB_WARN("FREE: addr %lx fail\n", value);
+		/* return mmap size for ummap */
+		put_user(size, (unsigned long *)arg);
+		MB_OPDBG("FREE: addr %lx out %ld\n\n", value, size);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 2, unsigned long)
+	 *  I: user address
+	 *  O: ummap size */
+	case MBIO_UNMAP:
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		mbu = mb_find_mbu((void *)value, tgid,
+			MBUFIND_USER|MBUFIND_MMAP);
+		if (mbu == NULL) {
+			spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+			MB_WARN("UNMAP: addr %lx fail\n\n", value);
+			return -EFAULT;
+		}
+		mb = mbu->mb;
+		size = mbu->size;
+		list_del(&mbu->mbu_list);
+		kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+		atomic_dec(&mb->count);
+		count = MB_COUNT(mb);
+		if (count <= 0)
+			MB_WARN("UNMAP: MB %8lx count %d weird\n\n",
+				mb->phys, count);
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		 /* return mmap size for ummap */
+		put_user(size, (unsigned long *)arg);
+		return 0;
+
+	/* _IOWR(MB_IOC_MAGIC, 3, unsigned long)
+	 *  I: phys address
+	 *  O: mb size */
+	case MBIO_MBSIZE:
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		mb = mb_find_mb((void *)value, MBFIND_PHYS);
+		if (mb == NULL) {
+			spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+			MB_WARN("MBSIZE: user %lx fail.\n\n", value);
+			return -EFAULT;
+		}
+		size = mb->size;
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		MB_OPDBG("MBSIZE: addr %lx size %ld\n\n", value, size);
+		put_user(size, (unsigned long *)arg);
+		break;
+
+	/* _IOR (MB_IOC_MAGIC, 4, unsigned long)
+	 *  O: max free mba size */
+	case MBIO_MAX_AVAILABLE_SIZE:
+		put_user(wmt_mbah->max_available_pages*PAGE_SIZE,
+			(unsigned long *)arg);
+		MB_OPDBG("MAX_MB_SIZE: size %ld KB\n\n",
+			PAGE_KB(wmt_mbah->max_available_pages));
+		break;
+
+	/* _IOW (MB_IOC_MAGIC, 5, unsigned long)
+	 *  I: user address */
+	case MBIO_GET:
+		get_user(value, (unsigned long *)arg);
+		ret = mb_do_get(value, tgid, mbti->task_name);
+		if (MBMSG_LEVEL) {
+			spin_lock_irqsave(&mb_ioctl_lock, flags);
+			mbu = mb_find_mbu((void *)value, tgid,
+				MBUFIND_USER|MBUFIND_GETPUT);
+			count = mbu ? MB_COUNT(mbu->mb) : 0xffffffff;
+			MB_OPDBG("GET: addr %lx cnt %x\n\n", value, count);
+			spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		}
+		break;
+
+	/* _IOW (MB_IOC_MAGIC, 6, unsigned long)
+	 *  I: user address */
+	case MBIO_PUT:
+		get_user(value, (unsigned long *)arg);
+		if (MBMSG_LEVEL) {
+			spin_lock_irqsave(&mb_ioctl_lock, flags);
+			mbu = mb_find_mbu((void *)value, tgid,
+				MBUFIND_USER|MBUFIND_GETPUT);
+			count = mbu ? MB_COUNT(mbu->mb) - 1 : 0xffffffff;
+			MB_OPDBG("PUT: addr %lx cnt %x\n\n", value, count);
+			spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		}
+		ret = mb_do_put(value, tgid, mbti->task_name);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 7, unsigned long)
+	 *  I: user address
+	 *  O: virt address */
+	case MBIO_USER_TO_VIRT:
+		get_user(value, (unsigned long *)arg);
+		virt = mb_do_user_to_virt(value, tgid, mbti->task_name);
+		put_user(virt, (unsigned long *)arg);
+		MB_OPDBG("USER_TO_VERT: user %8lx virt %lx\n\n", value, virt);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 8, unsigned long)
+	 *  I: user address
+	 *  O: phys address */
+	case MBIO_USER_TO_PHYS:
+		get_user(value, (unsigned long *)arg);
+		phys = mb_do_user_to_phys(value, tgid, mbti->task_name);
+		put_user(phys, (unsigned long *)arg);
+		MB_OPDBG("USER_TO_PHYS: user %8lx phys %lx\n\n", value, phys);
+		break;
+
+#ifdef CONFIG_WMT_MB_RESERVE_FROM_IO
+	/* This IOCTRL is provide AP to recognize MB region as framebuffer,
+	then can access mb memory directly. */
+	case MBIO_FSCREENINFO:
+	{
+		struct fb_fix_screeninfo ffs;
+
+		if (!wmt_mbah || list_empty(&wmt_mbah->mba_list)) {
+			MB_WARN("MBIO_FSCREENINFO: MB driver does not init.\n");
+			return -EFAULT;
+		}
+
+		mba = (struct mb_area_struct *)wmt_mbah->mba_list.next;
+		ffs.smem_start = mba->phys;
+		ffs.smem_len = wmt_mbah->tot_static_pages * PAGE_SIZE;
+		if (copy_to_user((void __user *)arg, &ffs, sizeof(ffs)))
+			ret = -EFAULT;
+		MB_OPDBG("FSCREENINFO: phys %lx len %x\n\n",
+			ffs.smem_start, ffs.smem_len);
+		break;
+	}
+#endif
+
+	/* _IOW (MB_IOC_MAGIC, 9, unsigned long)
+	 *  I: size */
+	case MBIO_PREFETCH:
+	{
+		unsigned long fetch_size = 0;
+		get_user(value, (unsigned long *)arg);
+#ifdef CONFIG_WMT_MB_DYNAMIC_ALLOCATE_SUPPORT
+{
+		unsigned long try_size = 0;
+
+		MB_OPDBG("PREFETCH: size %ld KB\n\n", value/1024);
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		while (try_size < value) {
+			int order;
+			order = get_order(value-fetch_size);
+			if (order > MBMAX_ORDER)
+				order = MBMAX_ORDER;
+			try_size += (1 << order) * PAGE_SIZE;
+			mba = mb_alloc_mba(1 << order);
+			if (mba) {
+				mba->flags |= MBAFLAG_STATIC;
+				mba->tgid = current->tgid;
+				wmt_mbah->tot_static_pages += mba->pages;
+				fetch_size += mba->pages * PAGE_SIZE;
+			}
+		}
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		MB_INFO("PREFETCH: SIZE %ld / %ld kB by %s\n",
+			fetch_size/1024, value/1024, current->comm);
+}
+#else
+		MB_WARN("PREFETCH: SIZE %ld / %ld kB by %s fail\n",
+			fetch_size/1024, value/1024, current->comm);
+		MB_WARN("PREFETCH: Dynamic Allocated Not Support\n");
+		ret = -ENOTTY;
+#endif
+		break;
+	}
+
+	/* _IOW (MB_IOC_MAGIC, 10, unsigned long)
+	 *  O: static mba size */
+	case MBIO_STATIC_SIZE:
+		put_user(wmt_mbah->tot_static_pages * PAGE_SIZE,
+			(unsigned long *)arg);
+		MB_OPDBG("STATIC_SIZE: size %ld KB\n\n",
+			PAGE_KB(wmt_mbah->tot_static_pages));
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC,11, unsigned long)
+	 *  I: physical address
+	 *  O: use counter */
+	case MBIO_MB_USER_COUNT:
+		get_user(value, (unsigned long *)arg);
+
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		mb = mb_find_mb((void *)value, MBFIND_PHYS);
+		if (mb == NULL)
+			size = 0;
+		else
+			size = MB_COUNT(mb);
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+
+		put_user(size, (unsigned long *)arg);
+		MB_OPDBG("USER_COUNT: addr %lx count %ld\n\n", value, size);
+		break;
+
+	/* _IO  (MB_IOC_MAGIC,12) */
+	case MBIO_FORCE_RESET:
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+RESCAN_MBA:
+		list_loop(mba, &wmt_mbah->mba_list, mba_list) {
+			list_loop(mb, &mba->mb_list, mb_list) {
+				list_loop(
+					mbu, &mb->mbu_list, mbu_list) {
+					list_del(&mbu->mbu_list);
+					kmem_cache_free(
+						wmt_mbah->mbu_cachep, mbu);
+				}
+				mb->creator = NULL;
+				atomic_set(&mb->count, 0);
+				mb_free_mb(mb);
+				/* because mba link maybe breaken */
+				goto RESCAN_MBA;
+			}
+		}
+		mb_update_mbah();
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		MB_OPDBG("RESET: OK\n\n");
+		break;
+
+	/* _IOW (MB_IOC_MAGIC,13, unsigned long) // I: phys address */
+	case MBIO_GET_BY_PHYS:
+		get_user(value, (unsigned long *)arg);
+		if (!value || !mbti->task_name || tgid == MB_DEF_TGID) {
+			MB_WARN("GET(phys): invalid args %lx/%d/%s\n",
+				value, tgid, mbti->task_name);
+			return -EINVAL;
+		}
+
+		mbu = kmem_cache_alloc(wmt_mbah->mbu_cachep, GFP_ATOMIC);
+		if (!mbu) {
+			MB_WARN("GET(phys): mbu_cachep out of memory\n");
+			return -ENOMEM;
+		}
+
+		spin_lock_irqsave(&mb_do_lock, flags);
+		mb = mb_find_mb((void *)value, MBFIND_PHYS);
+		if (!mb) {
+			spin_unlock_irqrestore(&mb_do_lock, flags);
+			kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+			MB_WARN("GET(phys): unknown phys %8lx name %s\n",
+				value, mbti->task_name);
+			return -EFAULT;
+		}
+
+		memset(mbu, 0x0, sizeof(struct mb_user));
+		INIT_LIST_HEAD(&mbu->mbu_list);
+		mbu->addr = value;
+		mbu->mb = mb;
+		mbu->tgid = tgid;
+		len = strlen(mbti->task_name);
+		if (len > TASK_COMM_LEN)
+			len = TASK_COMM_LEN;
+		strncpy(mbu->the_user, mbti->task_name, len);
+		mbu->the_user[len] = 0;
+		atomic_inc(&mb->count);
+		list_add_tail(&mbu->mbu_list, &mb->mbu_list);
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		MB_OPDBG("GET(phys): phys %8lx cnt %x\n\n",
+			value, MB_COUNT(mb));
+		break;
+
+	/* _IOW (MB_IOC_MAGIC,14, unsigned long) // I: phys address */
+	case MBIO_PUT_BY_PHYS:
+		get_user(value, (unsigned long *)arg);
+		if (!value || !mbti->task_name || tgid == MB_DEF_TGID) {
+			MB_WARN("PUT(phys): invalid args %lx/%d/%s\n",
+				value, tgid, mbti->task_name);
+			return -EINVAL;
+		}
+
+		spin_lock_irqsave(&mb_do_lock, flags);
+		mbu = mb_find_mbu((void *)value, tgid,
+			MBUFIND_PHYS|MBUFIND_GETPUT);
+		if (!mbu) {
+			spin_unlock_irqrestore(&mb_do_lock, flags);
+			MB_WARN("PUT(phys): unknow phys %8lx name %s\n",
+				value, mbti->task_name);
+			return -EINVAL;
+		}
+
+		mb = mbu->mb;
+		if (!MB_IN_USE(mb)) {
+			spin_unlock_irqrestore(&mb_do_lock, flags);
+			MB_WARN("PUT(phys): phys %8lx unbalance.\n", value);
+			return -EPERM;
+		}
+
+		list_del_init(&mbu->mbu_list);
+		atomic_dec(&mb->count);
+		size = MB_COUNT(mb);
+		/* retrieve unused block */
+		if (!size)
+			mb_free_mb(mb);
+
+		spin_unlock_irqrestore(&mb_do_lock, flags);
+		kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+
+		MB_OPDBG("PUT(phys): phys %8lx cnt %lx\n\n", value, size);
+
+		break;
+
+	/* _IOW (MB_IOC_MAGIC,15, unsigned long) // I: user address */
+	case MBIO_SYNC_CACHE:
+		get_user(value, (unsigned long *)arg);
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		mbu = mb_find_mbu((void *)value, tgid,
+			MBUFIND_USER|MBUFIND_MMAP);
+		if (mbu == NULL) {
+			spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+			MB_WARN("SYNC_CACHE: invalid addr %lx\n\n", value);
+			return -EFAULT;
+		}
+		mb = mbu->mb;
+		size = mbu->size;
+		dmac_flush_range(mb->virt, mb->virt + size);
+		outer_flush_range(mb->phys, mb->phys + size);
+		MB_OPDBG("SYNC_CACHE: (%lx # %lx) V %p ~ %p P %lx ~ %lx\n\n",
+			value, size, mb->virt, mb->virt + size,
+			mb->phys, mb->phys + size);
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		return 0;
+
+	/* _IOW(MB_IOC_MAGIC, 19, unsigned long) // I: phys address */
+	case MBIO_STATIC_GET:
+		get_user(value, (unsigned long *)arg);
+		if (!value || !mbti->task_name || tgid == MB_DEF_TGID) {
+			MB_WARN("GET(STATIC): invalid args %lx/%d/%s\n",
+				value, tgid, mbti->task_name);
+			return -EINVAL;
+		}
+
+		ret = mb_do_get(value, MB_DEF_TGID, mbti->task_name);
+		if (ret != 0)
+			MB_WARN("GET(STATIC): fail (args %lx/%d/%s). ret %d\n",
+				value, tgid, mbti->task_name, ret);
+		MB_OPDBG("GET(STATIC): phys %8lx done\n\n", value);
+		break;
+
+	/* _IOW(MB_IOC_MAGIC, 20, unsigned long) // I: phys address */
+	case MBIO_STATIC_PUT:
+		get_user(value, (unsigned long *)arg);
+		if (!value || !mbti->task_name || tgid == MB_DEF_TGID) {
+			MB_WARN("PUT(STATIC): invalid args %lx/%d/%s\n",
+				value, tgid, mbti->task_name);
+			return -EINVAL;
+		}
+
+		ret = mb_do_put(value, MB_DEF_TGID, mbti->task_name);
+		if (ret != 0)
+			MB_WARN("PUT(STATIC): fail (args %lx/%d/%s). ret %d\n",
+				value, tgid, mbti->task_name, ret);
+		MB_OPDBG("PUT(STATIC): phys %8lx done\n\n", value);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 100, unsigned long)
+	   I: user address O: physical address */
+	case MBIO_TEST_USER2PHYS:
+		get_user(value, (unsigned long *)arg);
+		if (!value) {
+			MB_WARN("USER2PHYS: invalid args %lx/%d/%s\n",
+				value, tgid, mbti->task_name);
+			return -EINVAL;
+		}
+		phys = user_to_phys(value);
+		put_user(phys, (unsigned long *)arg);
+		if (!phys)
+			MB_WARN("USER2PHYS fail: value %#lx phys %#lx\n", value, phys);
+		break;
+
+	/* _IOWR(MB_IOC_MAGIC, 101, unsigned long)
+	   I: user address, size, prdt addr, and prdt size */
+	case MBIO_TEST_USER2PRDT:
+	/* _IOW(MB_IOC_MAGIC, 103, unsigned long)
+	*  I: user address, size, prdt addr, and prdt size */
+	case MBIO_TEST_MB2PRDT: {
+		int items, type = (cmd == MBIO_TEST_MB2PRDT) ? 0 : 1;
+		unsigned long size,  data[4] = {0};
+		struct prdt_struct *prdt;
+		copy_from_user(data, (const void *)arg, 4 * sizeof(unsigned long));
+		if (!data[0] || !data[1] || !data[2] || !data[3]) {
+			MB_WARN("%s: invalid args [%#lx, %#lx, %#lx, %#lx]\n",
+				type ? "MB2PRDT" : "USER2PRDT",
+				data[0], data[1], data[2], data[3]);
+			return -EINVAL;
+		}
+		items = data[1] / PAGE_SIZE + 2;
+		size = items * sizeof(struct prdt_struct);
+		if (data[3] < size) {
+			MB_WARN("%s: invalid args. prdt size %#lx < %#lx\n",
+				type ? "MB2PRDT" : "USER2PRDT", data[3], size);
+			return -EINVAL;
+		}
+		prdt = kmalloc(size, GFP_ATOMIC);
+		if (prdt == NULL) {
+			MB_WARN("%s: fail, no prdt space %d for size %ld\n",
+				type ? "MB2PRDT" : "USER2PRDT",
+				items * sizeof(struct prdt_struct), data[1]);
+			return -EINVAL;
+		}
+		MB_DBG("%s: IN %#lx, %#lx, %#lx, %#lx\n",
+			type ? "MB2PRDT" : "USER2PRDT",
+			data[0], data[1], data[2], data[3]);
+		memset(prdt, 0x0, items * sizeof(struct prdt_struct));
+		if ((!type && !mb_to_prdt(data[0], data[1], prdt, items)) ||
+			(!user_to_prdt(data[0], data[1], prdt, items))) {
+			if (MBMSG_LEVEL)
+				show_prdt(prdt);
+			copy_to_user((void __user *)data[2], prdt, size);
+			MB_INFO("%s: Done %#lx, %#lx, %#lx, %#lx\n",
+				type ? "MB2PRDT" : "USER2PRDT",
+				data[0], data[1], data[2], data[3]);
+		} else {
+			MB_WARN("%s: fail.\n", type ? "MB2PRDT" : "USER2PRDT");
+			ret = -EINVAL;
+		}
+		kfree(prdt);
+		break;
+	}
+
+	/* _IOWR(MB_IOC_MAGIC, 102, unsigned long)
+	   I: user address, size, mmu addr, and mmu size O: mmu physical addr */
+	case MBIO_TEST_USER2MMUT:
+	/* _IOWR(MB_IOC_MAGIC, 104, unsigned long)
+	   I: user address, size, mmu addr, and mmu size O: mmu physical addr */
+	case MBIO_TEST_MB2MMUT: {
+		int type = (cmd == MBIO_TEST_MB2MMUT) ? 0 : 1;
+		unsigned long mmuSize, data[4] = {0};
+		struct mmu_table_info info = {0};
+		copy_from_user(data, (const void *)arg, 4 * sizeof(unsigned long));
+		if (!data[0] || !data[1] || !data[2] || !data[3]) {
+			MB_WARN("%s: invalid args [%#lx, %#lx, %#lx, %#lx]\n",
+				type ? "USER2MMUT" : "PHYS2MMUT",
+				data[0], data[1], data[2], data[3]);
+			return -EINVAL;
+		}
+		mmuSize = wmt_mmu_table_size(data[1]);
+		if (data[3] < mmuSize) {
+			MB_WARN("%s: invalid args. mmu size %#lx < %#lx\n",
+				type ? "MB2PRDT" : "USER2PRDT", data[3], mmuSize);
+			return -EINVAL;
+		}
+		MB_DBG("%s: IN %#lx, %#lx, %#lx, %#lx(req %#lx)\n",
+			type ? "USER2MMUT" : "PHYS2MMUT",
+			data[0], data[1], data[2], data[3], mmuSize);
+		if (wmt_mmu_table_create(data[0], data[1], type, &info) == 0) {
+			void *mmuAddr = mb_phys_to_virt((unsigned long)info.addr);
+			if (MBMSG_LEVEL)
+				wmt_mmu_table_dump(&info);
+			copy_to_user((void __user *)data[2], mmuAddr, mmuSize);
+			put_user(info.addr, (unsigned long *)arg);
+			ret = mb_do_get(info.addr, MB_DEF_TGID, mbti->task_name);
+			wmt_mmu_table_destroy(&info);
+			MB_INFO("%s: Done %#lx, %#lx, %#lx, %#lx\n",
+				type ? "USER2MMUT" : "PHYS2MMUT",
+				data[0], data[1], data[2], data[3]);
+		} else {
+			MB_WARN("%s: fail. no mmu table space for size %ld\n",
+				type ? "USER2MMUT" : "PHYS2MMUT", data[1]);
+			return -EINVAL;
+		}
+		break;
+	}
+
+	default:
+		ret = -ENOTTY;
+		break;
+	}
+
+	return ret;
+}
+
+static int mb_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct mb_user *mbu = NULL;
+	struct mb_task_info *mbti;
+	struct mb_struct *mb;
+	unsigned long off, flags;
+	unsigned int len;
+	pid_t tgid;
+	size_t ns;
+
+	if (!filp || !filp->private_data) {
+		MB_ERROR("mmap with null file info or task.\n");
+		return -EFAULT;
+	}
+
+	mbti = (struct mb_task_info *)(filp->private_data);
+	tgid = mbti->tgid;
+	if (tgid != current->tgid) {
+		MB_WARN("mmap within diff task.\n");
+		MB_WARN("Open: task %s TGID %x VS Curr: task %s TGID %x\n",
+			mbti->task_name, tgid, current->comm, current->tgid);
+	}
+
+	off = vma->vm_pgoff << PAGE_SHIFT;
+	MB_DBG("IN, offset %lx TGID %x name %s\n", off, tgid, mbti->task_name);
+#ifdef CONFIG_WMT_MB_RESERVE_FROM_IO
+	/* if page offset under MB total size, it means page offset
+	 * is not physical address from MB_alloc and then map function
+	 * works like framebuffer.
+	 * Suppose MB total size will not cross MBAH phys start address */
+	if (vma->vm_pgoff <= wmt_mbah->tot_static_pages) {
+		struct mb_area_struct *mba = NULL;
+		unsigned long mbtotal =
+			wmt_mbah->tot_static_pages << PAGE_SHIFT;
+		if ((vma->vm_end - vma->vm_start + off) > mbtotal) {
+			MB_ERROR("mmap io fail. range %lx @ [%lx, %lx] s %lx\n",
+				off, vma->vm_start, vma->vm_end, mbtotal);
+			return -EINVAL;
+		}
+		mba = (struct mb_area_struct *)wmt_mbah->mba_list.next;
+		vma->vm_pgoff += mba->phys >> PAGE_SHIFT;
+		vma->vm_flags |= VM_IO | VM_RESERVED;
+		if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+			vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+			MB_ERROR("mmap io fail. (io_remap pfn %lx len %lx)\n",
+				vma->vm_pgoff, vma->vm_end - vma->vm_start);
+			return -EAGAIN;
+		}
+		MB_OPDBG("MAP: IO from %lx to %lx/%lx size %ld\n\n",
+			vma->vm_pgoff << PAGE_SHIFT,
+			vma->vm_start, vma->vm_end,
+			vma->vm_end - vma->vm_start);
+		return 0;
+	}
+#endif
+
+	mbu = kmem_cache_alloc(wmt_mbah->mbu_cachep, GFP_ATOMIC);
+	if (!mbu) {
+		MB_ERROR("mbu_cachep out of memory.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&mb_ioctl_lock, flags);
+	mb = mb_find_mb((void *)off, MBFIND_PHYS);
+	if (!mb) {
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+		MB_ERROR("map addr %lx not exist in MB.\n", off);
+		return -EINVAL;
+	}
+
+	len = PAGE_ALIGN(mb->phys + mb->size);
+	if ((vma->vm_end - vma->vm_start + off) > len) {
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+		return -EINVAL;
+	}
+
+	memset(mbu, 0x0, sizeof(struct mb_user));
+	INIT_LIST_HEAD(&mbu->mbu_list);
+	mbu->tgid = tgid;
+	mbu->mb = mb;
+	mbu->addr = vma->vm_start;
+	mbu->size = vma->vm_end - vma->vm_start;
+	ns = strlen(mbti->task_name);
+	if (ns > TASK_COMM_LEN)
+		ns = TASK_COMM_LEN;
+	strncpy(mbu->the_user, mbti->task_name, ns);
+	mbu->the_user[ns] = 0;
+	list_add_tail(&mbu->mbu_list, &mb->mbu_list);
+	atomic_inc(&mb->count);
+
+	off = mb->phys;
+	spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	if (!(mb->flags & MBFLAG_CACHED))
+		vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+		vma->vm_end - vma->vm_start, vma->vm_page_prot)) {
+		spin_lock_irqsave(&mb_ioctl_lock, flags);
+		list_del(&mbu->mbu_list);
+		atomic_dec(&mb->count);
+		kmem_cache_free(wmt_mbah->mbu_cachep, mbu);
+		spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+		MB_ERROR("virtual address memory map fail.\n");
+		return -EAGAIN;
+	}
+
+	MB_OPDBG("MAP: IO from %lx to %lx/%lx size %ld mbcnt %d\n\n",
+		off, vma->vm_start, vma->vm_end,
+		(vma->vm_end - vma->vm_start), MB_COUNT(mb));
+
+	return 0;
+}
+
+/*!*************************************************************************
+    driver file operations struct define
+****************************************************************************/
+const struct file_operations mb_fops = {
+	.owner = THIS_MODULE,
+	.open = mb_open,
+	.release = mb_release,
+	.unlocked_ioctl = mb_ioctl,
+	.mmap = mb_mmap,
+};
+
+static int mb_probe(struct platform_device *dev)
+{
+	struct mb_area_struct *mba = NULL, *bind = NULL;
+	unsigned long flags;
+	int ret = 0;
+	dev_t dev_no;
+
+	dev_no = MKDEV(mb_dev_major, mb_dev_minor);
+
+	if (wmt_mbah) {
+		MB_ERROR("%s dirty.\n", DEVICE_NAME);
+		return -EINVAL;
+	}
+
+	/* register char device */
+	mb_cdev = cdev_alloc();
+	if (!mb_cdev) {
+		MB_ERROR("alloc dev error.\n");
+		return -ENOMEM;
+	}
+
+	cdev_init(mb_cdev, &mb_fops);
+	ret = cdev_add(mb_cdev, dev_no, 1);
+
+	if (ret) {
+		MB_ERROR("reg char dev error(%d).\n", ret);
+		cdev_del(mb_cdev);
+		return ret;
+	}
+
+	wmt_mbah = kmalloc(sizeof(struct mba_host_struct), GFP_ATOMIC);
+	if (!wmt_mbah) {
+		MB_ERROR("out of memory (mb_area_struct).\n");
+		cdev_del(mb_cdev);
+		return -ENOMEM;
+	}
+	memset(wmt_mbah, 0x0, sizeof(struct mba_host_struct));
+
+	wmt_mbah->mba_cachep = kmem_cache_create("mb_area_struct",
+		sizeof(struct mb_area_struct),
+		0,
+		SLAB_HWCACHE_ALIGN,
+		NULL);
+	if (!wmt_mbah->mba_cachep) {
+		MB_ERROR("out of memory (mba_cachep).\n");
+		kfree(wmt_mbah);
+		cdev_del(mb_cdev);
+		return -ENOMEM;
+	}
+
+	wmt_mbah->mb_cachep = kmem_cache_create("mb_struct",
+		sizeof(struct mb_struct),
+		0,
+		SLAB_HWCACHE_ALIGN,
+		NULL);
+	if (!wmt_mbah->mb_cachep) {
+		MB_ERROR("out of memory (mb_cachep).\n");
+		kmem_cache_destroy(wmt_mbah->mba_cachep);
+		kfree(wmt_mbah);
+		cdev_del(mb_cdev);
+		return -ENOMEM;
+	}
+
+	wmt_mbah->mbu_cachep = kmem_cache_create("mb_user",
+		sizeof(struct mb_user),
+		0,
+		SLAB_HWCACHE_ALIGN,
+		NULL);
+	if (!wmt_mbah->mbu_cachep) {
+		MB_ERROR("out of memory (mbu_cachep).\n");
+		kmem_cache_destroy(wmt_mbah->mb_cachep);
+		kmem_cache_destroy(wmt_mbah->mba_cachep);
+		kfree(wmt_mbah);
+		cdev_del(mb_cdev);
+		return -ENOMEM;
+	}
+
+	wmt_mbah->mbti_cachep = kmem_cache_create("mb_task_info",
+		sizeof(struct mb_task_info),
+		0,
+		SLAB_HWCACHE_ALIGN,
+		NULL);
+	if (!wmt_mbah->mbti_cachep) {
+		MB_ERROR("out of memory (mbti_cachep).\n");
+		kmem_cache_destroy(wmt_mbah->mbu_cachep);
+		kmem_cache_destroy(wmt_mbah->mb_cachep);
+		kmem_cache_destroy(wmt_mbah->mba_cachep);
+		kfree(wmt_mbah);
+		cdev_del(mb_cdev);
+		return -ENOMEM;
+	}
+
+	MBMAX_ORDER = MBA_MAX_ORDER;
+	MBMIN_ORDER = MBA_MIN_ORDER;
+	INIT_LIST_HEAD(&wmt_mbah->mba_list);
+	INIT_LIST_HEAD(&wmt_mbti.mbti_list);
+
+	spin_lock_init(&mb_do_lock);
+	spin_lock_init(&mb_search_lock);
+	spin_lock_init(&mb_ioctl_lock);
+	spin_lock_init(&mb_task_mm_lock);
+	spin_lock_init(&mb_task_lock);
+
+	MB_INFO("Preparing VIDEO BUFFER (SIZE %d kB) ...\n", MB_TOTAL_SIZE);
+	spin_lock_irqsave(&mb_do_lock, flags);
+	while (PAGE_KB(wmt_mbah->tot_static_pages) < MB_TOTAL_SIZE) {
+		int pages = MB_TOTAL_SIZE*1024 -
+			wmt_mbah->tot_static_pages * PAGE_SIZE;
+		pages = min((pages >> PAGE_SHIFT), (int)(1 << MBMAX_ORDER));
+		mba = mb_alloc_mba(pages);
+		if (mba) {
+			mba->flags |= MBAFLAG_STATIC;
+			mba->tgid = MB_DEF_TGID;
+			wmt_mbah->tot_static_pages += mba->pages;
+			/* conbine to continue mba if possible */
+			if (bind && bind->pgi.pfn_end == mba->pgi.pfn_start) {
+				MB_COMBIND_MBA(bind, mba);
+				continue;
+			}
+			if (bind && bind->pgi.pfn_start == mba->pgi.pfn_end)
+				MB_COMBIND_MBA(mba, bind);
+			bind = mba;
+		}
+	}
+	spin_unlock_irqrestore(&mb_do_lock, flags);
+
+	mb_update_mbah();
+	MB_INFO("MB version: %d.%d.%d.%d\n",
+		MB_VERSION_MAJOR, MB_VERSION_MINOR,
+		MB_VERSION_MICRO, MB_VERSION_BUILD);
+	MB_INFO("MAX MB Area size: Max %ld Kb Min %ld Kb\n",
+		PAGE_KB(1 << MBMAX_ORDER), PAGE_KB(1 << MBMIN_ORDER));
+	MB_INFO("prob /dev/%s major %d, minor %d\n",
+		DEVICE_NAME, mb_dev_major, mb_dev_minor);
+
+	return ret;
+}
+
+static int mb_remove(struct platform_device *dev)
+{
+	if (mb_cdev)
+		cdev_del(mb_cdev);
+
+	if (wmt_mbah) {
+		if (wmt_mbah->mba_cachep)
+			kmem_cache_destroy(wmt_mbah->mba_cachep);
+		if (wmt_mbah->mb_cachep)
+			kmem_cache_destroy(wmt_mbah->mb_cachep);
+		if (wmt_mbah->mbu_cachep)
+			kmem_cache_destroy(wmt_mbah->mbu_cachep);
+		if (wmt_mbah->mbti_cachep)
+			kmem_cache_destroy(wmt_mbah->mbti_cachep);
+		kfree(wmt_mbah);
+	}
+
+	MB_INFO("MB dev remove\n");
+	return 0;
+}
+
+static int mb_suspend(struct platform_device *dev, pm_message_t state)
+{
+	MB_DBG("MB get suspend, Event %d.\n", state.event);
+	return 0;
+}
+
+static int mb_resume(struct platform_device *dev)
+{
+	MB_DBG("MB get resume.\n");
+	return 0;
+}
+
+int mb_area_read_proc(
+	char *buf, char **start, off_t off,
+	int count, int *eof, void *data
+)
+{
+	struct mb_area_struct *mba;
+	struct free_area *fa;
+	struct zone *zone;
+	unsigned long flags;
+	unsigned int idx = 1;
+	char *p = buf, *base = (char *)data;
+	int datalen = 0, len;
+
+	if (!data || !count) {
+		p += sprintf(p, "no resource for mb_area read proc. (%p,%d)\n",
+			data, count);
+		return p-buf;
+	}
+
+	if (!wmt_mbah) {
+		p += sprintf(p, "no MB area host existed.\n");
+		return p-buf;
+	}
+
+	spin_lock_irqsave(&mb_ioctl_lock, flags);
+	if (!off) { /* re read mb area information */
+		p = base;
+		memset(p, 0x0, MBPROC_BUFSIZE);
+
+		/* show block information */
+		p += sprintf(p, "VERSION:                  %3d.%3d.%3d.%3d\n",
+			MB_VERSION_MAJOR, MB_VERSION_MINOR,
+			MB_VERSION_MICRO, MB_VERSION_BUILD);
+		p += sprintf(p, "MESSAGE LEVEL:       %8d   /%8lx\n",
+			MBMSG_LEVEL, __pa(&MBMSG_LEVEL));
+		p += sprintf(p, "STATIC MB SIZE:   %8ld MB   /%5d MB\n",
+			PAGE_KB(wmt_mbah->tot_static_pages)/1024,
+			MB_TOTAL_SIZE/1024);
+		p += sprintf(p, "MAX MBA ORDER:       %8d   /%8lx\n",
+			MBMAX_ORDER, __pa(&MBMAX_ORDER));
+		p += sprintf(p, "MIN MBA ORDER:       %8d   /%8lx\n\n",
+			MBMIN_ORDER, __pa(&MBMIN_ORDER));
+		p += sprintf(p, "USER TO PRDT METHOD: %8d   /%8lx\n\n",
+			USR2PRDT_METHOD, __pa(&USR2PRDT_METHOD));
+		p += sprintf(p, "total MB areas:      %8d\n",
+			wmt_mbah->nr_mba);
+		p += sprintf(p, "total size:          %8ld kB\n",
+			PAGE_KB(wmt_mbah->tot_pages));
+		p += sprintf(p, "total free size:     %8ld kB\n",
+			PAGE_KB(wmt_mbah->tot_free_pages));
+		p += sprintf(p, "max MB size:         %8ld kB\n\n",
+			PAGE_KB(wmt_mbah->max_available_pages));
+
+		list_loop(mba, &wmt_mbah->mba_list, mba_list) {
+			p += sprintf(p, "(ID) [MB Area] VirtAddr PhysAddr  ");
+			p += sprintf(p, "size [   zs,   ze] MBs      Max/");
+			p += sprintf(p, "    Free Ste\n");
+			len = (int)(p-base);
+			if ((MBPROC_BUFSIZE - len) < 12) {
+				p += sprintf(p, " more ...\n");
+				break;
+			}
+			p += sprintf(p, "(%2d)", idx++);
+			len = (int)(p-base);
+			/* show all MBs */
+			/* -2 is for \n and zero */
+			p += mb_show_mba(mba, NULL, p,
+				MBPROC_BUFSIZE - len - 2, 1);
+			p += sprintf(p, "\n");
+		}
+		/* show memory fragment */
+		zone = (first_online_pgdat())->node_zones;
+		fa = zone->free_area;
+		p += sprintf(p, "DMA ZONE:\n");
+		for (idx = 0; idx < MAX_ORDER; idx++)
+			p += sprintf(p, " %5ld * %5ldkB = %5ld kB\n",
+				fa[idx].nr_free, PAGE_KB((1<<idx)),
+				fa[idx].nr_free * PAGE_KB((1<<idx)));
+		p += sprintf(p, " ------------------------------\n");
+		p += sprintf(p, "               + = %ld kB\n\n",
+			PAGE_KB((unsigned long)nr_free_pages()));
+	}
+	spin_unlock_irqrestore(&mb_ioctl_lock, flags);
+	datalen = strlen(base);
+	if (off >= datalen) {
+		*eof = 1;
+		return 0;
+	}
+	len = min((int)(datalen - off), count);
+	memcpy(buf, &base[off], len);
+	*start = (char *)len; /* for case1: *start < page, mass read data */
+
+	return len;
+}
+
+static struct platform_driver mb_driver = {
+	.driver.name    = "wmt_mb",
+	.probe          = mb_probe,
+	.remove         = mb_remove,
+	.suspend        = mb_suspend,
+	.resume         = mb_resume
+};
+
+static void mb_platform_release(struct device *device)
+{
+	return;
+}
+
+static struct platform_device mb_device = {
+	.name          = "wmt_mb",
+	.id            = 0,
+	.dev           = { .release =  mb_platform_release, },
+	.num_resources = 0,
+	.resource      = NULL,
+};
+
+static int __init mb_init(void)
+{
+	int varlen = 32, ret = -1, mbtotal = 0;
+	unsigned char buf[32];
+	dev_t dev_no;
+
+	mb_dev_major = MB_MAJOR;
+	mb_dev_minor = 0;
+	mb_dev_nr = 1;
+
+	dev_no = MKDEV(mb_dev_major, mb_dev_minor);
+	ret = register_chrdev_region(dev_no, mb_dev_nr, "wmt_mb");
+	if (ret < 0) {
+		MB_ERROR("can't get %s device major %d\n",
+			DEVICE_NAME, mb_dev_major);
+		return ret;
+	}
+
+	if (wmt_getsyspara("mbsize", buf, &varlen) == 0) {
+		sscanf(buf, "%dM", &mbtotal);
+		mbtotal *= 1024;
+		MB_INFO("Set MB total size %d KB\n", mbtotal);
+		if (mbtotal > 0)
+			MB_TOTAL_SIZE = mbtotal;
+	}
+
+	wmt_mbah = NULL;
+	MBMSG_LEVEL = MBMAX_ORDER = MBMIN_ORDER = USR2PRDT_METHOD = 0;
+	mb_dev_class = class_create(THIS_MODULE, "mbdev");
+	device_create(mb_dev_class, NULL, dev_no, NULL, "mbdev");
+
+#ifdef CONFIG_PROC_FS
+	{
+		void *proc_buffer = kmalloc(MBPROC_BUFSIZE, GFP_KERNEL);
+		struct proc_dir_entry *res = NULL;
+		if (proc_buffer) {
+			memset(proc_buffer, 0x0, MBPROC_BUFSIZE);
+			res = create_proc_entry("mbinfo", 0, NULL);
+			if (res) {
+				res->read_proc = mb_area_read_proc;
+				res->data = proc_buffer;
+				MB_DBG("create MB proc\n");
+			} else
+				kfree(proc_buffer);
+		}
+	}
+#endif
+
+	ret = platform_driver_register(&mb_driver);
+	if (!ret) {
+		ret = platform_device_register(&mb_device);
+		if (ret)
+			platform_driver_unregister(&mb_driver);
+	}
+
+	return ret;
+}
+
+/* because mb will not exit from system, not need to release proc resource */
+static void __exit mb_exit(void)
+{
+	dev_t dev_no;
+
+	platform_driver_unregister(&mb_driver);
+	platform_device_unregister(&mb_device);
+	dev_no = MKDEV(mb_dev_major, mb_dev_minor);
+	device_destroy(mb_dev_class, dev_no);
+	class_destroy(mb_dev_class);
+	unregister_chrdev_region(dev_no, mb_dev_nr);
+
+	return;
+}
+
+fs_initcall(mb_init);
+module_exit(mb_exit);
+
+MODULE_AUTHOR("WonderMedia Technologies, Inc.");
+MODULE_DESCRIPTION("memory block driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/wmt/wmt-sync.c b/drivers/video/wmt/wmt-sync.c
new file mode 100755
index 00000000..2bc39edd
--- /dev/null
+++ b/drivers/video/wmt/wmt-sync.c
@@ -0,0 +1,340 @@
+/*++
+ * linux/drivers/video/wmt/wmt-sync.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2013  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define DEV_SYNC_C
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <linux/sched.h>
+#include <linux/wmt-mb.h>
+#include <linux/wmt-se.h>
+#include <linux/poll.h>
+
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+#include "vpp.h"
+
+#define DEVICE_NAME "wmt-sync"
+
+static DEFINE_SEMAPHORE(wmt_sync_sem);
+static DECLARE_WAIT_QUEUE_HEAD(wmt_sync_wait);
+static struct class *wmt_sync_class;
+static int wmt_sync_major;
+unsigned int wmt_vsync_flag;
+enum vpp_int_t wmt_sync_type;
+int wmt_sync_set_vsync(void *arg)
+{
+	wmt_vsync_flag++;
+	wake_up_interruptible(&wmt_sync_wait);
+	vpp_mb_irqproc_sync(0);
+	return 0;
+}
+
+static int wmt_sync_open(
+	struct inode *inode,
+	struct file *filp
+)
+{
+	struct govrh_mod_t *govr;
+
+	DBG_MSG("\n");
+
+	down(&wmt_sync_sem);
+
+	/* non-dual use govrh2, because HDMI should slow down */
+	govr = vout_info_get_govr((g_vpp.virtual_display) ? 1 : 0);
+	wmt_sync_type = (govr->mod == VPP_MOD_GOVRH) ?
+			VPP_INT_GOVRH_VBIS : VPP_INT_GOVRH2_VBIS;
+	vpp_irqproc_work(wmt_sync_type, wmt_sync_set_vsync, 0, 0, 0);
+
+	up(&wmt_sync_sem);
+	return 0;
+} /* End of wmt_sync_open() */
+
+static int wmt_sync_release(
+	struct inode *inode,
+	struct file *filp
+)
+{
+	DBG_MSG("\n");
+
+	down(&wmt_sync_sem);
+	vpp_irqproc_del_work(wmt_sync_type, wmt_sync_set_vsync);
+	up(&wmt_sync_sem);
+	return 0;
+} /* End of wmt_sync_release() */
+
+static long wmt_sync_ioctl(struct file *filp, unsigned int cmd,
+						unsigned long arg)
+{
+	int ret = -EINVAL;
+
+	DBG_MSG("0x%x,0x%x\n", cmd, arg);
+
+	/* check type and number, if fail return ENOTTY */
+	if (_IOC_TYPE(cmd) != WMT_CEC_IOC_MAGIC)
+		return -ENOTTY;
+	if (_IOC_NR(cmd) > WMT_CEC_IOC_MAXNR)
+		return -ENOTTY;
+
+	/* check argument area */
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ret = !access_ok(VERIFY_WRITE,
+				(void __user *) arg, _IOC_SIZE(cmd));
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		ret = !access_ok(VERIFY_READ,
+				(void __user *) arg, _IOC_SIZE(cmd));
+	else
+		ret = 0;
+
+	if (ret)
+		return -EFAULT;
+
+	down(&wmt_sync_sem);
+	switch (cmd) {
+	default:
+		DBG_ERR("*W* cmd 0x%x\n", cmd);
+		break;
+	}
+	up(&wmt_sync_sem);
+	return ret;
+} /* End of wmt_sync_ioctl() */
+
+static ssize_t wmt_sync_read(
+	struct file *filp,
+	char __user *buf,
+	size_t count,
+	loff_t *f_pos
+)
+{
+	unsigned long data;
+	ssize_t retval = 0;
+
+	down(&wmt_sync_sem);
+	if (filp->f_flags & O_NONBLOCK && !wmt_vsync_flag) {
+		retval = -EAGAIN;
+		goto read_end;
+	}
+	data = xchg(&wmt_vsync_flag, 0);
+	retval = wait_event_interruptible(wmt_sync_wait, data);
+	if (retval == 0)
+		retval = put_user(data, (unsigned int __user *)buf);
+read_end:
+	up(&wmt_sync_sem);
+	return retval;
+} /* wmt_sync_read */
+
+static ssize_t wmt_sync_write(
+	struct file *filp,
+	const char __user *buf,
+	size_t count,
+	loff_t *f_pos
+)
+{
+	ssize_t ret = 0;
+	down(&wmt_sync_sem);
+	/* TODO */
+	up(&wmt_sync_sem);
+	return ret;
+} /* End of wmt_sync_write() */
+
+static unsigned int wmt_sync_poll(
+	struct file *filp,
+	struct poll_table_struct *wait
+)
+{
+	unsigned int mask = 0;
+
+	down(&wmt_sync_sem);
+	poll_wait(filp, &wmt_sync_wait, wait);
+	if (wmt_vsync_flag != 0)
+		mask |= POLLIN | POLLRDNORM;
+	up(&wmt_sync_sem);
+	return mask;
+}
+
+const struct file_operations wmt_sync_fops = {
+	.owner          = THIS_MODULE,
+	.open           = wmt_sync_open,
+	.release        = wmt_sync_release,
+	.read           = wmt_sync_read,
+	.write          = wmt_sync_write,
+	.unlocked_ioctl = wmt_sync_ioctl,
+	.poll           = wmt_sync_poll,
+};
+
+static int wmt_sync_probe
+(
+	struct platform_device *dev /*!<; // a pointer to struct device */
+)
+{
+	return 0;
+} /* End of wmt_sync_probe */
+
+static int wmt_sync_remove
+(
+	struct platform_device *dev /*!<; // a pointer to struct device */
+)
+{
+	return 0;
+} /* End of wmt_sync_remove */
+
+#ifdef CONFIG_PM
+static int wmt_sync_suspend
+(
+	struct platform_device *pDev,	/*!<; // a pointer to struct device */
+	pm_message_t state		/*!<; // suspend state */
+)
+{
+	DPRINT("Enter wmt_sync_suspend\n");
+	return 0;
+} /* End of wmt_sync_suspend */
+
+static int wmt_sync_resume
+(
+	struct platform_device *pDev	/*!<; // a pointer to struct device */
+)
+{
+	DPRINT("Enter wmt_sync_resume\n");
+	return 0;
+} /* End of wmt_sync_resume */
+#else
+#define wmt_sync_suspend NULL
+#define wmt_sync_resume NULL
+#endif
+
+/***************************************************************************
+	device driver struct define
+****************************************************************************/
+static struct platform_driver wmt_sync_driver = {
+	.driver.name    = DEVICE_NAME, /* equal to platform device name. */
+/*	.bus            = &platform_bus_type, */
+	.probe          = wmt_sync_probe,
+	.remove         = wmt_sync_remove,
+	.suspend        = wmt_sync_suspend,
+	.resume         = wmt_sync_resume,
+};
+
+static void wmt_sync_platform_release(struct device *device)
+{
+} /* End of wmt_sync_platform_release() */
+
+/***************************************************************************
+	platform device struct define
+****************************************************************************/
+/* static u64 wmt_sync_dma_mask = 0xffffffffUL; */
+static struct platform_device wmt_sync_device = {
+	.name   = DEVICE_NAME,
+	.id     = 0,
+	.dev    = {
+		.release = wmt_sync_platform_release,
+#if 0
+		.dma_mask = &wmt_sync_dma_mask,
+		.coherent_dma_mask = ~0,
+#endif
+	},
+	.num_resources  = 0,	/* ARRAY_SIZE(cipher_resources), */
+	.resource       = NULL,	/* cipher_resources, */
+};
+
+static int __init wmt_sync_init(void)
+{
+	int ret;
+	char buf[100];
+	int varlen = 100;
+	unsigned int sync_enable = 1; /* default enable */
+	dev_t dev_no;
+
+	if (wmt_getsyspara("wmt.display.sync", buf, &varlen) == 0)
+		vpp_parse_param(buf, &sync_enable, 1, 0);
+
+	if (sync_enable == 0)
+		return 0;
+
+	wmt_sync_major = register_chrdev(0, DEVICE_NAME, &wmt_sync_fops);
+	if (wmt_sync_major < 0) {
+		DBG_ERR("get gpio_dev_major failed\n");
+		return -EFAULT;
+	}
+
+	wmt_sync_class = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(wmt_sync_class)) {
+		ret = PTR_ERR(wmt_sync_class);
+		DBG_ERR("Can't create class : %s !!\n", DEVICE_NAME);
+		return ret;
+	}
+
+	dev_no = MKDEV(wmt_sync_major, 0);
+	device_create(wmt_sync_class, NULL, dev_no, NULL, DEVICE_NAME);
+	ret = platform_device_register(&wmt_sync_device);
+	if (ret != 0)
+		return -ENODEV;
+
+	ret = platform_driver_register(&wmt_sync_driver);
+	if (ret != 0) {
+		platform_device_unregister(&wmt_sync_device);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit wmt_sync_exit(void)
+{
+	dev_t dev_no;
+
+	DBG_MSG("\n");
+
+	platform_driver_unregister(&wmt_sync_driver);
+	platform_device_unregister(&wmt_sync_device);
+	dev_no = MKDEV(wmt_sync_major, 0);
+	device_destroy(wmt_sync_class, dev_no);
+	class_destroy(wmt_sync_class);
+	unregister_chrdev(wmt_sync_major, DEVICE_NAME);
+	return;
+}
+
+module_init(wmt_sync_init);
+module_exit(wmt_sync_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("WMT SYNC driver");
+MODULE_AUTHOR("WMT TECH");
+MODULE_VERSION("1.0.0");
+
diff --git a/drivers/video/wmt/wmt-vpp.c b/drivers/video/wmt/wmt-vpp.c
new file mode 100755
index 00000000..4415477b
--- /dev/null
+++ b/drivers/video/wmt/wmt-vpp.c
@@ -0,0 +1,1538 @@
+/*++
+ * linux/drivers/video/wmt/wmt-vpp.c
+ * WonderMedia video post processor (VPP) driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define DEV_VPP_C
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/dma-mapping.h>
+#include <linux/major.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <mach/irqs.h>
+#include <mach/hardware.h>
+#include <linux/sched.h>
+#include <linux/wmt-mb.h>
+#include <linux/wmt-se.h>
+#include <linux/poll.h>
+
+#undef DEBUG
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+#include "vpp.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define WMT_VPP_XXXX    1     *//*Example*/
+#define DEVICE_NAME "wmt-vpp"
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx wmt_vpp_xxx_t; *//*Example*/
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  wmt_vpp_xxx;        *//*Example*/
+static DEFINE_SEMAPHORE(wmt_vpp_sem);
+static struct class *wmt_vpp_class;
+static int wmt_vpp_major;
+
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void wmt_vpp_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+#ifdef CONFIG_PROC_FS
+#define CONFIG_VPP_PROC
+#ifdef CONFIG_VPP_PROC
+unsigned int vpp_proc_value;
+char vpp_proc_str[16];
+static ctl_table vpp_table[];
+static int vpp_do_proc(ctl_table *ctl, int write,
+				void *buffer, size_t *len, loff_t *ppos)
+{
+	int ret;
+	int ctl_name;
+
+	ctl_name = (((int)ctl - (int)vpp_table) / sizeof(ctl_table)) + 1;
+	if (!write) {
+		switch (ctl_name) {
+		case 1:
+			vpp_proc_value = g_vpp.dbg_msg_level;
+			break;
+		case 2:
+			vpp_proc_value = g_vpp.dbg_wait;
+			break;
+		case 3:
+			vpp_proc_value = g_vpp.dbg_flag;
+			break;
+		case 8:
+		case 9:
+			vpp_proc_value = vpp_get_base_clock((ctl_name == 8) ?
+				VPP_MOD_GOVRH : VPP_MOD_GOVRH2);
+			break;
+		case 10:
+			vpp_proc_value = p_scl->scale_mode;
+			break;
+		case 11:
+			vpp_proc_value = p_scl->filter_mode;
+			break;
+#ifdef CONFIG_WMT_HDMI
+		case 12:
+			vpp_proc_value = g_vpp.hdmi_cp_enable;
+			break;
+		case 13:
+			vpp_proc_value = g_vpp.hdmi_3d_type;
+			break;
+		case 14:
+			vpp_proc_value = g_vpp.hdmi_certify_flag;
+			break;
+#endif
+		case 15:
+			vpp_proc_value = govrh_get_brightness(p_govrh);
+			break;
+		case 16:
+			vpp_proc_value = govrh_get_contrast(p_govrh);
+			break;
+		case 17:
+			vpp_proc_value = govrh_get_saturation(p_govrh);
+			break;
+		case 18:
+			vpp_proc_value = g_vpp.fb_manual;
+			break;
+		default:
+			break;
+		}
+	}
+
+	ret = proc_dointvec(ctl, write, buffer, len, ppos);
+	if (write) {
+		switch (ctl_name) {
+		case 1:
+			DPRINT("---------- VPP debug level ----------\n");
+			DPRINT("0-disable,255-show all\n");
+			DPRINT("1-scale,2-disp fb,3-interrupt,4-timer\n");
+			DPRINT("5-ioctl,6-diag,7-stream\n");
+			DPRINT("-------------------------------------\n");
+			g_vpp.dbg_msg_level = vpp_proc_value;
+			break;
+		case 2:
+			g_vpp.dbg_wait = vpp_proc_value;
+			vpp_dbg_wake_up();
+			break;
+		case 3:
+			g_vpp.dbg_flag = vpp_proc_value;
+			break;
+#ifdef CONFIG_WMT_EDID
+		case 6:
+			{
+			struct vout_t *vo;
+
+			vo = vout_get_entry_adapter(vpp_proc_value);
+			if ((vo->inf) && (vo->inf->get_edid)) {
+				vo->status &= ~VPP_VOUT_STS_EDID;
+				if (vout_get_edid(vo->num)) {
+					int i;
+
+					vo->edid_info.option = 0;
+					edid_dump(vo->edid);
+					for (i = 1; i <= vo->edid[126]; i++)
+						edid_dump(vo->edid + 128 * i);
+					if (!edid_parse(vo->edid,
+						&vo->edid_info))
+						DBG_ERR("parse EDID\n");
+				} else {
+					DBG_ERR("read EDID\n");
+				}
+			}
+			}
+			break;
+#endif
+		case 8:
+		case 9:
+			govrh_set_clock((ctl_name == 8) ? p_govrh : p_govrh2,
+				vpp_proc_value);
+			DPRINT("set govr pixclk %d\n", vpp_proc_value);
+			break;
+		case 10:
+			DPRINT("---------- scale mode ----------\n");
+			DPRINT("0-recursive normal\n");
+			DPRINT("1-recursive sw bilinear\n");
+			DPRINT("2-recursive hw bilinear\n");
+			DPRINT("3-realtime noraml (quality but x/32 limit)\n");
+			DPRINT("4-realtime bilinear (fit edge w skip line)\n");
+			DPRINT("-------------------------------------\n");
+			p_scl->scale_mode = vpp_proc_value;
+			break;
+		case 11:
+			p_scl->filter_mode = vpp_proc_value;
+			break;
+#ifdef CONFIG_WMT_HDMI
+		case 12:
+			g_vpp.hdmi_cp_enable = vpp_proc_value;
+			hdmi_set_cp_enable(vpp_proc_value);
+			break;
+		case 13:
+			g_vpp.hdmi_3d_type = vpp_proc_value;
+			hdmi_tx_vendor_specific_infoframe_packet();
+			break;
+		case 14:
+			g_vpp.hdmi_certify_flag = vpp_proc_value;
+			break;
+#endif
+		case 15:
+			govrh_set_brightness(p_govrh, vpp_proc_value);
+			break;
+		case 16:
+			govrh_set_contrast(p_govrh, vpp_proc_value);
+			break;
+		case 17:
+			govrh_set_saturation(p_govrh, vpp_proc_value);
+			break;
+		case 18:
+			g_vpp.fb_manual = vpp_proc_value;
+			break;
+		default:
+			break;
+		}
+	}
+	return ret;
+}
+
+struct proc_dir_entry *vpp_proc_dir;
+static ctl_table vpp_table[] = {
+	{ /* .ctl_name = 1, */
+	.procname	= "dbg_msg",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 2, */
+	.procname	= "dbg_wait",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 3, */
+	.procname	= "dbg_flag",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 4, */
+	.procname	= "edid_disable",
+	.data		= &edid_disable,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 5, */
+	.procname	= "edid_msg",
+	.data		= &edid_msg_enable,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 6, */
+	.procname	= "vout_edid",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 7, */
+	.procname	= "vo_mode",
+	.data		= vpp_proc_str,
+	.maxlen		= 12,
+	.mode		= 0666,
+	.proc_handler = &proc_dostring,
+	},
+	{ /* .ctl_name = 8, */
+	.procname	= "govr1_pixclk",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 9, */
+	.procname	= "govr2_pixclk",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 10, */
+	.procname	= "scl_scale_mode",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 11, */
+	.procname	= "scl_filter",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 12 */
+	.procname	= "hdmi_cp_enable",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 13 */
+	.procname	= "hdmi_3d",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 14 */
+	.procname	= "hdmi_certify",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 15 */
+	.procname	= "brightness",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 16 */
+	.procname	= "contrast",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 17 */
+	.procname	= "saturation",
+	.data		= &vpp_proc_value,
+	.maxlen		= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* .ctl_name = 18 */
+	.procname	= "fb_manual",
+	.data		= &vpp_proc_value,
+	.maxlen 	= sizeof(int),
+	.mode		= 0666,
+	.proc_handler = &vpp_do_proc,
+	},
+	{ /* end of table */
+	}
+};
+
+static ctl_table vpp_root_table[] = {
+	{
+	.procname	= "vpp", /* create path ==> /proc/sys/vpp */
+	.mode		= 0555,
+	.child		= vpp_table
+	},
+	{ /* end of table */
+	}
+};
+static struct ctl_table_header *vpp_table_header;
+#endif
+
+static int vpp_sts_read_proc(char *buf, char **start, off_t offset,
+					int len, int *eof, void *data)
+{
+	struct govrh_regs *regs = (struct govrh_regs *) REG_GOVRH_BASE1_BEGIN;
+	unsigned int yaddr, caddr;
+	char *p = buf;
+	unsigned int reg;
+
+	p += sprintf(p, "--- VPP HW status ---\n");
+#ifdef WMT_FTBLK_GOVRH
+	p += sprintf(p, "GOVRH memory read underrun error %d,cnt %d,cnt2 %d\n",
+		(regs->interrupt.val & 0x200) ? 1 : 0,
+		p_govrh->underrun_cnt, p_govrh2->underrun_cnt);
+	p_govrh->clr_sts(VPP_INT_ALL);
+#endif
+
+#ifdef WMT_FTBLK_SCL
+	p += sprintf(p, "---------------------------------------\n");
+	p += sprintf(p, "SCL TG error %d\n", scl_regs1->tg_sts.b.tgerr);
+	p += sprintf(p, "SCLR MIF1 read error %d\n",
+		scl_regs1->r_fifo_ctl.b.r1_mif_err);
+	p += sprintf(p, "SCLR MIF2 read error %d\n",
+		scl_regs1->r_fifo_ctl.b.r2_mif_err);
+	p += sprintf(p, "SCLW RGB fifo overflow %d\n",
+		scl_regs1->w_ff_ctl.b.mif_rgb_err);
+	p += sprintf(p, "SCLW Y fifo overflow %d\n",
+		scl_regs1->w_ff_ctl.b.mif_y_err);
+	p += sprintf(p, "SCLW C fifo overflow %d\n",
+		scl_regs1->w_ff_ctl.b.mif_c_err);
+	p_scl->clr_sts(VPP_INT_ALL);
+#endif
+
+	p += sprintf(p, "---------------------------------------\n");
+	p += sprintf(p, "(880.0)GOVRH Enable %d,(900.0)TG %d\n",
+		regs->mif.b.enable, regs->tg_enable.b.enable);
+
+	reg = inl(PM_CTRL_BASE_ADDR + 0x258);
+	p += sprintf(p, "--- POWER CONTROL ---\n");
+	p += sprintf(p, "0x%x = 0x%x\n", PM_CTRL_BASE_ADDR + 0x258, reg);
+	p += sprintf(p, "HDCP %d,VPP %d,SCL %d,HDMI I2C %d\n",
+		(reg & BIT7) ? 1 : 0, (reg & BIT18) ? 1 : 0,
+		(reg & BIT21) ? 1 : 0, (reg & BIT22) ? 1 : 0);
+	p += sprintf(p, "HDMI %d,GOVR %d,NA12 %d\n",
+		(reg & BIT23) ? 1 : 0, (reg & BIT25) ? 1 : 0,
+		(reg & BIT16) ? 1 : 0);
+	p += sprintf(p, "DVO %d,HDMI OUT %d,LVDS %d\n", (reg & BIT29) ? 1 : 0,
+		(reg & BIT30) ? 1 : 0, (reg & BIT14) ? 1 : 0);
+
+	p += sprintf(p, "--- VPP fb Address ---\n");
+
+#ifdef WMT_FTBLK_GOVRH
+	govrh_get_fb_addr(p_govrh, &yaddr, &caddr);
+	p += sprintf(p, "GOVRH fb addr Y(0x%x) 0x%x, C(0x%x) 0x%x\n",
+		REG_GOVRH_YSA, yaddr, REG_GOVRH_CSA, caddr);
+	govrh_get_fb_addr(p_govrh2, &yaddr, &caddr);
+	p += sprintf(p, "GOVRH2 fb addr Y(0x%x) 0x%x, C(0x%x) 0x%x\n",
+		REG_GOVRH2_YSA, yaddr, REG_GOVRH2_CSA, caddr);
+#endif
+	p_govrh->underrun_cnt = 0;
+	p_govrh2->underrun_cnt = 0;
+	return p - buf;
+}
+
+static int vpp_reg_read_proc(char *buf, char **start, off_t offset,
+					int len, int *eof, void *data)
+{
+	char *p = buf;
+	struct vpp_mod_base_t *mod_p;
+	int i;
+
+	DPRINT("Product ID:0x%x\n", vpp_get_chipid());
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->dump_reg)
+			mod_p->dump_reg();
+	}
+#ifdef WMT_FTBLK_HDMI
+	hdmi_reg_dump();
+#endif
+#ifdef WMT_FTBLK_LVDS
+	lvds_reg_dump();
+#endif
+	return p - buf;
+}
+#endif
+
+irqreturn_t vpp_interrupt_routine(int irq, void *dev_id)
+{
+	enum vpp_int_t int_sts;
+
+	switch (irq) {
+	case VPP_IRQ_VPPM: /* VPP */
+		int_sts = p_vppm->get_sts();
+		p_vppm->clr_sts(int_sts);
+
+		vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] VPPM INT", int_sts);
+		{
+		int i;
+		unsigned int mask;
+		struct vpp_irqproc_t *irqproc;
+
+		for (i = 0, mask = 0x1; (i < 32) && int_sts; i++, mask <<= 1) {
+			if ((int_sts & mask) == 0)
+				continue;
+
+			irqproc = vpp_irqproc_get_entry(mask);
+			if (irqproc) {
+				if (list_empty(&irqproc->list) == 0)
+					tasklet_schedule(&irqproc->tasklet);
+			} else {
+				irqproc = vpp_irqproc_get_entry(VPP_INT_MAX);
+				if (list_empty(&irqproc->list) == 0) {
+					struct vpp_proc_t *entry;
+					struct list_head *ptr;
+
+					ptr = (&irqproc->list)->next;
+					entry = list_entry(ptr,
+						struct vpp_proc_t, list);
+					if (entry->type == mask)
+						tasklet_schedule(
+							&irqproc->tasklet);
+				}
+			}
+			int_sts &= ~mask;
+		}
+		}
+		break;
+#ifdef WMT_FTBLK_SCL
+	case VPP_IRQ_SCL: /* SCL */
+		int_sts = p_scl->get_sts();
+		p_scl->clr_sts(int_sts);
+		vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] SCL INT", int_sts);
+		break;
+#endif
+#ifdef WMT_FTBLK_GOVRH
+	case VPP_IRQ_GOVR:	/* GOVR */
+	case VPP_IRQ_GOVR2:
+		{
+		struct govrh_mod_t *govr;
+
+		govr = (irq == VPP_IRQ_GOVR) ? p_govrh : p_govrh2;
+		int_sts = govr->get_sts();
+		govr->clr_sts(int_sts);
+		vpp_dbg_show_val1(VPP_DBGLVL_INT, 0, "[VPP] GOVR INT", int_sts);
+		govr->underrun_cnt++;
+#ifdef VPP_DBG_DIAG_NUM
+		vpp_dbg_show(VPP_DBGLVL_DIAG, 3, "GOVR MIF Err");
+		vpp_dbg_diag_delay = 10;
+#endif
+		}
+		break;
+#endif
+	default:
+		DPRINT("*E* invalid vpp isr\n");
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+void vpp_wait_vsync(int no, int cnt)
+{
+	struct govrh_mod_t *govr;
+
+	govr = vout_info_get_govr(no);
+	if (govr) {
+		if (govrh_get_MIF_enable(govr)) {
+			vpp_irqproc_work((govr->mod == VPP_MOD_GOVRH) ?
+				VPP_INT_GOVRH_VBIS : VPP_INT_GOVRH2_VBIS,
+				0, 0, 100 * cnt, cnt);
+			if (vpp_check_dbg_level(VPP_DBGLVL_DISPFB))
+				MSG("wait vsync(%d,%d)\n", no, cnt);
+		}
+	}
+}
+
+/*----------------------- vpp ioctl --------------------------------------*/
+int vpp_common_ioctl(unsigned int cmd, unsigned long arg)
+{
+	struct vpp_mod_base_t *mod_p;
+	struct vpp_fb_base_t *mod_fb_p;
+	int retval = 0;
+
+	switch (cmd) {
+	case VPPIO_VPPGET_INFO:
+		{
+		int i;
+		vpp_cap_t parm;
+
+		parm.chip_id = vpp_get_chipid();
+		parm.version = 0x01;
+		parm.resx_max = VPP_HD_MAX_RESX;
+		parm.resy_max = VPP_HD_MAX_RESY;
+		parm.pixel_clk = 400000000;
+		parm.module = 0x0;
+		for (i = 0; i < VPP_MOD_MAX; i++) {
+			mod_p = vpp_mod_get_base(i);
+			if (mod_p)
+				parm.module |= (0x01 << i);
+		}
+		parm.option = VPP_CAP_DUAL_DISPLAY;
+		copy_to_user((void *)arg, (void *) &parm, sizeof(vpp_cap_t));
+		}
+		break;
+	case VPPIO_VPPSET_INFO:
+		{
+		vpp_cap_t parm;
+
+		copy_from_user((void *)&parm, (const void *)arg,
+			sizeof(vpp_cap_t));
+		}
+		break;
+	case VPPIO_I2CSET_BYTE:
+		{
+		vpp_i2c_t parm;
+		unsigned int id;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_i2c_t));
+		id = (parm.addr & 0x0000FF00) >> 8;
+		vpp_i2c_write(id, (parm.addr & 0xFF), parm.index,
+			(char *)&parm.val, 1);
+		}
+		break;
+	case VPPIO_I2CGET_BYTE:
+		{
+		vpp_i2c_t parm;
+		unsigned int id;
+		int len;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_i2c_t));
+		id = (parm.addr & 0x0000FF00) >> 8;
+		len = parm.val;
+		{
+			unsigned char buf[len];
+
+			vpp_i2c_read(id, (parm.addr & 0xFF), parm.index,
+				buf, len);
+			parm.val = buf[0];
+		}
+		copy_to_user((void *)arg, (void *) &parm, sizeof(vpp_i2c_t));
+		}
+		break;
+	case VPPIO_MODULE_FBINFO:
+		{
+		vpp_mod_fbinfo_t parm;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_mod_fbinfo_t));
+
+		if (g_vpp.virtual_display)
+			parm.mod = (hdmi_get_plugin()) ?
+				VPP_MOD_GOVRH : VPP_MOD_GOVRH2;
+		mod_fb_p = vpp_mod_get_fb_base(parm.mod);
+		if (!mod_fb_p)
+			break;
+		mod_p = vpp_mod_get_base(parm.mod);
+		if (parm.read) {
+			parm.fb = mod_fb_p->fb;
+			switch (parm.mod) {
+			case VPP_MOD_GOVRH:
+			case VPP_MOD_GOVRH2:
+				govrh_get_framebuffer(
+					(struct govrh_mod_t *)mod_p,
+					&parm.fb);
+				break;
+			default:
+				break;
+			}
+			copy_to_user((void *)arg, (void *) &parm,
+				sizeof(vpp_mod_fbinfo_t));
+		} else {
+			mod_fb_p->fb = parm.fb;
+			mod_fb_p->set_framebuf(&parm.fb);
+		}
+		}
+		break;
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+	case VPPIO_STREAM_ENABLE:
+		g_vpp.stream_enable = arg;
+		g_vpp.stream_mb_sync_flag = 0;
+		g_vpp.stream_mb_lock = 0;
+		g_vpp.stream_mb_index = 0xFF;
+		MSG("VPPIO_STREAM_ENABLE %d\n", g_vpp.stream_enable);
+		vpp_netlink_notify(WP_PID, DEVICE_STREAM,
+				(g_vpp.stream_enable) ? 1 : 0);
+		wmt_enable_mmfreq(WMT_MMFREQ_MIRACAST, g_vpp.stream_enable);
+		break;
+	case VPPIO_STREAM_GETFB:
+		{
+		vdo_framebuf_t fb;
+
+		vpp_lock();
+		if (g_vpp.stream_mb_index == 0xFF) { /* not avail */
+			retval = -1;
+			vpp_unlock();
+			break;
+		}
+		fb = vout_info[g_vpp.stream_fb]->fb;
+		fb.fb_h = vpp_calc_align(fb.img_h, 16);
+		copy_to_user((void *)arg, (void *) &fb, sizeof(vdo_framebuf_t));
+		retval = vpp_mb_get(fb.y_addr);
+		vpp_unlock();
+		}
+		break;
+	case VPPIO_STREAM_PUTFB:
+		{
+		vdo_framebuf_t fb;
+		copy_from_user((void *) &fb, (const void *)arg,
+			sizeof(vdo_framebuf_t));
+		vpp_lock();
+		vpp_mb_put(fb.y_addr);
+		vpp_unlock();
+		}
+		break;
+#endif
+	case VPPIO_MULTIVD_ENABLE:
+		wmt_enable_mmfreq(WMT_MMFREQ_MULTI_VD, arg);
+		break;
+	case VPPIO_MODSET_CSC:
+		{
+			struct vpp_mod_parm_t parm;
+			copy_from_user((void *) &parm, (const void *)arg,
+				sizeof(struct vpp_mod_parm_t));
+			switch (parm.mod) {
+			case VPP_MOD_GOVRH:
+				p_govrh->csc_mode_force = parm.parm;
+				break;
+			case VPP_MOD_GOVRH2:
+				if (p_govrh2->csc_mode_force != parm.parm)
+					MSG("GOVRH2 CSC %d-->%d\n",
+					p_govrh2->csc_mode_force, parm.parm);
+				p_govrh2->csc_mode_force = parm.parm;
+				break;
+			default:
+				break;
+			}
+		}
+		break;
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+	return retval;
+}
+
+int vpp_vout_ioctl(unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+
+	switch (cmd) {
+	case VPPIO_VOGET_INFO:
+		{
+		vpp_vout_info_t parm;
+		struct vout_info_t *info;
+		int fb_no, i, idx;
+		unsigned int status;
+
+		memset(&parm, 0, sizeof(vpp_vout_info_t));
+		for (fb_no = 0, idx = 0; ; fb_no++) {
+			info = vout_info_get_entry(fb_no);
+			if (!info)
+				break;
+
+			for (i = 0; i < VPP_VOUT_NUM; i++, idx++) {
+				if (info->vout[i] == 0)
+					break;
+				parm.mode[idx] = vout_get_mode_adapter(
+					info->vout[i]);
+				status = info->vout[i]->status |
+					(fb_no << 8);
+				DBGMSG("GET_INFO(fb %d,mode %d,sts 0x%x)",
+					fb_no, parm.mode[idx], status);
+				DBGMSG("plug %d\n",
+					(status & VPP_VOUT_STS_PLUGIN) ? 1 : 0);
+				parm.status[idx] = status;
+			}
+		}
+		copy_to_user((void *)arg, (const void *) &parm,
+			sizeof(vpp_vout_info_t));
+		}
+		break;
+	case VPPIO_VOUT_VMODE:
+		{
+		vpp_vout_vmode_t parm;
+		int i;
+		struct fb_videomode *vmode;
+		unsigned int resx, resy, fps;
+		unsigned int pre_resx, pre_resy, pre_fps;
+		int index, from_index;
+		int support;
+		unsigned int option, pre_option;
+#ifdef CONFIG_WMT_EDID
+		struct edid_info_t *edid_info;
+#endif
+		struct fb_videomode *edid_vmode;
+		vpp_vout_t mode;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_vout_vmode_t));
+		from_index = parm.num;
+		parm.num = 0;
+		mode = parm.mode & 0xF;
+#ifdef CONFIG_VPP_DEMO
+		parm.parm[parm.num].resx = 1920;
+		parm.parm[parm.num].resy = 1080;
+		parm.parm[parm.num].fps = 60;
+		parm.parm[parm.num].option = 0;
+		parm.num++;
+#else
+#ifdef CONFIG_WMT_EDID
+		{
+		struct vout_t *vo;
+
+		vo = vout_get_entry_adapter(mode);
+		if (!vo)
+			goto vout_vmode_end;
+
+		if (!(vo->status & VPP_VOUT_STS_PLUGIN)) {
+			DPRINT("*W* not plugin\n");
+			goto vout_vmode_end;
+		}
+
+		if (vout_get_edid(vo->num) == 0) {
+			DPRINT("*W* read EDID fail\n");
+			goto vout_vmode_end;
+		}
+		if (edid_parse(vo->edid, &vo->edid_info) == 0) {
+			DPRINT("*W* parse EDID fail\n");
+			goto vout_vmode_end;
+		}
+		edid_info = &vo->edid_info;
+		}
+#endif
+		index = 0;
+		resx = resy = fps = option = 0;
+		pre_resx = pre_resy = pre_fps = pre_option = 0;
+		for (i = 0; ; i++) {
+            int ret = 0;
+			vmode = (struct fb_videomode *) &vpp_videomode[i];
+			if (vmode->pixclock == 0)
+				break;
+			resx = vmode->xres;
+			resy = vmode->yres;
+			fps = vmode->refresh;
+			option = fps & EDID_TMR_FREQ;
+			option |= (vmode->vmode & FB_VMODE_INTERLACED) ?
+				EDID_TMR_INTERLACE : 0;
+			if ((pre_resx == resx) && (pre_resy == resy) &&
+				(pre_fps == fps) && (pre_option == option))
+				continue;
+			pre_resx = resx;
+			pre_resy = resy;
+			pre_fps = fps;
+			pre_option = option;
+			support = 0;
+#ifdef CONFIG_WMT_EDID
+			if (ret = edid_find_support(edid_info, resx, resy,
+				option, &edid_vmode))
+#else
+			if (1)
+#endif
+				support = 1;
+
+			if (support) {
+				if (index >= from_index) {
+					parm.parm[parm.num].resx = resx;
+					parm.parm[parm.num].resy = resy;
+					parm.parm[parm.num].fps = fps;
+					parm.parm[parm.num].option =
+						vmode->vmode;
+#ifdef CONFIG_WMT_EDID
+                    if(ret == 3)
+                        parm.parm[parm.num].option |= 0x80;
+#endif
+					parm.num++;
+				}
+				index++;
+				if (parm.num >= VPP_VOUT_VMODE_NUM)
+					break;
+			}
+		}
+#ifdef CONFIG_WMT_EDID
+vout_vmode_end:
+#endif
+#endif
+#if 0
+		if (parm.num == 0) { /* if no EDID*/
+			enum vout_tvformat_t tvformat = vout_get_tvformat();
+			if (g_vpp.virtual_display ||
+				(g_vpp.dual_display == 0)) {
+				if (mode == VPP_VOUT_DVI) {
+					switch (tvformat) {
+					case TV_PAL:
+						parm.parm[0].resx = 720;
+						parm.parm[0].resy = 576;
+						parm.parm[0].fps = 50;
+						parm.num = 1;
+						parm.parm[0].option = 0;
+						break;
+					case TV_NTSC:
+						parm.parm[0].resx = 720;
+						parm.parm[0].resy = 480;
+						parm.parm[0].fps = 60;
+						parm.num = 1;
+						parm.parm[0].option = 0;
+						break;
+					default:
+						break;
+					}
+				}
+			}
+		}
+#endif
+		DBG_MSG("[VPP] get support vmode %d\n", parm.num);
+		copy_to_user((void *)arg, (const void *) &parm,
+			sizeof(vpp_vout_vmode_t));
+		}
+		break;
+	case VPPIO_VOGET_EDID:
+		{
+		vpp_vout_edid_t parm;
+		char *edid;
+		struct vout_t *vo;
+		int size;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_vout_edid_t));
+		size = 0;
+#ifdef CONFIG_WMT_EDID
+		vo = vout_get_entry_adapter(parm.mode);
+		if (!vo)
+			goto vout_edid_end;
+
+		if (!(vo->status & VPP_VOUT_STS_PLUGIN)) {
+			DBG_ERR("*W* not plugin\n");
+			goto vout_edid_end;
+		}
+
+		edid = vout_get_edid(vo->num);
+		if (edid == 0) {
+			DBG_ERR("*W* read EDID fail\n");
+			goto vout_edid_end;
+		}
+		size = (edid[0x7E] + 1) * 128;
+		if (size > parm.size)
+			size = parm.size;
+		copy_to_user((void *) parm.buf, (void *) edid, size);
+vout_edid_end:
+#endif
+		parm.size = size;
+		copy_to_user((void *)arg, (const void *) &parm,
+			sizeof(vpp_vout_edid_t));
+		}
+		break;
+	case VPPIO_VOGET_CP_INFO:
+		{
+		vpp_vout_cp_info_t parm;
+		int num;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_vout_cp_info_t));
+		num = parm.num;
+		if (num >= VOUT_MODE_MAX) {
+			retval = -ENOTTY;
+			break;
+		}
+		memset(&parm, 0, sizeof(vpp_vout_cp_info_t));
+		switch (num) {
+		case VOUT_HDMI:
+			if (!g_vpp.hdmi_certify_flag) {
+				if (g_vpp.hdmi_bksv[0] == 0) {
+					hdmi_get_bksv(&g_vpp.hdmi_bksv[0]);
+					DBG_MSG("get BKSV 0x%x 0x%x\n",
+						g_vpp.hdmi_bksv[0],
+						g_vpp.hdmi_bksv[1]);
+				}
+			}
+		case VOUT_DVO2HDMI:
+			parm.bksv[0] = g_vpp.hdmi_bksv[0];
+			parm.bksv[1] = g_vpp.hdmi_bksv[1];
+			break;
+		default:
+			parm.bksv[0] = parm.bksv[1] = 0;
+			break;
+		}
+		copy_to_user((void *)arg, (const void *) &parm,
+			sizeof(vpp_vout_cp_info_t));
+		}
+		break;
+	case VPPIO_VOSET_CP_KEY:
+		if (g_vpp.hdmi_cp_p == 0) {
+			g_vpp.hdmi_cp_p = kmalloc(sizeof(vpp_vout_cp_key_t),
+				GFP_KERNEL);
+		}
+		if (g_vpp.hdmi_cp_p) {
+			copy_from_user((void *) g_vpp.hdmi_cp_p,
+				(const void *)arg, sizeof(vpp_vout_cp_key_t));
+			if (hdmi_cp)
+				hdmi_cp->init();
+		}
+		break;
+#ifdef WMT_FTBLK_HDMI
+	case VPPIO_VOSET_AUDIO_PASSTHRU:
+		hdmi_regs1->aud_mode.b.sub_packet = (arg) ? 0xF : 0x0;
+		break;
+#endif
+#ifdef CONFIG_VPP_VIRTUAL_DISPLAY
+	case VPPIO_VOSET_VIRTUAL_FBDEV:
+		{
+		struct vout_info_t *info;
+		int i;
+
+		g_vpp.fb0_bitblit = (arg) ? 0 : 1;
+		for (i = 1; ; i++) {
+			info = vout_info_get_entry(i);
+			if (!info)
+				break;
+			if (info->alloc_mode != VOUT_ALLOC_GE_OVERSCAN)
+				continue;
+			if (info->mb == 0)
+				continue;
+			MSG("fb%d mb free 0x%x\n", i, info->mb);
+			mb_free(info->mb);
+			info->mb = 0;
+		}
+		MSG("[VPP] virtual display %d\n", (int)arg);
+		}
+		break;
+#endif
+	case VPPIO_VOGET_HDMI_3D:
+		{
+		struct vpp_vout_parm_s parm;
+		struct vout_t *vo;
+
+		vo = vout_get_entry(VPP_VOUT_NUM_HDMI);
+		parm.arg = edid_get_hdmi_3d_mask(&vo->edid_info, hdmi_info.vic);
+		copy_to_user((void *)arg, (const void *) &parm,
+			sizeof(struct vpp_vout_parm_s));
+		}
+		break;
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+	return retval;
+}
+
+int vpp_scl_ioctl(unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+
+	switch (cmd) {
+	case VPPIO_SCL_SCALE_OVERLAP:
+		{
+		vpp_scale_overlap_t parm;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_scale_overlap_t));
+		if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+			vpp_dbg_timer(&p_scl->overlap_timer, 0, 1);
+
+		p_scl->scale_sync = 1;
+		retval = scl_set_scale_overlap(&parm.src_fb,
+			&parm.src2_fb, &parm.dst_fb);
+
+		if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+			vpp_dbg_timer(&p_scl->overlap_timer, "overlap", 2);
+		}
+		break;
+	case VPPIO_SCL_SCALE_ASYNC:
+	case VPPIO_SCL_SCALE:
+		{
+		vpp_scale_t parm;
+
+		p_scl->scale_sync = (cmd == VPPIO_SCL_SCALE) ? 1 : 0;
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_scale_t));
+		if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+			vpp_dbg_timer(&p_scl->scale_timer, 0, 1);
+
+		vpp_set_NA12_hiprio(1);
+		retval = vpp_set_recursive_scale(&parm.src_fb, &parm.dst_fb);
+		vpp_set_NA12_hiprio(0);
+
+		if (vpp_check_dbg_level(VPP_DBGLVL_FPS))
+			vpp_dbg_timer(&p_scl->scale_timer, "scale", 2);
+		copy_to_user((void *)arg, (void *)&parm, sizeof(vpp_scale_t));
+		}
+		break;
+	case VPPIO_SCL_SCALE_FINISH:
+		retval = p_scl->scale_finish();
+		break;
+	case VPPIO_SCLSET_OVERLAP:
+		{
+		vpp_overlap_t parm;
+
+		copy_from_user((void *) &parm, (const void *)arg,
+			sizeof(vpp_overlap_t));
+		vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_ENABLE, 0);
+		scl_set_overlap(&parm);
+		vpp_mod_set_clock(VPP_MOD_SCL, VPP_FLAG_DISABLE, 0);
+		}
+		break;
+	default:
+		retval = -ENOTTY;
+		break;
+	}
+	return retval;
+}
+
+static int wmt_vpp_open(struct inode *inode, struct file *filp)
+{
+	DBG_MSG("\n");
+	return 0;
+}
+
+static int wmt_vpp_release(struct inode *inode, struct file *filp)
+{
+	DBG_MSG("\n");
+	return 0;
+}
+
+static long wmt_vpp_ioctl(struct file *filp, unsigned int cmd,
+						unsigned long arg)
+{
+	int ret = -EINVAL;
+	int skip_mutex = 0;
+
+/*	DBG_MSG("0x%x,0x%x\n", cmd, (int)arg); */
+
+	if (_IOC_TYPE(cmd) != VPPIO_MAGIC)
+		return -ENOTTY;
+	if (_IOC_NR(cmd) > VPPIO_MAX)
+		return -ENOTTY;
+
+	/* check argument area */
+	if (_IOC_DIR(cmd) & _IOC_READ)
+		ret = !access_ok(VERIFY_WRITE,
+				(void __user *) arg, _IOC_SIZE(cmd));
+	else if (_IOC_DIR(cmd) & _IOC_WRITE)
+		ret = !access_ok(VERIFY_READ,
+				(void __user *) arg, _IOC_SIZE(cmd));
+	else
+		ret = 0;
+
+	if (ret)
+		return -EFAULT;
+
+	if (vpp_check_dbg_level(VPP_DBGLVL_IOCTL)) {
+		switch (cmd) {
+		default:
+			DPRINT("[VPP] ioctl cmd 0x%x,arg 0x%x\n",
+				_IOC_NR(cmd), (int)arg);
+			break;
+		}
+	}
+
+	switch (cmd) {
+	case VPPIO_STREAM_GETFB: /* block mode should wait vsync */
+		skip_mutex = 1;
+		break;
+	default:
+		/* scale should wait complete */
+		if ((_IOC_NR(cmd) >= VPPIO_SCL_BASE) &&
+			(_IOC_NR(cmd) < VPPIO_MAX))
+			skip_mutex = 1;
+		break;
+	}
+
+	if (!skip_mutex)
+		down(&wmt_vpp_sem);
+
+	switch (_IOC_NR(cmd)) {
+	case VPPIO_VPP_BASE ... (VPPIO_VOUT_BASE-1):
+		/* DBGMSG("VPP command ioctl\n"); */
+		ret = vpp_common_ioctl(cmd, arg);
+		break;
+	case VPPIO_VOUT_BASE ... (VPPIO_SCL_BASE - 1):
+		ret = vpp_vout_ioctl(cmd, arg);
+		break;
+	case VPPIO_SCL_BASE ... (VPPIO_MAX-1):
+		/* DBGMSG("SCL ioctl\n"); */
+		ret = vpp_scl_ioctl(cmd, arg);
+		break;
+	default:
+		DBG_ERR("*W* cmd 0x%x\n", cmd);
+		break;
+	}
+
+	if (!skip_mutex)
+		up(&wmt_vpp_sem);
+
+	if (vpp_check_dbg_level(VPP_DBGLVL_IOCTL)) {
+		switch (cmd) {
+		default:
+			DPRINT("[VPP] ioctl cmd 0x%x,ret 0x%x\n",
+				_IOC_NR(cmd), (int)ret);
+			break;
+		}
+	}
+	return ret;
+}
+
+const struct file_operations wmt_vpp_fops = {
+	.owner          = THIS_MODULE,
+	.open           = wmt_vpp_open,
+	.release        = wmt_vpp_release,
+	.unlocked_ioctl = wmt_vpp_ioctl,
+};
+
+static int wmt_vpp_probe(struct platform_device *dev)
+{
+	DBG_MSG("\n");
+
+	vpp_irqproc_init();
+	vpp_netlink_init();
+	vpp_init();
+#ifdef CONFIG_VPP_PROC
+	/* init system proc */
+	if (vpp_proc_dir == 0) {
+		struct proc_dir_entry *res;
+
+		vpp_proc_dir = proc_mkdir("driver/vpp", NULL);
+		res = create_proc_entry("sts", 0, vpp_proc_dir);
+		if (res)
+			res->read_proc = vpp_sts_read_proc;
+		res = create_proc_entry("reg", 0, vpp_proc_dir);
+		if (res)
+			res->read_proc = vpp_reg_read_proc;
+		vpp_table_header = register_sysctl_table(vpp_root_table);
+	}
+#endif
+
+	/* init interrupt service routine */
+#ifdef WMT_FTBLK_SCL
+	if (vpp_request_irq(VPP_IRQ_SCL, vpp_interrupt_routine,
+		SA_INTERRUPT, "scl", (void *)&g_vpp)) {
+		DPRINT("*E* request VPP ISR fail\n");
+		return -1;
+	}
+#endif
+	if (vpp_request_irq(VPP_IRQ_VPPM, vpp_interrupt_routine,
+		SA_INTERRUPT, "vpp", (void *)&g_vpp)) {
+		DPRINT("*E* request VPP ISR fail\n");
+		return -1;
+	}
+#ifdef WMT_FTBLK_GOVRH
+	if (vpp_request_irq(VPP_IRQ_GOVR, vpp_interrupt_routine,
+		SA_INTERRUPT, "govr", (void *)&g_vpp)) {
+		DPRINT("*E* request VPP ISR fail\n");
+		return -1;
+	}
+
+	if (vpp_request_irq(VPP_IRQ_GOVR2, vpp_interrupt_routine,
+		SA_INTERRUPT, "govr2", (void *)&g_vpp)) {
+		DPRINT("*E* request VPP ISR fail\n");
+		return -1;
+	}
+#endif
+	vpp_switch_state_init();
+	return 0;
+}
+
+static int wmt_vpp_remove(struct platform_device *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_PM
+unsigned int wmt_vpp_vout_blank_mask;
+static int wmt_vpp_suspend(struct device *dev)
+{
+
+	struct vpp_mod_base_t *mod_p;
+	struct vout_t *vo;
+	int i;
+
+	DPRINT("Enter wmt_vpp_suspend\n");
+
+	wmt_vpp_vout_blank_mask = 0;
+	for (i = 0; i <= VPP_VOUT_NUM; i++) {
+		vo = vout_get_entry(i);
+		if (vo && !(vo->status & VPP_VOUT_STS_BLANK))
+			wmt_vpp_vout_blank_mask |= (0x1 << i);
+		vout_set_blank(i, VOUT_BLANK_POWERDOWN);
+		if (vo && vo->dev && vo->dev->suspend)
+			vo->dev->suspend();
+	}
+
+	if (vout_check_plugin(1))
+		vpp_netlink_notify_plug(VPP_VOUT_ALL, 0);
+	else
+		wmt_set_mmfreq(0);
+
+	/* disable module */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->suspend)
+			mod_p->suspend(0);
+	}
+#ifdef WMT_FTBLK_HDMI
+	hdmi_suspend(0);
+#endif
+	wmt_suspend_mmfreq();
+#ifdef WMT_FTBLK_LVDS
+	lvds_suspend(0);
+#endif
+	/* disable tg */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->suspend)
+			mod_p->suspend(1);
+	}
+#ifdef WMT_FTBLK_HDMI
+	hdmi_suspend(1);
+#endif
+#ifdef WMT_FTBLK_LVDS
+	lvds_suspend(1);
+#endif
+	/* backup registers */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->suspend)
+			mod_p->suspend(2);
+	}
+#ifdef WMT_FTBLK_HDMI
+	hdmi_suspend(2);
+#endif
+#ifdef WMT_FTBLK_LVDS
+	lvds_suspend(2);
+#endif
+#if 0
+	if (lcd_get_lvds_id() == LCD_LVDS_1024x600) {
+		mdelay(5);
+		/* GPIO10 off  8ms -> clock -> off */
+		outl(inl(GPIO_BASE_ADDR + 0xC0) & ~BIT10,
+			GPIO_BASE_ADDR + 0xC0);
+	}
+#endif
+	return 0;
+}
+
+static int wmt_vpp_freeze(struct device *dev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_VPP_SHENZHEN
+extern int lcd_spi_resume(void);
+#endif
+
+static int wmt_vpp_resume(struct device *dev)
+{
+
+	struct vpp_mod_base_t *mod_p;
+	int i;
+
+#if 0
+	if (lcd_get_lvds_id() == LCD_LVDS_1024x600) {
+		/* GPIO10 6ms -> clock r0.02.04 */
+		outl(inl(GPIO_BASE_ADDR + 0x80) | BIT10,
+			GPIO_BASE_ADDR + 0x80);
+		outl(inl(GPIO_BASE_ADDR + 0xC0) | BIT10,
+			GPIO_BASE_ADDR + 0xC0);
+	}
+#endif
+
+	DPRINT("Enter wmt_vpp_resume\n");
+
+#ifdef CONFIG_VPP_SHENZHEN
+	lcd_spi_resume();
+#endif
+
+	/* restore registers */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->resume)
+			mod_p->resume(0);
+	}
+#ifdef WMT_FTBLK_LVDS
+	lvds_resume(0);
+#endif
+#ifdef WMT_FTBLK_HDMI
+	hdmi_check_plugin(0);
+	hdmi_resume(0);
+#endif
+	/* enable tg */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->resume)
+			mod_p->resume(1);
+	}
+#ifdef WMT_FTBLK_LVDS
+	lvds_resume(1);
+#endif
+#ifdef WMT_FTBLK_HDMI
+	hdmi_resume(1);
+#endif
+	/* wait */
+	msleep(150);
+
+	/* enable module */
+	for (i = 0; i < VPP_MOD_MAX; i++) {
+		mod_p = vpp_mod_get_base(i);
+		if (mod_p && mod_p->resume)
+			mod_p->resume(2);
+	}
+#ifdef WMT_FTBLK_LVDS
+	lvds_resume(2);
+#endif
+	if (lcd_get_lvds_id() != LCD_LVDS_1024x600) {
+		for (i = 0; i < VPP_VOUT_NUM; i++) {
+                        struct vout_t *vo;
+
+                        vo = vout_get_entry(i);
+                        if (vo && vo->dev) {
+				if (lcd_get_type() == 0) /* DVI type */
+                                govrh_set_dvo_enable(vo->govr, 1);
+                                vo->dev->init(vo);
+                                vo->dev->set_mode(&vo->option[0]);
+                                vo->inf->init(vo, 0);
+                        }
+
+			if (wmt_vpp_vout_blank_mask & (0x1 << i))
+				vout_set_blank(i, VOUT_BLANK_UNBLANK);
+			if (vo && vo->dev && vo->dev->resume)
+				vo->dev->resume();
+		}
+	}
+	wmt_resume_mmfreq();
+	if (vout_check_plugin(0))
+		vpp_netlink_notify_plug(VPP_VOUT_ALL, 1);
+	else
+		wmt_set_mmfreq(0);
+#ifdef WMT_FTBLK_HDMI
+	hdmi_resume(2);
+#endif
+	return 0;
+}
+
+static int wmt_vpp_restore(struct device *dev)
+{
+	return 0;
+}
+
+static void wmt_vpp_shutdown
+(
+	struct platform_device *pDev	/*!<; // a pointer struct device */
+)
+{
+	DPRINT("wmt_vpp_shutdown\n");
+	hdmi_set_power_down(1);
+	lvds_set_power_down(1);
+}
+
+#else
+#define wmt_vpp_suspend NULL
+#define wmt_vpp_resume NULL
+#define wmt_vpp_shutdown NULL
+#endif
+
+/********************************************************************
+	device driver struct define
+**********************************************************************/
+static struct dev_pm_ops wmt_vpp_pm_ops = {
+	.suspend	= wmt_vpp_suspend,
+	.resume		= wmt_vpp_resume,
+	.freeze		= wmt_vpp_freeze,
+	.thaw		= wmt_vpp_restore,
+	.restore	= wmt_vpp_restore,
+};
+
+static struct platform_driver wmt_vpp_driver = {
+	.driver.name    = DEVICE_NAME, /* equal to platform device name. */
+/*	.bus            = &platform_bus_type, */
+	.probe          = wmt_vpp_probe,
+	.remove         = wmt_vpp_remove,
+	/* .suspend	= wmt_vpp_suspend, */
+	/* .resume	= wmt_vpp_resume, */
+	.shutdown	= wmt_vpp_shutdown,
+	.driver.pm	= &wmt_vpp_pm_ops
+};
+
+static void wmt_vpp_platform_release(struct device *device)
+{
+}
+
+/********************************************************************
+	platform device struct define
+*********************************************************************/
+/* static u64 wmt_vpp_dma_mask = 0xffffffffUL; */
+static struct platform_device wmt_vpp_device = {
+	.name   = DEVICE_NAME,
+	.id     = 0,
+	.dev    = {
+		.release = wmt_vpp_platform_release,
+#if 0
+		.dma_mask = &wmt_vpp_dma_mask,
+		.coherent_dma_mask = ~0,
+#endif
+	},
+	.num_resources  = 0,	/* ARRAY_SIZE(cipher_resources), */
+	.resource       = NULL,	/* cipher_resources, */
+};
+
+static int __init wmt_vpp_init(void)
+{
+	int ret;
+	dev_t dev_no;
+
+	wmt_vpp_major = register_chrdev(0, DEVICE_NAME, &wmt_vpp_fops);
+	if (wmt_vpp_major < 0) {
+		DBG_ERR("get major failed\n");
+		return -EFAULT;
+	}
+
+	wmt_vpp_class = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(wmt_vpp_class)) {
+		ret = PTR_ERR(wmt_vpp_class);
+		DBG_ERR("Can't create class : %s !!\n", DEVICE_NAME);
+		return ret;
+	}
+
+	dev_no = MKDEV(wmt_vpp_major, 0);
+	device_create(wmt_vpp_class, NULL, dev_no, NULL, DEVICE_NAME);
+	ret = platform_device_register(&wmt_vpp_device);
+	if (ret != 0)
+		return -ENODEV;
+
+	ret = platform_driver_register(&wmt_vpp_driver);
+	if (ret != 0) {
+		platform_device_unregister(&wmt_vpp_device);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+static void __exit wmt_vpp_exit(void)
+{
+	dev_t dev_no;
+
+	DBG_MSG("\n");
+
+	vout_exit();
+#ifdef CONFIG_VPP_PROC
+	unregister_sysctl_table(vpp_table_header);
+#endif
+	platform_driver_unregister(&wmt_vpp_driver);
+	platform_device_unregister(&wmt_vpp_device);
+	dev_no = MKDEV(wmt_vpp_major, 0);
+	device_destroy(wmt_vpp_class, dev_no);
+	class_destroy(wmt_vpp_class);
+	unregister_chrdev(wmt_vpp_major, DEVICE_NAME);
+	return;
+}
+
+module_init(wmt_vpp_init);
+module_exit(wmt_vpp_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("WMT VPP driver");
+MODULE_AUTHOR("WMT TECH");
+MODULE_VERSION("1.0.0");
+
diff --git a/drivers/video/wmt/wmtfb.c b/drivers/video/wmt/wmtfb.c
new file mode 100755
index 00000000..72029bbc
--- /dev/null
+++ b/drivers/video/wmt/wmtfb.c
@@ -0,0 +1,1110 @@
+/*++
+ * linux/drivers/video/wmt/wmtfb.c
+ * WonderMedia frame buffer driver
+ *
+ * Copyright c 2014  WonderMedia  Technologies, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * WonderMedia Technologies, Inc.
+ * 4F, 533, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C
+--*/
+
+#define WMTFB_C
+/* #define DEBUG */
+/* #define DEBUG_DETAIL */
+
+/*----------------------- DEPENDENCE -----------------------------------------*/
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
+#include <linux/mm.h>
+#include <linux/proc_fs.h>
+
+#include "vpp.h"
+
+/*----------------------- PRIVATE MACRO --------------------------------------*/
+
+/*----------------------- PRIVATE CONSTANTS ----------------------------------*/
+/* #define FBUT_XXXX    1     *//*Example*/
+
+/*----------------------- PRIVATE TYPE  --------------------------------------*/
+/* typedef  xxxx fbut_xxx_t; *//*Example*/
+
+/*----------------------- INTERNAL PRIVATE VARIABLES - -----------------------*/
+/* int  fbut_xxx;        *//*Example*/
+
+static struct fb_fix_screeninfo wmtfb_fix = {
+	.id             = "wmtfbx",
+	.smem_start     = 0,
+	.smem_len       = 0,
+	.type           = FB_TYPE_PACKED_PIXELS,
+	.type_aux       = 0,
+	.visual         = FB_VISUAL_TRUECOLOR,
+	.xpanstep       = 1,
+	.ypanstep       = 1,
+	.ywrapstep      = 1,
+	.line_length    = 0,
+	.mmio_start     = 0,
+	.mmio_len       = 0,
+	.accel          = FB_ACCEL_NONE
+};
+
+static struct fb_var_screeninfo wmtfb_var = {
+	.xres           = 0,
+	.yres           = 0,
+	.xres_virtual   = 0,
+	.yres_virtual   = 0,
+#if 0
+	.bits_per_pixel = 32,
+	.red            = {16, 8, 0},
+	.green          = {8, 8, 0},
+	.blue           = {0, 8, 0},
+	.transp         = {24, 8, 0},
+#else
+	.bits_per_pixel = 16,
+	.red            = {11, 5, 0},
+	.green          = {5, 6, 0},
+	.blue           = {0, 5, 0},
+	.transp         = {0, 0, 0},
+#endif
+	.activate       = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE,
+	.height         = -1,
+	.width          = -1,
+	.pixclock       = 0,
+	.left_margin    = 40,
+	.right_margin   = 24,
+	.upper_margin   = 32,
+	.lower_margin   = 11,
+	.hsync_len      = 96,
+	.vsync_len      = 2,
+	.vmode          = FB_VMODE_NONINTERLACED
+};
+
+int wmtfb_probe_ready;
+/*--------------------- INTERNAL PRIVATE FUNCTIONS ---------------------------*/
+/* void fbut_xxx(void); *//*Example*/
+
+/*----------------------- Function Body --------------------------------------*/
+/*----------------------- Linux Proc --------------------------------------*/
+#ifdef DEBUG
+void wmtfb_show_var(char *str, struct fb_var_screeninfo *var)
+{
+	int pixclk;
+
+	pixclk = (var->pixclock) ? (PICOS2KHZ(var->pixclock) * 1000) : 0;
+	DPRINT("----- %s ------------------------\n", str);
+	DPRINT("res(%d,%d),vir(%d,%d),offset(%d,%d)\n",
+		var->xres, var->yres, var->xres_virtual,
+		var->yres_virtual, var->xoffset, var->yoffset);
+	DPRINT("pixclk %d(%d),hsync %d,vsync %d\n", var->pixclock, pixclk,
+		var->hsync_len, var->vsync_len);
+	DPRINT("left %d,right %d,upper %d,lower %d\n", var->left_margin,
+		var->right_margin, var->upper_margin, var->lower_margin);
+	DPRINT("bpp %d, grayscale %d\n", var->bits_per_pixel, var->grayscale);
+	DPRINT("nonstd %d, activate %d, height %d, width %d\n",
+		var->nonstd, var->activate, var->height, var->width);
+	DPRINT("vmode 0x%x,sync 0x%x,rotate %d,accel %d\n",
+		var->vmode, var->sync, var->rotate, var->accel_flags);
+	DPRINT("-----------------------------\n");
+	return;
+}
+#endif
+
+static DEFINE_SEMAPHORE(vpp_sem);
+static DEFINE_SEMAPHORE(vpp_sem2);
+void wmtfb_set_mutex(struct fb_info *info, int lock)
+{
+	struct vout_info_t *par = (struct vout_info_t *) info->par;
+
+	if (lock)
+		down(&par->sem);
+	else
+		up(&par->sem);
+}
+
+int vpp_set_blank(struct fb_info *info, int blank)
+{
+	struct vout_info_t *par = (struct vout_info_t *) info->par;
+	int i;
+
+	DBG_MSG("(%d,%d)\n", info->node, blank);
+
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		if (par->vout[i] == 0)
+			break;
+		vout_set_blank(par->vout[i]->num, blank);
+	}
+	return 0;
+}
+
+void vpp_set_lvds_blank(int blank)
+{
+	if (lcd_get_lvds_id() != LCD_LVDS_1024x600)
+		return;
+
+	if (blank == 0) {
+		outl(inl(GPIO_BASE_ADDR + 0xC0) | BIT10, GPIO_BASE_ADDR + 0xC0);
+		outl(inl(GPIO_BASE_ADDR + 0x80) | BIT10, GPIO_BASE_ADDR + 0x80);
+		mdelay(6);
+	}
+
+	if (blank)
+		msleep(50);
+
+	vout_set_blank(VPP_VOUT_NUM_LVDS,
+		(blank) ? VOUT_BLANK_POWERDOWN : VOUT_BLANK_UNBLANK);
+	lvds_set_power_down((blank) ? 1 : 0);
+
+	if (blank) {
+		mdelay(6);
+		/* GPIO10 off  8ms -> clock -> off */
+		outl(inl(GPIO_BASE_ADDR + 0xC0) & ~BIT10,
+			GPIO_BASE_ADDR + 0xC0);
+	}
+}
+
+void vpp_var_to_fb(struct fb_var_screeninfo *var,
+				struct fb_info *info, vdo_framebuf_t *fb)
+{
+	unsigned int addr;
+	int y_bpp, c_bpp;
+
+	if (var) {
+		fb->col_fmt = WMT_FB_COLFMT(var->nonstd);
+		if (!fb->col_fmt) {
+			switch (var->bits_per_pixel) {
+			case 16:
+				if ((info->var.red.length == 5) &&
+					(info->var.green.length == 6) &&
+					(info->var.blue.length == 5)) {
+					fb->col_fmt = VDO_COL_FMT_RGB_565;
+				} else if ((info->var.red.length == 5) &&
+					(info->var.green.length == 5) &&
+					(info->var.blue.length == 5)) {
+					fb->col_fmt = VDO_COL_FMT_RGB_1555;
+				} else {
+					fb->col_fmt = VDO_COL_FMT_RGB_5551;
+				}
+				break;
+			case 32:
+				fb->col_fmt = VDO_COL_FMT_ARGB;
+				break;
+			default:
+				fb->col_fmt = VDO_COL_FMT_RGB_565;
+				break;
+			}
+			y_bpp = var->bits_per_pixel;
+			c_bpp = 0;
+		} else {
+			y_bpp = 8;
+			c_bpp = 8;
+		}
+
+		fb->img_w = var->xres;
+		fb->img_h = var->yres;
+		fb->fb_w = var->xres_virtual;
+		fb->fb_h = var->yres_virtual;
+		fb->h_crop = 0;
+		fb->v_crop = 0;
+		fb->flag = 0;
+		fb->bpp = var->bits_per_pixel;
+
+		addr = info->fix.smem_start +
+		(var->yoffset * var->xres_virtual * ((y_bpp + c_bpp) >> 3));
+		addr += var->xoffset * ((y_bpp) >> 3);
+		fb->y_addr = addr;
+		fb->y_size = var->xres_virtual * var->yres * (y_bpp >> 3);
+		fb->c_addr = fb->y_addr + fb->y_size;
+		fb->c_size = var->xres_virtual * var->yres * (c_bpp >> 3);
+	}
+}
+
+void vpp_pan_display_bitblit(struct vout_info_t *par)
+{
+	vdo_framebuf_t src, dst;
+	struct fb_videomode vmode;
+	struct govrh_mod_t *govr;
+	struct fb_info *dfb_info;
+	struct vout_info_t *d_info;
+	int fb_no;
+
+	/* DBG_MSG("fb0 bitblit\n"); */
+	src = par->fb;
+	for (fb_no = 1; ; fb_no++) {
+		d_info = vout_info_get_entry(fb_no);
+		if (!d_info)
+			break;
+
+		govr = vout_info_get_govr(fb_no);
+		if (govr == 0)
+			break;
+		govrh_get_framebuffer(govr, &dst);
+		govrh_get_videomode(govr, &vmode);
+		dst.img_w = vmode.xres;
+		dst.fb_w = vpp_calc_fb_width(dst.col_fmt, dst.img_w);
+		dst.img_h = vmode.yres;
+		dst.fb_h = vmode.yres;
+		dst.y_size = dst.fb_w * dst.img_h * (dst.bpp >> 3);
+
+		dfb_info = (struct fb_info *) d_info->fb_info_p;
+		if (dfb_info) {
+			dfb_info->var.yoffset =
+				(dfb_info->var.yoffset) ? 0 : dst.img_h;
+			dst.y_addr = dfb_info->fix.smem_start +
+				(dst.fb_w * dfb_info->var.yoffset *
+				(dst.bpp >> 3));
+			dst.c_addr = 0;
+		} else {
+			govrh_get_fb_addr(govr, &dst.y_addr, &dst.c_addr);
+		}
+
+		if (d_info->alloc_mode == VOUT_ALLOC_GE_OVERSCAN) {
+			if (!d_info->mb) {
+				int size = dst.y_size * VPP_MB_ALLOC_NUM;
+
+				d_info->mb = mb_alloc(size);
+				if (d_info->mb) {
+					MSG("mb alloc 0x%x,%d\n",
+						d_info->mb, size);
+				} else {
+					DBG_ERR("alloc fail\n");
+					return;
+				}
+			}
+			dst.y_addr = d_info->mb +
+				(dst.fb_w * dfb_info->var.yoffset *
+				(dst.bpp >> 3));
+		}
+
+		if (dst.y_addr) {
+			p_scl->scale_sync = 1;
+			vpp_set_recursive_scale(&src, &dst);
+			vout_set_framebuffer(d_info, &dst);
+		}
+	}
+}
+
+int vpp_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct vout_info_t *par = (struct vout_info_t *) info->par;
+
+	if (g_vpp.hdmi_certify_flag)
+		return 0;
+
+	DBG_DETAIL("fb %d\n", (info) ? info->node : 0);
+	vpp_var_to_fb(var, info, &par->fb);
+	if (wmtfb_probe_ready && g_vpp.fb0_bitblit && (info->node == 0))
+		vpp_pan_display_bitblit(par);
+	else
+		vout_set_framebuffer(par, &par->fb);
+
+#ifdef CONFIG_VPP_STREAM_CAPTURE
+	if (g_vpp.stream_enable && (par->hwc_mode == VOUT_HWC_VIRTUAL)) {
+		g_vpp.stream_mb_index = var->yoffset / var->yres;
+		vpp_dbg_show_val1(VPP_DBGLVL_STREAM, 0,
+			"stream pan disp", g_vpp.stream_mb_index);
+	}
+#endif
+	if (vpp_check_dbg_level(VPP_DBGLVL_DISPFB)) {
+		char buf[50];
+		unsigned int yaddr = 0, caddr = 0;
+		struct govrh_mod_t *govr;
+
+		govr = vout_info_get_govr(info->node);
+		if (govr)
+			govrh_get_fb_addr(govr, &yaddr, &caddr);
+		sprintf(buf, "pan_display %d,0x%x", par->num, yaddr);
+		vpp_dbg_show(VPP_DBGLVL_DISPFB, par->num + 1, buf);
+	}
+
+	if (vpp_check_dbg_level(VPP_DBGLVL_FPS)) {
+		char buf[10];
+
+		sprintf(buf, "fb%d", par->num);
+		vpp_dbg_timer(&par->pandisp_timer, buf, 2);
+	}
+	return 0;
+}
+
+int vpp_set_par(struct fb_info *info)
+{
+	struct vout_info_t *par = (struct vout_info_t *) info->par;
+	vdo_framebuf_t fb;
+	struct fb_videomode var, cur;
+	struct govrh_mod_t *govr;
+
+	if (g_vpp.hdmi_certify_flag)
+		return 0;
+
+	govr = vout_info_get_govr(info->node);
+	if (!govr)
+		return 0;
+
+	wmtfb_set_mutex(info, 1);
+
+	/* check frame buffer */
+	vpp_var_to_fb(&info->var, info, &fb);
+	par->fb.fb_h = fb.fb_h;
+	if (memcmp(&fb.img_w, &par->fb.img_w, 32)) {
+		if ((wmtfb_probe_ready == 0) && g_vpp.govrh_preinit) {
+			MSG("[uboot logo] fb%d\n", info->node);
+			govrh_get_framebuffer(govr, &par->fb);
+			vpp_set_recursive_scale(&par->fb, &fb);
+		}
+#ifdef DEBUG
+		MSG("set_par %d : set framebuf\n",
+			info->node);
+		vpp_show_framebuf("cur", &par->fb);
+		vpp_show_framebuf("new", &fb);
+#endif
+		par->fb = fb;
+	} else {
+		fb.img_w = 0;
+	}
+
+	/* check timing */
+	fb_var_to_videomode(&var, &info->var);
+	govrh_get_videomode(govr, &cur);
+	if ((cur.xres == var.xres) && (cur.yres == var.yres)) {
+		unsigned int cur_pixclk, new_pixclk;
+
+		/* diff less than 500K */
+		cur_pixclk = PICOS2KHZ(cur.pixclock);
+		new_pixclk = PICOS2KHZ(var.pixclock);
+		if (abs(new_pixclk - cur_pixclk) < 500) {
+			var.pixclock = cur.pixclock;
+			var.refresh = cur.refresh;
+		}
+		/* diff less than 2 */
+		if (abs(var.refresh - cur.refresh) <= 2)
+			var.refresh = cur.refresh;
+	}
+
+	//var.sync &= (FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT);
+    var.sync = cur.sync;
+	if (memcmp(&var, &cur, sizeof(struct fb_videomode))) {
+#ifdef DEBUG
+		DPRINT("[wmtfb] set_par %d: set timing\n", info->node);
+		vpp_show_timing("cur", &cur, 0);
+		vpp_show_timing("new", &var, 0);
+#endif
+	} else {
+		var.xres = 0;
+	}
+	vout_config(par, (var.xres) ? &var : 0, (fb.img_w) ? &fb : 0);
+	wmtfb_set_mutex(info, 0);
+	return 0;
+}
+
+int vpp_get_info(int fbn, struct fb_var_screeninfo *var)
+{
+	struct vout_info_t *par;
+
+	par = vout_info_get_entry(fbn);
+	if (!par)
+		return -1;
+
+	var->xres = par->resx;
+	var->yres = par->resy;
+	var->xres_virtual = par->resx_virtual;
+	var->yres_virtual = var->yres * VPP_MB_ALLOC_NUM;
+	var->bits_per_pixel = (g_vpp.mb_colfmt == VDO_COL_FMT_ARGB) ? 32 : 16;
+	var->pixclock = par->resx * par->resy * par->fps;
+	var->pixclock = (var->pixclock) ? (var->pixclock / 1000) : 0;
+	var->pixclock = (var->pixclock) ? KHZ2PICOS(var->pixclock) : 0;
+	var->left_margin = 0;
+	var->right_margin = 0;
+	var->upper_margin = 0;
+	var->lower_margin = 0;
+	var->hsync_len = 0;
+	var->vsync_len = 0;
+        if (par->option & VPP_OPT_INTERLACE) {
+                var->vmode |= FB_VMODE_INTERLACED;
+                var->pixclock *= 2;
+        }
+#ifdef DEBUG
+	MSG("[get_info] fb%d\n", fbn);
+	wmtfb_show_var("get_info", var);
+#endif
+	return 0;
+}
+
+int wmtfb_alloc(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct vout_info_t *par = (struct vout_info_t *) info->par;
+	unsigned int size;
+	int no_alloc = 0;
+	vdo_color_fmt colfmt;
+	int y_bpp, c_bpp;
+	unsigned int mb_resx, mb_resy, fb_num;
+	int i;
+
+	colfmt = (var->nonstd) ? WMT_FB_COLFMT(var->nonstd) :
+		((var->bits_per_pixel == 16) ?
+		VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB);
+	vpp_get_colfmt_bpp(colfmt, &y_bpp, &c_bpp);
+
+	switch (par->alloc_mode) {
+	case VOUT_ALLOC_FIX_MB:
+		if (info->fix.smem_start) {
+			no_alloc = 1;
+			break;
+		}
+
+		{
+		char buf[100];
+		int varlen = 100;
+
+		if (wmt_getsyspara("wmt.display.mb",
+			(unsigned char *)buf, &varlen) == 0) {
+			unsigned int parm[10];
+
+			vpp_parse_param(buf, (unsigned int *)parm, 4, 0);
+			MSG("boot parm mb (%d,%d),bpp %d,fb %d\n",
+					parm[0], parm[1], parm[2], parm[3]);
+			mb_resx = parm[0];
+			mb_resy = parm[1];
+			y_bpp = parm[2] * 8;
+			c_bpp = 0;
+			fb_num = parm[3];
+		} else {
+			mb_resx = VPP_HD_MAX_RESX;
+			mb_resy = VPP_HD_MAX_RESY;
+			fb_num = VPP_MB_ALLOC_NUM;
+		}
+		}
+		break;
+	case VOUT_ALLOC_DYNAMIC_MB:
+		if ((par->hwc_mode == VOUT_HWC_VIRTUAL)
+			&& !wmtfb_probe_ready) {
+			no_alloc = 1;
+			break;
+		}
+		mb_resx = var->xres_virtual;
+		mb_resy = var->yres;
+		fb_num = VPP_MB_ALLOC_NUM;
+		break;
+	case VOUT_ALLOC_GE_OVERSCAN:
+		if (!info->fix.smem_start) {
+			struct vout_info_t *fb0_par;
+			struct fb_info *fb0_info;
+
+			fb0_par = vout_info_get_entry(0);
+			fb0_info = (struct fb_info *) fb0_par->fb_info_p;
+			info->fix.smem_start = fb0_info->fix.smem_start;
+			info->fix.smem_len = fb0_info->fix.smem_len;
+			info->screen_base = fb0_info->screen_base;
+			info->screen_size = fb0_info->screen_size;
+		}
+	default:
+		no_alloc = 1;
+		break;
+	}
+#if 0
+	DBG_MSG("fb%d,mode %d,size %d,len %d,%dx%d,no alloc %d\n",
+		info->node, par->alloc_mode, size, info->fix.smem_len,
+		var->xres, var->yres, no_alloc);
+#endif
+	if (no_alloc)
+		return 0; /* don't need */
+
+	size = mb_resx * mb_resy * ((y_bpp + c_bpp) / 8) * fb_num ;
+	if (size == info->fix.smem_len)
+		return 0;
+
+	/* free pre mb */
+	if (info->fix.smem_start) {
+		mb_free(info->fix.smem_start);
+		info->fix.smem_start = 0;
+		info->fix.smem_len = 0;
+		info->screen_base = 0;
+		info->screen_size = 0;
+		MSG("[wmtfb] fb%d free mb\n", info->node);
+	}
+
+	if ((var->xres == 0) || (var->yres == 0))
+		return -1;
+
+	info->fix.smem_start = mb_alloc(size);
+	if (!info->fix.smem_start) {
+		DBG_ERR("fb%d alloc mb fail %d\n", info->node, size);
+		return -1;
+	}
+	info->fix.smem_len = size;
+	info->screen_base = mb_phys_to_virt(info->fix.smem_start);
+	info->screen_size = size;
+	MSG("[wmtfb] fb%d mb 0x%x,len %d,base 0x%x(%d,%d,%d)\n", info->node,
+		(int) info->fix.smem_start, info->fix.smem_len,
+		(int) info->screen_base, mb_resx, mb_resy, fb_num);
+
+	if (wmtfb_probe_ready) {
+		int ysize, csize;
+
+		size = size / fb_num;
+		ysize = mb_resx * mb_resy * y_bpp / 8;
+		csize = mb_resx * mb_resy * c_bpp / 8;
+		for (i = 0; i < fb_num; i++) {
+			memset(info->screen_base + i * size, 0x0, ysize);
+			if (c_bpp)
+				memset(info->screen_base + i * size + ysize,
+					0x80, csize);
+		}
+	}
+
+	if (par->hwc_mode == VOUT_HWC_VIRTUAL) {
+		vpp_lock();
+		g_vpp.stream_mb_cnt = VPP_MB_ALLOC_NUM;
+		size = var->xres_virtual * var->yres * ((y_bpp + c_bpp) / 8);
+		for (i = 0; i < g_vpp.stream_mb_cnt; i++)
+			g_vpp.stream_mb[i] = info->fix.smem_start + size * i;
+		vpp_unlock();
+	}
+	return 0;
+}
+
+static int wmtfb_open
+(
+	struct fb_info *info,   /*!<; // a pointer point to struct fb_info */
+	int user                /*!<; // user space mode */
+)
+{
+	DBG_MSG("Enter wmtfb_open\n");
+	return 0;
+}
+
+static int wmtfb_release
+(
+	struct fb_info *info,   /*!<; // a pointer point to struct fb_info */
+	int user                /*!<; // user space mode */
+)
+{
+	DBG_MSG("Enter wmtfb_release\n");
+	return 0;
+}
+
+int wmtfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
+{
+	struct vout_info_t *par;
+	int temp;
+	int force = 0;
+
+#ifdef DEBUG_DETAIL
+	DMSG("Enter %d\n", info->node);
+	wmtfb_show_var("[check_var beg] cur var", &info->var);
+	wmtfb_show_var("[check_var beg] new var", var);
+#endif
+	if (!info->par) { /* link fb & vout info */
+		par = vout_info_get_entry(info->node);
+		info->par = (void *) par;
+		par->fb_info_p = (void *) info;
+	}
+
+	par = (struct vout_info_t *) info->par;
+	if (par->alloc_mode == VOUT_ALLOC_GE_OVERSCAN) {
+		struct vout_info_t *fb0_par;
+
+		fb0_par = vout_info_get_entry(0);
+		var->xres_virtual = fb0_par->resx_virtual;
+		var->yres_virtual = fb0_par->resy_virtual * VPP_MB_ALLOC_NUM;
+	} else {
+		var->xres_virtual = vpp_calc_fb_width(
+			(var->bits_per_pixel == 16) ?
+			VDO_COL_FMT_RGB_565 : VDO_COL_FMT_ARGB,
+			(var->xres_virtual < var->xres) ?
+			var->xres : var->xres_virtual);
+	}
+
+	if (wmtfb_alloc(var, info))
+		return -ENOMEM;
+
+	if ((var->xres == 0) || (var->yres == 0))
+		return -1;
+
+	temp = var->xres_virtual * (var->bits_per_pixel >> 3);
+	temp = (temp) ? (info->fix.smem_len / temp) : 0;
+	if (temp < var->yres_virtual) {
+		var->yres_virtual = temp;
+	}
+
+	/* more than 1M is khz not picos (for ut_vpp) */
+	if (var->pixclock > 1000000) {
+		temp = var->pixclock / 1000;
+		temp = (temp) ? KHZ2PICOS(temp) : 0;
+		DBG_MSG("pixclock patch(>1000000)%d-->%d\n",
+			var->pixclock, temp);
+		var->pixclock = temp;
+	}
+
+	/* less than 100 is fps not picos (for ut_vpp) */
+	if ((var->pixclock > 0) && (var->pixclock < 100)) {
+		unsigned int htotal, vtotal;
+
+		htotal = var->xres + var->right_margin + var->hsync_len +
+			var->left_margin;
+		vtotal = var->yres + var->lower_margin + var->vsync_len +
+			var->upper_margin;
+		temp = (htotal * vtotal * var->pixclock) / 1000;
+		temp = (temp) ? KHZ2PICOS(temp) : 0;
+		DBG_MSG("pixclock patch(<100)%d-->%d\n", var->pixclock, temp);
+		var->pixclock = temp;
+	}
+#ifdef DEBUG_DETAIL
+	wmtfb_show_var("cur var", &info->var);
+	wmtfb_show_var("new var", var);
+#endif
+	switch (var->bits_per_pixel) {
+	case 1:
+	case 8:
+		if (var->red.offset > 8) {
+			var->red.offset = 0;
+			var->red.length = 8;
+			var->green.offset = 0;
+			var->green.length = 8;
+			var->blue.offset = 0;
+			var->blue.length = 8;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 16: /* ARGB 1555 */
+		if (var->transp.length) {
+			var->red.offset = 10;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 5;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 15;
+			var->transp.length = 1;
+		} else { /* RGB 565 */
+			var->red.offset = 11;
+			var->red.length = 5;
+			var->green.offset = 5;
+			var->green.length = 6;
+			var->blue.offset = 0;
+			var->blue.length = 5;
+			var->transp.offset = 0;
+			var->transp.length = 0;
+		}
+		break;
+	case 24: /* RGB 888 */
+	case 32: /* ARGB 8888 */
+		var->red.offset = 16;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 0;
+		var->blue.length = 8;
+		var->transp.offset = 0;
+		var->transp.length = 0;
+		break;
+	}
+
+	if (g_vpp.fb_manual)
+		return 0;
+
+	if (!wmtfb_probe_ready)
+		force = 1;
+
+	if (g_vpp.fb_recheck & (0x1 << info->node)) {
+		force = 1;
+		g_vpp.fb_recheck &= ~(0x1 << info->node);
+	}
+
+	if ((var->xres != info->var.xres) || (var->yres != info->var.yres) ||
+		memcmp(&info->var.pixclock, &var->pixclock, 4 * 9) || force) {
+		struct fb_videomode varfbmode;
+		unsigned int yres_virtual;
+		unsigned int xres_virtual;
+
+		DPRINT("[wmtfb_check_var] fb%d res(%d,%d)->(%d,%d),force %d\n",
+			info->node, info->var.xres, info->var.yres,
+			var->xres, var->yres, force);
+#ifdef DEBUG
+		wmtfb_show_var("cur var", &info->var);
+		wmtfb_show_var("new var", var);
+#endif
+		yres_virtual = var->yres_virtual;
+		xres_virtual = var->xres_virtual;
+		fb_var_to_videomode(&varfbmode, var);
+#ifdef DEBUG
+		DPRINT("new fps %d\n", varfbmode.refresh);
+#endif
+		if (vout_find_match_mode(info->node, &varfbmode, 1)) {
+			DPRINT("[wmtfb] not support\n");
+			return -1;
+		}
+		fb_videomode_to_var(var, &varfbmode);
+		var->yres_virtual = yres_virtual;
+		var->xres_virtual = xres_virtual;
+#ifdef DEBUG
+		wmtfb_show_var("[wmtfb] time change", var);
+#endif
+		vout_get_width_height(info->node, &var->width, &var->height);
+	}
+	return 0;
+}
+
+static int wmtfb_set_par
+(
+	struct fb_info *info /*!<; // a pointer point to struct fb_info */
+)
+{
+	struct fb_var_screeninfo *var = &info->var;
+
+	DBG_DETAIL("Enter fb%d(%dx%d)\n", info->node, var->xres, var->yres);
+
+	/* init your hardware here */
+	/* ... */
+	if (var->bits_per_pixel == 8)
+		info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
+	else
+		info->fix.visual = FB_VISUAL_TRUECOLOR;
+	vpp_set_par(info);
+	info->fix.line_length = var->xres_virtual * var->bits_per_pixel / 8;
+	return 0;
+}
+
+static int wmtfb_setcolreg
+(
+	unsigned regno,         /*!<; // register no */
+	unsigned red,           /*!<; // red color map */
+	unsigned green,         /*!<; // green color map */
+	unsigned blue,          /*!<; // blue color map */
+	unsigned transp,        /*!<; // transp map */
+	struct fb_info *info    /*!<; // a pointer point to struct fb_info */
+)
+{
+	return 0;
+
+}
+
+static int wmtfb_pan_display
+(
+	struct fb_var_screeninfo *var,  /*!<; // a pointer fb_var_screeninfo */
+	struct fb_info *info            /*!<; // a pointer fb_info */
+)
+{
+	static struct timeval tv1 = {0, 0};
+
+	DBG_DETAIL("Enter wmtfb_pan_display\n");
+
+	wmtfb_set_mutex(info, 1);
+	if (var->activate & FB_ACTIVATE_VBL) {
+		struct timeval tv2;
+
+		do_gettimeofday(&tv2);
+		if (tv1.tv_sec) {
+			int us;
+
+			us = (tv2.tv_sec == tv1.tv_sec) ?
+				(tv2.tv_usec - tv1.tv_usec) :
+				(1000000 + tv2.tv_usec - tv1.tv_usec);
+			if (us < 16667)
+				vpp_wait_vsync(1, 1);
+		}
+	}
+	vpp_pan_display(var, info);
+	do_gettimeofday(&tv1);
+	wmtfb_set_mutex(info, 0);
+
+	DBG_DETAIL("Exit wmtfb_pan_display\n");
+	return 0;
+}
+
+#define UMP_INVALID_SECURE_ID    ((unsigned int)-1)
+#define GET_UMP_SECURE_ID        _IOWR('m', 310, unsigned int)
+#define GET_UMP_SECURE_ID_BUF1   _IOWR('m', 311, unsigned int)
+#define GET_UMP_SECURE_ID_BUF2   _IOWR('m', 312, unsigned int)
+int wmtfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
+{
+	int retval = 0;
+
+	switch (cmd) {
+	case FBIO_WAITFORVSYNC:
+		vpp_wait_vsync(info->node, 1);
+		break;
+	case GET_UMP_SECURE_ID:
+	case GET_UMP_SECURE_ID_BUF1:
+	case GET_UMP_SECURE_ID_BUF2:
+		{
+		unsigned int ump_id;
+		extern unsigned int (*mali_get_ump_secure_id)
+			(unsigned int addr, unsigned int size);
+		if (mali_get_ump_secure_id)
+			ump_id = (*mali_get_ump_secure_id)(info->fix.smem_start,
+							   info->fix.smem_len);
+		else
+			ump_id = UMP_INVALID_SECURE_ID;
+		printk("[wmtfb] ump_id %d,0x%x,len %d\n", ump_id,
+			(int)info->fix.smem_start, info->fix.smem_len);
+		return put_user((unsigned int) ump_id,
+				(unsigned int __user *) arg);
+		}
+		break;
+	default:
+		break;
+	}
+	return retval;
+}
+
+static int wmtfb_mmap
+(
+	struct fb_info *info,           /*!<; // a pointer fb_info */
+	struct vm_area_struct *vma      /*!<; // a pointer vm_area_struct */
+)
+{
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+
+	DBGMSG("Enter wmtfb_mmap\n");
+
+	/* frame buffer memory */
+	start = info->fix.smem_start;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+	len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.smem_len);
+	if (off >= len) {
+		/* memory mapped io */
+		off -= len;
+		if (info->var.accel_flags)
+			return -EINVAL;
+		start = info->fix.mmio_start;
+		len = PAGE_ALIGN((start & ~PAGE_MASK) + info->fix.mmio_len);
+	}
+
+	start &= PAGE_MASK;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		return -EINVAL;
+	off += start;
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+		vma->vm_end - vma->vm_start, vma->vm_page_prot))
+		return -EAGAIN;
+	DBGMSG("Exit wmtfb_mmap\n");
+	return 0;
+}
+
+int wmtfb_hw_cursor(struct fb_info *info, struct fb_cursor *cursor)
+{
+	return 0;
+}
+
+int wmtfb_blank(int blank, struct fb_info *info)
+{
+	DBGMSG("(%d,%d)\n", info->node, blank);
+	vpp_set_blank(info, blank);
+	return 0;
+}
+
+/***************************************************************************
+	driver file operations struct define
+****************************************************************************/
+static struct fb_ops wmtfb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = wmtfb_open,
+	.fb_release     = wmtfb_release,
+#if 0
+	.fb_read      = wmtfb_read,
+	.fb_write     = wmtfb_write,
+#endif
+	.fb_check_var   = wmtfb_check_var,
+	.fb_set_par     = wmtfb_set_par,
+	.fb_setcolreg   = wmtfb_setcolreg,
+	.fb_pan_display = wmtfb_pan_display,
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+	.fb_blank       = wmtfb_blank,
+	.fb_cursor      = wmtfb_hw_cursor,
+	.fb_ioctl       = wmtfb_ioctl,
+	.fb_mmap        = wmtfb_mmap,
+};
+
+static int __init wmtfb_probe
+(
+	struct platform_device *dev /*!<; // a pointer point to struct device */
+)
+{
+	struct fb_info *info;
+	struct fb_var_screeninfo var;
+	int i;
+
+	DBG_MSG("Enter\n");
+
+	for (i = 1; ; i++) {
+		memcpy(&var, &wmtfb_var, sizeof(struct fb_var_screeninfo));
+		if (vpp_get_info(i, &var))
+			break;
+		info = framebuffer_alloc(0, &dev->dev);
+		if (!info)
+			return -ENOMEM;
+		info->fbops = &wmtfb_ops;
+		memcpy(&info->fix, &wmtfb_fix,
+			sizeof(struct fb_fix_screeninfo));
+		info->fix.id[5] = '0' + i;
+		info->flags = FBINFO_DEFAULT;
+		if (register_framebuffer(info) < 0)
+			return -EINVAL;
+
+		MSG(KERN_INFO "fb%d: %s frame buffer device\n",
+			info->node, info->fix.id);
+
+		wmtfb_check_var(&var, info);
+		memcpy(&info->var, &var, sizeof(struct fb_var_screeninfo));
+		wmtfb_set_par(info);
+		wmtfb_pan_display(&info->var, info);
+
+		if (info->node == 1) {
+			info->dev->power.async_suspend = 1;
+			dev_set_drvdata(&dev->dev, info);
+		}
+	}
+
+	for (i = 0; i < VPP_VOUT_NUM; i++) {
+		int blank;
+		struct vout_t *vout;
+
+		vout = vout_get_entry(i);
+		if (!vout)
+			continue;
+		blank = (vout->status & VPP_VOUT_STS_ACTIVE) ?
+			VOUT_BLANK_UNBLANK : VOUT_BLANK_POWERDOWN;
+		blank = (vout->status & VPP_VOUT_STS_BLANK) ?
+			VOUT_BLANK_NORMAL : blank;
+		vout_set_blank(i, blank);
+	}
+	DBG_MSG("Leave\n");
+	wmtfb_probe_ready = 1;
+	g_vpp.govrh_preinit = 0;
+	return 0;
+}
+
+static int wmtfb_remove
+(
+	struct platform_device *dev /*!<; // a pointer point to struct device */
+)
+{
+	struct fb_info *info = dev_get_drvdata(&dev->dev);
+
+	if (info) {
+		unregister_framebuffer(info);
+		fb_dealloc_cmap(&info->cmap);
+		framebuffer_release(info);
+	}
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int wmtfb_suspend
+(
+	struct platform_device *pDev,   /*!<; // a pointer struct device */
+	pm_message_t state		/*!<; // suspend state */
+)
+{
+	return 0;
+}
+
+static int wmtfb_resume
+(
+	struct platform_device *pDev	/*!<; // a pointer struct device */
+)
+{
+	return 0;
+}
+#else
+#define wmtfb_suspend NULL
+#define wmtfb_resume NULL
+#endif
+
+/***************************************************************************
+	device driver struct define
+****************************************************************************/
+static struct platform_driver wmtfb_driver = {
+	.driver.name	= "wmtfb",
+	.driver.bus	= &platform_bus_type,
+	.probe		= wmtfb_probe,
+	.remove		= wmtfb_remove,
+	.suspend	= wmtfb_suspend,
+	.resume		= wmtfb_resume,
+};
+
+/***************************************************************************
+	platform device struct define
+****************************************************************************/
+static u64 wmtfb_dma_mask = 0xffffffffUL;
+static struct platform_device wmtfb_device = {
+	.name   = "wmtfb",
+	.dev    = {
+		.dma_mask = &wmtfb_dma_mask,
+		.coherent_dma_mask = ~0,
+		.power.async_suspend = 1,
+	},
+
+#if 0
+	.id     = 0,
+	.dev    = {
+		.release = wmtfb_platform_release,
+	},
+	.num_resources  = 0,    /* ARRAY_SIZE(wmtfb_resources), */
+	.resource       = NULL, /* wmtfb_resources, */
+#endif
+};
+
+static int __init wmtfb_init(void)
+{
+	int ret;
+
+	/*
+	 *  For kernel boot options (in 'video=wmtfb:<options>' format)
+	 */
+	ret = platform_driver_register(&wmtfb_driver);
+	if (!ret) {
+		ret = platform_device_register(&wmtfb_device);
+		if (ret)
+			platform_driver_unregister(&wmtfb_driver);
+	}
+	return ret;
+
+}
+module_init(wmtfb_init);
+
+static void __exit wmtfb_exit(void)
+{
+	printk(KERN_ALERT "Enter wmtfb_exit\n");
+
+	platform_driver_unregister(&wmtfb_driver);
+	platform_device_unregister(&wmtfb_device);
+	return;
+}
+module_exit(wmtfb_exit);
+
+MODULE_AUTHOR("WonderMedia SW Team");
+MODULE_DESCRIPTION("wmtfb device driver");
+MODULE_LICENSE("GPL");
+/*--------------------End of Function Body -----------------------------------*/
+#undef WMTFB_C
-- 
cgit