[linux-yocto] [PATCH 12/65] video: add owl video drivers

Jiang Lu lu.jiang at windriver.com
Wed Dec 21 01:16:13 PST 2016


From: wurui <wurui at actions-semi.com>

commit 120d6cf0a139e84b89314d1102e71fc8b03a6040 from
https://github.com/xapp-le/kernel.git

Change-Id: I7f686dbc76d414a15139b2b09bfe67a7c2793d8f
---
 drivers/video/Kconfig                              |    4 +
 drivers/video/fbdev/Kconfig                        |    1 +
 drivers/video/fbdev/Makefile                       |    1 +
 drivers/video/fbdev/core/fbmem.c                   |    1 +
 drivers/video/fbdev/owl/Kconfig                    |   16 +
 drivers/video/fbdev/owl/Makefile                   |    3 +
 drivers/video/fbdev/owl/backlight/Kconfig          |   10 +
 drivers/video/fbdev/owl/backlight/Makefile         |    1 +
 drivers/video/fbdev/owl/backlight/owl_pwm_bl.c     |  630 ++++++
 drivers/video/fbdev/owl/displays/Kconfig           |    5 +
 drivers/video/fbdev/owl/displays/Makefile          |    1 +
 drivers/video/fbdev/owl/displays/cvbs/Kconfig      |    9 +
 drivers/video/fbdev/owl/displays/cvbs/Makefile     |    4 +
 drivers/video/fbdev/owl/displays/cvbs/cvbs.c       |  847 ++++++++
 drivers/video/fbdev/owl/displays/cvbs/cvbs.h       |  125 ++
 drivers/video/fbdev/owl/displays/cvbs/cvbs_ip.h    |   54 +
 drivers/video/fbdev/owl/displays/cvbs/cvbs_reg.h   |  218 ++
 drivers/video/fbdev/owl/displays/cvbs/cvbs_sysfs.c |  120 ++
 drivers/video/fbdev/owl/displays/cvbs/panel-cvbs.c |  245 +++
 drivers/video/fbdev/owl/displays/dsi/Kconfig       |    9 +
 drivers/video/fbdev/owl/displays/dsi/Makefile      |    4 +
 drivers/video/fbdev/owl/displays/dsi/dsi.h         |   35 +
 drivers/video/fbdev/owl/displays/dsi/dsi_cmd.c     |   87 +
 drivers/video/fbdev/owl/displays/dsi/dsi_sysfs.c   |   90 +
 drivers/video/fbdev/owl/displays/dsi/dsihw.c       | 1222 +++++++++++
 drivers/video/fbdev/owl/displays/dsi/dsihw.h       |  141 ++
 drivers/video/fbdev/owl/displays/dsi/panel-mipi.c  |  251 +++
 drivers/video/fbdev/owl/displays/edp/edphw.c       |  709 +++++++
 drivers/video/fbdev/owl/displays/edp/edphw.h       |  259 +++
 .../fbdev/owl/displays/edp/panel-retina-fpga.c     |  233 +++
 drivers/video/fbdev/owl/displays/hdmi/Kconfig      |   13 +
 drivers/video/fbdev/owl/displays/hdmi/Makefile     |    4 +
 drivers/video/fbdev/owl/displays/hdmi/cec.h        |  100 +
 drivers/video/fbdev/owl/displays/hdmi/cec_reg.h    |  103 +
 drivers/video/fbdev/owl/displays/hdmi/hdcp.c       | 1310 ++++++++++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi.c       | 1289 ++++++++++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi.h       |  421 ++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_cec.c   |  404 ++++
 .../video/fbdev/owl/displays/hdmi/hdmi_cec_ctrl.c  |  406 ++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_edid.c  |  745 +++++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.c    |  906 +++++++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.h    |  189 ++
 .../video/fbdev/owl/displays/hdmi/hdmi_packet.c    |  453 +++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_panel.c |  343 ++++
 drivers/video/fbdev/owl/displays/hdmi/hdmi_sysfs.c |  440 ++++
 drivers/video/fbdev/owl/displays/lcdc/Kconfig      |    9 +
 drivers/video/fbdev/owl/displays/lcdc/Makefile     |    3 +
 drivers/video/fbdev/owl/displays/lcdc/lcdchw.c     | 1079 ++++++++++
 drivers/video/fbdev/owl/displays/lcdc/lcdchw.h     |   88 +
 drivers/video/fbdev/owl/displays/lcdc/panel-lcd.c  |  257 +++
 drivers/video/fbdev/owl/dss/Kconfig                |   45 +
 drivers/video/fbdev/owl/dss/Makefile               |    8 +
 drivers/video/fbdev/owl/dss/core.c                 |  681 +++++++
 drivers/video/fbdev/owl/dss/de.c                   | 1004 ++++++++++
 drivers/video/fbdev/owl/dss/de.h                   |  248 +++
 drivers/video/fbdev/owl/dss/de_atm7059.c           | 1222 +++++++++++
 drivers/video/fbdev/owl/dss/de_atm7059.h           |  154 ++
 drivers/video/fbdev/owl/dss/display.c              |  417 ++++
 drivers/video/fbdev/owl/dss/dss.h                  |  161 ++
 drivers/video/fbdev/owl/dss/dss_features.c         |  228 +++
 drivers/video/fbdev/owl/dss/dss_features.h         |  111 +
 drivers/video/fbdev/owl/dss/manager.c              | 1184 +++++++++++
 drivers/video/fbdev/owl/dss/mmu.c                  |  675 +++++++
 drivers/video/fbdev/owl/dss/overlay.c              |  935 +++++++++
 drivers/video/fbdev/owl/fb/Kconfig                 |   21 +
 drivers/video/fbdev/owl/fb/Makefile                |    2 +
 .../video/fbdev/owl/fb/owl-ddr-debug-readme.txt    |   99 +
 drivers/video/fbdev/owl/fb/owl-ddr-debug.c         |  461 +++++
 drivers/video/fbdev/owl/fb/owlfb-dc-debug.c        |  102 +
 drivers/video/fbdev/owl/fb/owlfb-dc.c              |  591 ++++++
 drivers/video/fbdev/owl/fb/owlfb-ioctl.c           |  887 ++++++++
 drivers/video/fbdev/owl/fb/owlfb-main.c            | 2118 ++++++++++++++++++++
 drivers/video/fbdev/owl/fb/owlfb-sysfs.c           |  498 +++++
 drivers/video/fbdev/owl/fb/owlfb.h                 |  228 +++
 drivers/video/fbdev/owl/switch/Kconfig             |   15 +
 drivers/video/fbdev/owl/switch/Makefile            |    4 +
 drivers/video/fbdev/owl/switch/switch_class.c      |  174 ++
 drivers/video/fbdev/owl/switch/switch_gpio.c       |  172 ++
 drivers/video/fbdev/owl/vce/Kconfig                |   11 +
 drivers/video/fbdev/owl/vce/Makefile               |    2 +
 drivers/video/fbdev/owl/vce/readme.txt             |   11 +
 drivers/video/fbdev/owl/vce/vce_drv.c              | 1616 +++++++++++++++
 drivers/video/fbdev/owl/vce/vce_drv.h              |   91 +
 drivers/video/fbdev/owl/vce/vce_reg.h              |   55 +
 drivers/video/fbdev/owl/vde/Kconfig                |   11 +
 drivers/video/fbdev/owl/vde/Makefile               |    2 +
 drivers/video/fbdev/owl/vde/vde_core.h             |  188 ++
 drivers/video/fbdev/owl/vde/vde_drv.c              | 1966 ++++++++++++++++++
 drivers/video/fbdev/owl/vde/vde_drv.h              |   20 +
 drivers/video/logo/Kconfig                         |   10 +
 drivers/video/logo/Makefile                        |    1 +
 drivers/video/logo/logo.c                          |    3 +
 drivers/video/logo/logo_actions_clut224.ppm        |  123 ++
 include/linux/fb.h                                 |    1 +
 include/linux/linux_logo.h                         |    1 +
 include/trace/events/owlfb_trace_events.h          |   98 +
 include/video/omapdss.h                            |   11 +
 include/video/owldisplay.h                         |  197 ++
 include/video/owldss.h                             |  597 ++++++
 include/video/owlfb.h                              |  332 +++
 kernel/power/Kconfig                               |   10 +
 kernel/power/Makefile                              |    1 +
 kernel/power/fbearlysuspend.c                      |  153 ++
 103 files changed, 31853 insertions(+)
 mode change 100644 => 100755 drivers/video/Kconfig
 mode change 100644 => 100755 drivers/video/fbdev/Kconfig
 mode change 100644 => 100755 drivers/video/fbdev/Makefile
 mode change 100644 => 100755 drivers/video/fbdev/core/fbmem.c
 create mode 100755 drivers/video/fbdev/owl/Kconfig
 create mode 100755 drivers/video/fbdev/owl/Makefile
 create mode 100755 drivers/video/fbdev/owl/backlight/Kconfig
 create mode 100755 drivers/video/fbdev/owl/backlight/Makefile
 create mode 100755 drivers/video/fbdev/owl/backlight/owl_pwm_bl.c
 create mode 100755 drivers/video/fbdev/owl/displays/Kconfig
 create mode 100755 drivers/video/fbdev/owl/displays/Makefile
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/Kconfig
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/Makefile
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/cvbs.c
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/cvbs.h
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/cvbs_ip.h
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/cvbs_reg.h
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/cvbs_sysfs.c
 create mode 100755 drivers/video/fbdev/owl/displays/cvbs/panel-cvbs.c
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/Kconfig
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/Makefile
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/dsi.h
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/dsi_cmd.c
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/dsi_sysfs.c
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/dsihw.c
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/dsihw.h
 create mode 100755 drivers/video/fbdev/owl/displays/dsi/panel-mipi.c
 create mode 100755 drivers/video/fbdev/owl/displays/edp/edphw.c
 create mode 100755 drivers/video/fbdev/owl/displays/edp/edphw.h
 create mode 100755 drivers/video/fbdev/owl/displays/edp/panel-retina-fpga.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/Kconfig
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/Makefile
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/cec.h
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/cec_reg.h
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdcp.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi.h
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_cec.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_cec_ctrl.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_edid.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.h
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_packet.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_panel.c
 create mode 100755 drivers/video/fbdev/owl/displays/hdmi/hdmi_sysfs.c
 create mode 100755 drivers/video/fbdev/owl/displays/lcdc/Kconfig
 create mode 100755 drivers/video/fbdev/owl/displays/lcdc/Makefile
 create mode 100755 drivers/video/fbdev/owl/displays/lcdc/lcdchw.c
 create mode 100755 drivers/video/fbdev/owl/displays/lcdc/lcdchw.h
 create mode 100755 drivers/video/fbdev/owl/displays/lcdc/panel-lcd.c
 create mode 100755 drivers/video/fbdev/owl/dss/Kconfig
 create mode 100755 drivers/video/fbdev/owl/dss/Makefile
 create mode 100755 drivers/video/fbdev/owl/dss/core.c
 create mode 100755 drivers/video/fbdev/owl/dss/de.c
 create mode 100755 drivers/video/fbdev/owl/dss/de.h
 create mode 100755 drivers/video/fbdev/owl/dss/de_atm7059.c
 create mode 100755 drivers/video/fbdev/owl/dss/de_atm7059.h
 create mode 100755 drivers/video/fbdev/owl/dss/display.c
 create mode 100755 drivers/video/fbdev/owl/dss/dss.h
 create mode 100755 drivers/video/fbdev/owl/dss/dss_features.c
 create mode 100755 drivers/video/fbdev/owl/dss/dss_features.h
 create mode 100755 drivers/video/fbdev/owl/dss/manager.c
 create mode 100755 drivers/video/fbdev/owl/dss/mmu.c
 create mode 100755 drivers/video/fbdev/owl/dss/overlay.c
 create mode 100755 drivers/video/fbdev/owl/fb/Kconfig
 create mode 100755 drivers/video/fbdev/owl/fb/Makefile
 create mode 100755 drivers/video/fbdev/owl/fb/owl-ddr-debug-readme.txt
 create mode 100755 drivers/video/fbdev/owl/fb/owl-ddr-debug.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb-dc-debug.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb-dc.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb-ioctl.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb-main.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb-sysfs.c
 create mode 100755 drivers/video/fbdev/owl/fb/owlfb.h
 create mode 100644 drivers/video/fbdev/owl/switch/Kconfig
 create mode 100644 drivers/video/fbdev/owl/switch/Makefile
 create mode 100644 drivers/video/fbdev/owl/switch/switch_class.c
 create mode 100644 drivers/video/fbdev/owl/switch/switch_gpio.c
 create mode 100755 drivers/video/fbdev/owl/vce/Kconfig
 create mode 100755 drivers/video/fbdev/owl/vce/Makefile
 create mode 100755 drivers/video/fbdev/owl/vce/readme.txt
 create mode 100755 drivers/video/fbdev/owl/vce/vce_drv.c
 create mode 100755 drivers/video/fbdev/owl/vce/vce_drv.h
 create mode 100755 drivers/video/fbdev/owl/vce/vce_reg.h
 create mode 100755 drivers/video/fbdev/owl/vde/Kconfig
 create mode 100755 drivers/video/fbdev/owl/vde/Makefile
 create mode 100755 drivers/video/fbdev/owl/vde/vde_core.h
 create mode 100755 drivers/video/fbdev/owl/vde/vde_drv.c
 create mode 100755 drivers/video/fbdev/owl/vde/vde_drv.h
 mode change 100644 => 100755 drivers/video/logo/Kconfig
 mode change 100644 => 100755 drivers/video/logo/Makefile
 mode change 100644 => 100755 drivers/video/logo/logo.c
 create mode 100755 drivers/video/logo/logo_actions_clut224.ppm
 mode change 100644 => 100755 include/linux/fb.h
 mode change 100644 => 100755 include/linux/linux_logo.h
 create mode 100755 include/trace/events/owlfb_trace_events.h
 mode change 100644 => 100755 include/video/omapdss.h
 create mode 100755 include/video/owldisplay.h
 create mode 100755 include/video/owldss.h
 create mode 100755 include/video/owlfb.h
 create mode 100755 kernel/power/fbearlysuspend.c

diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
old mode 100644
new mode 100755
index 8bf495f..c009491
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -17,6 +17,8 @@ config SH_LCD_MIPI_DSI
 
 source "drivers/char/agp/Kconfig"
 
+source "drivers/gpu/stub/Kconfig"
+
 source "drivers/gpu/vga/Kconfig"
 
 source "drivers/gpu/host1x/Kconfig"
@@ -32,6 +34,8 @@ endmenu
 
 source "drivers/video/backlight/Kconfig"
 
+source "drivers/gpu/pvr/Kconfig"
+
 config VGASTATE
        tristate
        default n
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
old mode 100644
new mode 100755
index 44eb7c7..13672c1
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2453,6 +2453,7 @@ source "drivers/video/fbdev/omap/Kconfig"
 source "drivers/video/fbdev/omap2/Kconfig"
 source "drivers/video/fbdev/exynos/Kconfig"
 source "drivers/video/fbdev/mmp/Kconfig"
+source "drivers/video/fbdev/owl/Kconfig"
 
 config FB_SH_MOBILE_MERAM
 	tristate "SuperH Mobile MERAM read ahead support"
diff --git a/drivers/video/fbdev/Makefile b/drivers/video/fbdev/Makefile
old mode 100644
new mode 100755
index 1979aff..fc88880
--- a/drivers/video/fbdev/Makefile
+++ b/drivers/video/fbdev/Makefile
@@ -152,3 +152,4 @@ obj-$(CONFIG_FB_SIMPLE)           += simplefb.o
 
 # the test framebuffer is last
 obj-$(CONFIG_FB_VIRTUAL)          += vfb.o
+obj-y                             += owl/
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
old mode 100644
new mode 100755
index 0705d88..be4e5ea
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1907,5 +1907,6 @@ int fb_new_modelist(struct fb_info *info)
 
 	return err;
 }
+EXPORT_SYMBOL(fb_new_modelist);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/Kconfig b/drivers/video/fbdev/owl/Kconfig
new file mode 100755
index 0000000..c3564be6
--- /dev/null
+++ b/drivers/video/fbdev/owl/Kconfig
@@ -0,0 +1,16 @@
+menuconfig VIDEO_OWL
+	bool "OWL video support"
+	depends on ARCH_OWL
+        help
+	  Actions OWL Soc video support.
+
+if VIDEO_OWL
+source "drivers/video/fbdev/owl/vce/Kconfig"
+source "drivers/video/fbdev/owl/vde/Kconfig"
+source "drivers/video/fbdev/owl/backlight/Kconfig"
+source "drivers/video/fbdev/owl/dss/Kconfig"
+source "drivers/video/fbdev/owl/displays/Kconfig"
+source "drivers/video/fbdev/owl/fb/Kconfig"
+
+source "drivers/video/fbdev/owl/switch/Kconfig"
+endif
diff --git a/drivers/video/fbdev/owl/Makefile b/drivers/video/fbdev/owl/Makefile
new file mode 100755
index 0000000..d669dbe
--- /dev/null
+++ b/drivers/video/fbdev/owl/Makefile
@@ -0,0 +1,3 @@
+obj-y += vce/
+obj-y += vde/
+obj-y += backlight/ dss/ displays/ fb/ switch/
diff --git a/drivers/video/fbdev/owl/backlight/Kconfig b/drivers/video/fbdev/owl/backlight/Kconfig
new file mode 100755
index 0000000..6b49a82
--- /dev/null
+++ b/drivers/video/fbdev/owl/backlight/Kconfig
@@ -0,0 +1,10 @@
+config VIDEO_OWL_PWM_BACKLIGHT
+	tristate "OWL PWM backlight support"
+	---help---
+	  Actions OWL Soc PWM backlight support.
+
+	  Say Y here if you need pwm backligh in your system.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called owl_pwm_bl.ko.
+
diff --git a/drivers/video/fbdev/owl/backlight/Makefile b/drivers/video/fbdev/owl/backlight/Makefile
new file mode 100755
index 0000000..ca46f8d
--- /dev/null
+++ b/drivers/video/fbdev/owl/backlight/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_OWL_PWM_BACKLIGHT)   += owl_pwm_bl.o
diff --git a/drivers/video/fbdev/owl/backlight/owl_pwm_bl.c b/drivers/video/fbdev/owl/backlight/owl_pwm_bl.c
new file mode 100755
index 0000000..748ba4a
--- /dev/null
+++ b/drivers/video/fbdev/owl/backlight/owl_pwm_bl.c
@@ -0,0 +1,630 @@
+/*
+ * linux/drivers/video/backlight/pwm_bl.c
+ *
+ * simple PWM based backlight control, board code has to setup
+ * 1) pin configuration so PWM waveforms can output
+ * 2) platform_data casts to the PWM id (0/1/2/3 on PXA)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/err.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <mach/hardware.h>
+#include <mach/pwm-owl.h>
+
+#include <linux/mfd/atc260x/atc260x.h>
+
+#if 0
+#define BL_PRINT(fmt, args...) printk(KERN_INFO fmt, ##args)
+#else
+#define BL_PRINT(fmt, args...)
+#endif
+
+struct pwm_en_gpio {
+    int             gpio;
+    int             active_low;
+};
+
+struct owl_pwm_bl_platform_data {
+    int             pwm_id;
+    unsigned int    total_steps;
+    unsigned int    max_brightness;
+    unsigned int    min_brightness;
+    unsigned int    dft_brightness;
+    unsigned int    pwm_period_ns;
+    unsigned int    polarity_inversed;
+
+    u32             delay_before_pwm;
+    u32             delay_after_pwm;
+
+    struct pwm_en_gpio en_gpio;
+
+    int (*init) (struct device *dev);
+    int (*notify) (int brightness);
+    void (*exit) (struct device *dev);
+};
+
+/*
+ * period,          PWM period in ns
+ * total_steps,     the total brightness levels in ns, max brightness
+ * threshold_step,  the start step in ns, another word, min brightness
+ * duty(ns) = brightness / total steps *  period
+ */
+struct owl_pwm_bl {
+    struct pwm_device   *pwm;
+    unsigned int        period;
+    unsigned int        total_steps;
+    unsigned int        threshold_step;
+    unsigned int        polarity_inversed;
+    int                 (*notify)(int brightness);
+
+    struct pwm_en_gpio  en_gpio;
+
+    int                 dev_enable;
+
+    u32                 delay_before_pwm;
+    u32                 delay_after_pwm;
+	bool 				need_update_bl;
+};
+
+static struct backlight_device *owl_pwm_bl_device = NULL;
+
+static int owl_pwm_bl_update_status(struct backlight_device *bl) {
+    struct owl_pwm_bl *pb = dev_get_drvdata(&bl->dev);
+
+    int brightness      = bl->props.brightness;
+    int total_steps     = pb->total_steps;
+
+    int old_dev_enable  = pb->dev_enable;
+
+    /* the percent of backlight, used to adjust charging cuurent */
+    int brightness_percent;
+
+    BL_PRINT("owl pwm bl update status\n");
+
+    if (bl->props.power != FB_BLANK_UNBLANK
+        || bl->props.fb_blank != FB_BLANK_UNBLANK) {
+        brightness = 0;
+		pb->need_update_bl = 1;
+    }
+
+    /* modified for the threshold_step */
+    if (brightness > 0) {
+        brightness += pb->threshold_step;
+    }
+
+    if (pb->notify) {
+        BL_PRINT("brightness from  notify\n");
+        brightness = pb->notify(brightness);
+    }
+
+    BL_PRINT("bl->props.power = %d\n", bl->props.power);
+    BL_PRINT("bl->props.fb_blank = %d\n", bl->props.fb_blank);
+    BL_PRINT("pb->polarity_inversed = %d\n", pb->polarity_inversed);
+
+    if (brightness > total_steps) {
+        return -EINVAL;
+    }
+
+    /*
+     * adjust the charger current according to brightness
+     */
+    if (brightness > 0) {
+        brightness_percent = bl->props.brightness * 100 / bl->props.max_brightness;
+    } else {
+        brightness_percent = 0;
+    }
+    config_inner_charger_current(DEV_CHARGER_PRE_CONFIG,
+                                 DEV_CHARGER_CURRENT_LCD,
+                                 brightness_percent);
+
+    if (brightness == 0) {
+        if (old_dev_enable == 0) {
+            goto config_out;
+        }
+
+        BL_PRINT("disable device, turn off backlight\n");
+
+        pb->dev_enable = 0;
+
+        if (gpio_is_valid(pb->en_gpio.gpio)) {
+            gpio_set_value(pb->en_gpio.gpio, pb->en_gpio.active_low);
+        }
+
+        /*
+         * First, ic's bug, backlight cannot be closed
+         * when polarity=1, duty=0.
+         * Second, pwm framework refuse to call
+         * pwm_set_polarity when pwm is enabled.
+         */
+        pb->pwm->chip->ops->set_polarity(pb->pwm->chip,
+                                         pb->pwm,
+                                         !pb->polarity_inversed);
+        pwm_config(pb->pwm, pb->period, pb->period);
+        msleep_interruptible(10);
+        pwm_disable(pb->pwm);
+    } else {
+        BL_PRINT("turn on backlight\n");
+        BL_PRINT("duty_ns = %x\n", brightness * pb->period / total_steps);
+        BL_PRINT("period_ns = %x\n", pb->period);
+
+        pwm_set_polarity(pb->pwm, pb->polarity_inversed);
+        pwm_config(pb->pwm, brightness * pb->period / total_steps,
+                   pb->period);
+        pwm_enable(pb->pwm);
+
+        if (old_dev_enable == 0) {
+            if (gpio_is_valid(pb->en_gpio.gpio)) {
+                if (pb->delay_after_pwm) {
+                    BL_PRINT("delay %d ms after pwm cfg\n", pb->delay_after_pwm);
+                    msleep_interruptible(pb->delay_after_pwm);
+                }
+                gpio_set_value(pb->en_gpio.gpio, !pb->en_gpio.active_low);
+            }
+        }
+
+        pb->dev_enable = 1;
+    }
+
+config_out:
+    config_inner_charger_current(DEV_CHARGER_POST_CONFIG,
+            DEV_CHARGER_CURRENT_LCD,
+            brightness_percent);
+
+    return 0;
+}
+
+static int owl_pwm_bl_get_brightness(struct backlight_device *bl) {
+    return bl->props.brightness;
+}
+
+static int owl_pwm_bl_check_fb(struct backlight_device *bl,
+                                  struct fb_info *fbi) {
+    return 0;
+}
+
+static const struct backlight_ops owl_pwm_bl_ops = {
+    .update_status  = owl_pwm_bl_update_status,
+    .get_brightness = owl_pwm_bl_get_brightness,
+    .check_fb       = owl_pwm_bl_check_fb,
+};
+
+static int of_parse_pwm_gpio(struct device_node *of_node,
+                             const char *propname,
+                             struct pwm_en_gpio *gpio) {
+    enum of_gpio_flags flags;
+    int gpio_num;
+
+    gpio_num = of_get_named_gpio_flags(of_node, propname, 0, &flags);
+    if (gpio_num >= 0) {
+        gpio->gpio = gpio_num;
+    } else {
+        gpio->gpio = -1;
+    }
+
+    gpio->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+    BL_PRINT("%s, gpio = %d\n", __func__, gpio->gpio);
+    BL_PRINT("%s, active low = %d\n", __func__, gpio->active_low);
+    return 0;
+}
+
+static int owl_pwm_bl_of_data_get(
+        struct platform_device *pdev,
+        struct owl_pwm_bl_platform_data *data) {
+    struct device_node *of_node;
+
+    memset(data, 0, sizeof(struct owl_pwm_bl_platform_data));
+
+    of_node = pdev->dev.of_node;
+
+    if (of_property_read_u32(of_node,
+        "total_steps", &data->total_steps)) {
+        return -EINVAL;
+    }
+
+    if (of_property_read_u32(of_node,
+        "max_brightness", &data->max_brightness)) {
+        return -EINVAL;
+    }
+
+    if (of_property_read_u32(of_node,
+        "min_brightness", &data->min_brightness)) {
+        return -EINVAL;
+    }
+
+    if (of_property_read_u32(of_node,
+        "dft_brightness", &data->dft_brightness)) {
+        return -EINVAL;
+    }
+
+    if (of_property_read_u32(of_node,
+        "delay_bf_pwm", &data->delay_before_pwm)) {
+        data->delay_before_pwm = 0;
+    }
+
+    if (of_property_read_u32(of_node,
+        "delay_af_pwm", &data->delay_after_pwm)) {
+        data->delay_after_pwm = 0;
+    }
+
+    of_parse_pwm_gpio(of_node, "backlight_en_gpios", &data->en_gpio);
+
+    return 0;
+}
+
+
+static bool boot_pwm_inited;
+
+static inline bool is_pwm_enabled(int hwpwm) {
+    /* 
+     * CMU_DEVCLKEN1 is 0xB0160070, FIXME
+     * return !!(act_readl(CMU_PWM0CLK + 4 * hwpwm));
+     */
+    return !!(readl(ioremap(0xB0160070 + 4 * hwpwm, 4)));
+}
+
+static void check_boot_pwm_inited(int hwpwm) {
+    /* 
+     * CMU_DEVCLKEN1 is 0xB01600A4, FIXME
+     * boot_pwm_inited = (act_readl(CMU_DEVCLKEN1) & (1 << (23 + hwpwm)));
+     */
+    boot_pwm_inited = (readl(ioremap(0xB01600A4, 4)) & (1 << (23 + hwpwm)));
+
+    if (boot_pwm_inited) {
+        boot_pwm_inited = (boot_pwm_inited && is_pwm_enabled(hwpwm));
+    }
+
+    BL_PRINT("PWM%d INITED FROM UBOOT??  %d\n", hwpwm, boot_pwm_inited);
+
+    return ;
+}
+
+static ssize_t show_total_steps(struct device *device,
+                                struct device_attribute *attr,
+                                char *buf) {
+    struct owl_pwm_bl *pb = dev_get_drvdata(device);
+
+    return snprintf(buf, PAGE_SIZE, "%d\n", pb->total_steps);
+}
+
+static ssize_t show_threshold_step(struct device *device,
+                                   struct device_attribute *attr,
+                                   char *buf) {
+    struct owl_pwm_bl *pb = dev_get_drvdata(device);
+
+    return snprintf(buf, PAGE_SIZE, "%d\n", pb->threshold_step);
+}
+
+static struct device_attribute owl_pwm_bl_attrs[] = {
+    __ATTR(total_steps, S_IRUGO, show_total_steps, NULL),
+    __ATTR(threshold_step, S_IRUGO, show_threshold_step, NULL),
+};
+
+int owl_pwm_bl_init_attr(struct device *dev) {
+    int i, error = 0;
+
+    BL_PRINT("init att\n");
+    for (i = 0; i < ARRAY_SIZE(owl_pwm_bl_attrs); i++) {
+        error = device_create_file(dev, &owl_pwm_bl_attrs[i]);
+
+        if (error) {
+            BL_PRINT("init attr err\n");
+            break;
+        }
+    }
+
+    if (error) {
+        while (--i >= 0) {
+            device_remove_file(dev, &owl_pwm_bl_attrs[i]);
+        }
+    }
+    return 0;
+}
+
+int owl_pwm_bl_remove_attr(struct device *dev) {
+    /*TODO*/
+    return 0;
+}
+
+static int owl_pwm_bl_probe(struct platform_device *pdev) {
+    struct owl_pwm_bl_platform_data  *data = pdev->dev.platform_data;
+    struct owl_pwm_bl_platform_data  of_data;
+    struct backlight_device             *bl;
+    struct backlight_properties         props;
+    struct owl_pwm_bl                *pb;
+    int                                 ret;
+
+    /* has the Open Firmare data from DT */
+    int                                 has_of_data = 0;
+
+    printk("%s: name = %s\n", __func__, pdev->name);
+
+    BL_PRINT("%s: get platform data\n", __func__);
+    if (!data) {
+        /* pdev has no platform data, get them from DT */
+        ret = owl_pwm_bl_of_data_get(pdev, &of_data);
+        if (ret < 0) {
+            dev_err(&pdev->dev, "failed to find platform data\n");
+            return ret;
+        }
+
+        data        = &of_data;
+        has_of_data = 1;
+    }
+
+    BL_PRINT("%s: data->init\n", __func__);
+    if (data->init) {
+        if ((ret = data->init(&pdev->dev)) < 0) {
+            return ret;
+        }
+    }
+
+    BL_PRINT("%s: alloc pb\n", __func__);
+    pb = kzalloc(sizeof(*pb), GFP_KERNEL);
+    if (!pb) {
+        dev_err(&pdev->dev, "no memory for state\n");
+        ret = -ENOMEM;
+        goto err_alloc;
+    }
+
+    BL_PRINT("%s: init pb\n", __func__);
+
+    pb->total_steps     = data->total_steps;
+    pb->threshold_step  = data->min_brightness;
+    pb->notify          = data->notify;
+	pb->need_update_bl = 0;
+
+    BL_PRINT("%s: get pwm device\n", __func__);
+    pb->pwm = devm_pwm_get(&pdev->dev, NULL);
+    if (IS_ERR(pb->pwm)) {
+        dev_err(&pdev->dev, "unable to request PWM, trying legacy API\n");
+
+        pb->pwm = pwm_request(data->pwm_id, "pwm-backlight");
+        if (IS_ERR(pb->pwm)) {
+            dev_err(&pdev->dev, "unable to request legacy PWM\n");
+            ret = PTR_ERR(pb->pwm);
+            goto err_pwm;
+        }
+    }
+
+    pb->delay_before_pwm    = data->delay_before_pwm;
+    pb->delay_after_pwm     = data->delay_after_pwm;
+    pb->en_gpio.gpio        = data->en_gpio.gpio;
+    pb->en_gpio.active_low  = data->en_gpio.active_low;
+
+    gpio_request(pb->en_gpio.gpio, NULL);
+
+    check_boot_pwm_inited(pb->pwm->hwpwm);
+
+    BL_PRINT("%s: get period\n", __func__);
+
+    pb->polarity_inversed = data->polarity_inversed;
+    /*
+     * The DT case will set the pwm_period_ns field to 0 and store the
+     * period, parsed from the DT, in the PWM device. For the non-DT case,
+     * set the period from platform data.
+     */
+    if (has_of_data) {
+        pb->polarity_inversed = owl_pwm_get_polarity(pb->pwm);
+    } else {
+        pwm_set_period(pb->pwm, data->pwm_period_ns);
+    }
+    pb->period = pwm_get_period(pb->pwm);
+
+    BL_PRINT("%s: register backlight\n", __func__);
+
+    memset(&props, 0, sizeof(props));
+    props.type              = BACKLIGHT_RAW;
+    props.max_brightness    = data->max_brightness - pb->threshold_step;
+    bl = backlight_device_register(pdev->name, &pdev->dev, pb,
+                                   &owl_pwm_bl_ops, &props);
+    if (IS_ERR(bl)) {
+        dev_err(&pdev->dev, "failed to register backlight\n");
+        ret = PTR_ERR(bl);
+        goto err_bl;
+    }
+
+    BL_PRINT("%s: set default brightess\n", __func__);
+
+    bl->props.brightness = data->dft_brightness - pb->threshold_step;
+
+    if (boot_pwm_inited) {
+        gpio_direction_output(pb->en_gpio.gpio, !pb->en_gpio.active_low);
+
+        bl->props.power = FB_BLANK_UNBLANK;
+        pb->dev_enable  = 1;
+    } else {
+        gpio_direction_output(pb->en_gpio.gpio, pb->en_gpio.active_low);
+
+        bl->props.power = FB_BLANK_POWERDOWN;
+        pb->dev_enable = 0;
+    }
+
+    owl_pwm_bl_device = bl;
+    platform_set_drvdata(pdev, bl);
+
+    owl_pwm_bl_init_attr(&bl->dev);
+
+    return 0;
+
+err_bl:
+    gpio_free(pb->en_gpio.gpio);
+    pwm_free(pb->pwm);
+err_pwm:
+    kfree(pb);
+err_alloc:
+    if (data->exit) {
+        data->exit(&pdev->dev);
+    }
+    return ret;
+}
+
+static int owl_pwm_bl_remove(struct platform_device *pdev) {
+    struct owl_pwm_bl_platform_data *data = pdev->dev.platform_data;
+    struct backlight_device             *bl = platform_get_drvdata(pdev);
+    struct owl_pwm_bl                *pb = dev_get_drvdata(&bl->dev);
+
+    owl_pwm_bl_device = NULL;
+
+    backlight_device_unregister(bl);
+    gpio_free(pb->en_gpio.gpio);
+    pwm_config(pb->pwm, 0, pb->period);
+    pwm_disable(pb->pwm);
+    pwm_free(pb->pwm);
+    kfree(pb);
+
+    if (data->exit) {
+        data->exit(&pdev->dev);
+    }
+    return 0;
+}
+
+#ifdef CONFIG_PM
+static int owl_pwm_bl_suspend(struct platform_device *pdev,
+                                 pm_message_t state) {
+#if 0
+    struct backlight_device *bl = platform_get_drvdata(pdev);
+    struct owl_pwm_bl *pb = dev_get_drvdata(&bl->dev);
+
+    bl->props.power = FB_BLANK_POWERDOWN;
+    backlight_update_status(bl);
+#endif
+    return 0;
+}
+
+static int owl_pwm_bl_resume(struct platform_device *pdev) {
+#if 0
+    struct backlight_device *bl = platform_get_drvdata(pdev);
+
+    bl->props.power = FB_BLANK_UNBLANK;
+    backlight_update_status(bl);
+#endif
+    return 0;
+}
+#else
+#define owl_pwm_bl_suspend    NULL
+#define owl_pwm_bl_resume    NULL
+#endif
+
+static struct of_device_id owl_pwm_bl_of_match[] = {
+    { .compatible = "actions,owl-pwm-backlight" },
+    { }
+};
+
+static struct platform_driver owl_pwm_bl_driver = {
+    .driver = {
+        .name   = "owl_pwm_backlight",
+        .owner  = THIS_MODULE,
+        .of_match_table = of_match_ptr(owl_pwm_bl_of_match),
+    },
+    .probe      = owl_pwm_bl_probe,
+    .remove     = owl_pwm_bl_remove,
+    .suspend    = owl_pwm_bl_suspend,
+    .resume     = owl_pwm_bl_resume,
+};
+
+static int __init owl_pwm_bl_init(void) {
+    return platform_driver_register(&owl_pwm_bl_driver);
+}
+
+#ifdef MODULE
+module_init(owl_pwm_bl_init);
+
+static void __exit owl_pwm_bl_exit(void) {
+    platform_driver_unregister(&owl_pwm_bl_driver);
+}
+module_exit(owl_pwm_bl_exit);
+
+MODULE_DESCRIPTION("OWL PWM based Backlight Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform: owl_pwm_backlight");
+#else
+subsys_initcall(owl_pwm_bl_init);
+#endif
+
+
+/*
+ * return backlight's on/off status,
+ * 0 is off, > 0 is on
+ */
+int owl_backlight_is_on(void) {
+    int stat, bright, power;
+    struct backlight_device *bl = owl_pwm_bl_device;
+
+    if (NULL == bl) {
+        BL_PRINT("%s/%s: get backlight failed!\n", __FILE__, __func__);
+        return 1;
+    }
+
+    power   = bl->props.power;
+    bright  = bl->props.brightness;
+
+    stat    = bright && (!power);
+
+    BL_PRINT("%s: state = %d\n", __func__, stat);
+
+    return stat;
+}
+EXPORT_SYMBOL(owl_backlight_is_on);
+
+/*
+ * set backlight on/off, 0 is off, 1 is on.
+ *
+ * NOTE: this interface SHOULD ONLY change the on/off
+ *       status, CAN NOT change the brightness value.
+ */
+static void owl_turnon_backlight_function(struct work_struct *work)
+{
+    struct backlight_device *bl = owl_pwm_bl_device;
+	struct owl_pwm_bl *pb = dev_get_drvdata(&bl->dev);
+    bl->props.power = FB_BLANK_UNBLANK;	
+	if(pb->need_update_bl){
+		BL_PRINT("owl_turnon_backlight_function\n");
+		backlight_update_status(owl_pwm_bl_device);	
+		pb->need_update_bl = 0;
+	}
+    BL_PRINT("backlight turn on \n"); 
+}
+
+static DECLARE_DELAYED_WORK(owl_turnon_backlight_work, owl_turnon_backlight_function);
+
+void owl_backlight_set_onoff(int onoff) {
+    struct backlight_device *bl = owl_pwm_bl_device;
+	struct owl_pwm_bl *pb = NULL;
+    if (NULL == bl) {
+        printk("ERROR! backlight is no exist!\n");
+    }
+    pb = dev_get_drvdata(&bl->dev)
+
+    BL_PRINT("%s: onoff = %d\n", __func__, onoff); 
+
+    /* 
+     * do not update status for backlight on.
+     */
+    if (onoff == 0)
+    {
+    	bl->props.power =  FB_BLANK_POWERDOWN;
+    	backlight_update_status(owl_pwm_bl_device);
+    }
+    else    	
+    {
+    	schedule_delayed_work(&owl_turnon_backlight_work, msecs_to_jiffies(pb->delay_before_pwm));
+    }
+
+    return;
+}
+EXPORT_SYMBOL(owl_backlight_set_onoff);
diff --git a/drivers/video/fbdev/owl/displays/Kconfig b/drivers/video/fbdev/owl/displays/Kconfig
new file mode 100755
index 0000000..2748e1d
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/Kconfig
@@ -0,0 +1,5 @@
+source "drivers/video/fbdev/owl/displays/lcdc/Kconfig"
+source "drivers/video/fbdev/owl/displays/dsi/Kconfig"
+source "drivers/video/fbdev/owl/displays/hdmi/Kconfig"
+source "drivers/video/fbdev/owl/displays/cvbs/Kconfig"
+#source "drivers/video/fbdev/owl/displays/edp/Kconfig"
diff --git a/drivers/video/fbdev/owl/displays/Makefile b/drivers/video/fbdev/owl/displays/Makefile
new file mode 100755
index 0000000..5093ca5
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/Makefile
@@ -0,0 +1 @@
+obj-y += lcdc/ dsi/ hdmi/ cvbs/#edp/
diff --git a/drivers/video/fbdev/owl/displays/cvbs/Kconfig b/drivers/video/fbdev/owl/displays/cvbs/Kconfig
new file mode 100755
index 0000000..2adbe30
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_OWL_CVBS
+	tristate "OWL cvbs support"
+	depends on ARCH_OWL
+	---help---
+	  Say Y here if you need cvbs controller in your system.
+
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
diff --git a/drivers/video/fbdev/owl/displays/cvbs/Makefile b/drivers/video/fbdev/owl/displays/cvbs/Makefile
new file mode 100755
index 0000000..6555a4a
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_OWL_CVBS) += owl_cvbs.o
+
+owl_cvbs-y :=panel-cvbs.o cvbs.o cvbs_sysfs.o
+
diff --git a/drivers/video/fbdev/owl/displays/cvbs/cvbs.c b/drivers/video/fbdev/owl/displays/cvbs/cvbs.c
new file mode 100755
index 0000000..fa6a7a3
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/cvbs.c
@@ -0,0 +1,847 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/lcdc.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Xieshsh <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "CVBS"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <mach/switch.h>
+#include <mach/irqs.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/earlysuspend.h>
+#include <video/owldisplay.h>
+#include <asm/atomic.h>
+#include <linux/sched.h>    
+#include <linux/kthread.h> 
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+#include <mach/clkname.h>
+#include <mach/module-owl.h>
+
+#include <video/owldss.h>
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+#include "../../dss/de.h"
+#include "cvbs_ip.h"
+#include "cvbs_reg.h"
+#include "cvbs.h"
+ 
+
+
+int preline = 8;
+
+
+struct switch_dev cdev = {
+	.name = "cvbs",
+};
+
+void  *CMU_TVOUTPLL = 0;
+
+struct cvbs_info cvbs;
+
+
+#define CVBS_IN  	1
+#define CVBS_OUT	2
+
+static bool first_status = false;
+static bool first_hpt = true;
+static int  cvbs_state = 0;
+static DEFINE_MUTEX(cvbs_setting_mutex);
+
+static struct work_struct cvbs_in_work;
+static struct work_struct cvbs_out_work;
+//static struct work_struct cvbs_check_work;
+
+static struct delayed_work cvbs_check_work;
+
+#define    OWL_TV_MOD_PAL                  8
+#define    OWL_TV_MOD_NTSC                 9
+
+#define NUM_CVBS                     1
+
+struct data_fmt_param {
+    const char *name;
+    s32 data_fmt;
+};
+
+static struct data_fmt_param date_fmts[] = {
+	{"PAL", OWL_TV_MOD_PAL},
+	{"NTSC", OWL_TV_MOD_NTSC},	
+};
+
+static const struct owl_video_timings cvbs_display_modes[]=
+{
+	
+	{ 720, 576, 13500, 64, 16, 39, 5, 64, 5,
+	OWLDSS_SIG_ACTIVE_LOW, OWLDSS_SIG_ACTIVE_LOW,
+	true, 1, 0, },
+				
+	{ 720, 480, 27000, 60, 16, 30, 9, 62, 6,
+	OWLDSS_SIG_ACTIVE_LOW, OWLDSS_SIG_ACTIVE_LOW,
+	true, 1, 0, },	
+};
+
+void io_cmap(void)
+{
+	CMU_TVOUTPLL = ioremap(0xb0160018, 4);	
+}
+
+inline void cvbs_write_reg(const u32 index, u32 val)
+{
+	writel(val, cvbs.base+index);
+}
+
+inline u32 cvbs_read_reg(const u32 index)
+{
+	return readl(cvbs.base + index);
+}
+void dump_reg(void)
+{
+	#define DUMPREG(name,r) printk("%s %08x\n",name,cvbs_read_reg(r))
+	
+     DUMPREG("TVOUT_EN  	value is ", TVOUT_EN);
+     DUMPREG("TVOUT_OCR  	value is ", TVOUT_OCR);
+     DUMPREG("TVOUT_STA  	value is ", TVOUT_STA);
+     DUMPREG("TVOUT_CCR    value is ", TVOUT_CCR);
+     DUMPREG("TVOUT_BCR  	value is ", TVOUT_BCR);
+     DUMPREG("TVOUT_CSCR  	value is ", TVOUT_CSCR);
+     DUMPREG("TVOUT_PRL  	value is ", TVOUT_PRL);
+     
+     DUMPREG("TVOUT_VFALD  	value is ", TVOUT_VFALD);
+     DUMPREG("CVBS_MSR  	value is ", CVBS_MSR);    
+     DUMPREG("CVBS_AL_SEPO  	value is ", CVBS_AL_SEPO);
+     DUMPREG("CVBS_AL_SEPE  	value is ", CVBS_AL_SEPE);
+     DUMPREG("CVBS_AD_SEP  value is ", CVBS_AD_SEP);
+     DUMPREG("CVBS_HUECR  value is ", CVBS_HUECR);     
+     DUMPREG("CVBS_SCPCR  value is ", CVBS_SCPCR);
+     DUMPREG("CVBS_SCFCR  value is ", CVBS_SCFCR);
+     DUMPREG("CVBS_CBACR  value is ", CVBS_CBACR);     
+     DUMPREG("CVBS_SACR  value is ", CVBS_SACR);
+     DUMPREG("TVOUT_DCR  value is ", TVOUT_DCR);
+     DUMPREG("TVOUT_DDCR  value is ", TVOUT_DDCR);
+     DUMPREG("TVOUT_DCORCTL  value is ", TVOUT_DCORCTL);
+     DUMPREG("TVOUT_DRCR  value is ", TVOUT_DRCR);
+	
+}
+
+/*****************tvout_reset***********************************/
+static void tvout_reset(void)
+{
+	
+	DEBUG_CVBS("[%s start]\n", __func__);
+	module_reset(MOD_ID_TVOUT);
+	DEBUG_CVBS("[%s start] TVOUT_DDCR=0x%x\n", __func__,TVOUT_DDCR);
+	cvbs_write_reg(TVOUT_DDCR,0x110050);
+	
+	/* disable before registering irq handler */
+	cvbs_write_reg(TVOUT_OCR,0x0);
+	/* clear pendings before registering irq handler */
+	cvbs_write_reg( TVOUT_STA,cvbs_read_reg(TVOUT_STA));
+
+}
+
+
+
+static void cvbs_irq_enable(int flag,bool enable)
+{
+	u32 val;
+	if (flag==CVBS_IN)
+	{
+		val = cvbs_read_reg( TVOUT_OCR);
+		val = REG_SET_VAL(val,enable, 12, 12);
+		cvbs_write_reg(TVOUT_OCR,val);	
+	}
+	else if(flag==CVBS_OUT)
+	{
+		val = cvbs_read_reg(TVOUT_OCR);
+		val = REG_SET_VAL(val,enable, 11, 11);
+		cvbs_write_reg( TVOUT_OCR,val);
+	}
+
+}
+
+static bool cvbs_pending(int flag)
+{
+	u32 val;
+	if (flag==CVBS_IN)
+	{
+		val = cvbs_read_reg( TVOUT_STA);
+		return (REG_GET_VAL(val,3,3) == 1);
+	}
+	if(flag==CVBS_OUT)
+	{
+		val = cvbs_read_reg(TVOUT_STA);
+		return (REG_GET_VAL(val,7,7) == 1);
+	}
+
+	return false;
+}
+
+static void cvbs_clear_pending(int flag)
+{
+	u32 val;
+	if (flag==CVBS_IN)
+	{
+		val = cvbs_read_reg( TVOUT_STA);		
+		val = REG_SET_VAL(val,1, 3, 3);
+		cvbs_write_reg(val, TVOUT_STA);
+
+			
+	}
+	else if(flag==CVBS_OUT)
+	{
+		val = cvbs_read_reg(TVOUT_STA); 
+		val = REG_SET_VAL(val,1, 7, 7);
+		cvbs_write_reg( TVOUT_STA,val);			
+	}
+}
+
+static void auto_detect_bit(int flag)
+{
+	u32 val = 0;	
+	if(flag==CVBS_IN)
+	{
+		val = cvbs_read_reg( TVOUT_OCR);	
+		val = REG_SET_VAL(val,1, 8, 8);
+		cvbs_write_reg( TVOUT_OCR,val);
+	}
+	else if(flag==CVBS_OUT)
+	{
+		val = cvbs_read_reg( TVOUT_OCR);	
+		val = REG_SET_VAL(val,1, 9, 9);
+		cvbs_write_reg( TVOUT_OCR,val);
+	}
+}
+
+void enable_cvbs_output(void)
+{
+	cvbs_write_reg(TVOUT_EN,cvbs_read_reg(TVOUT_EN) | TVOUT_EN_CVBS_EN);
+	cvbs_write_reg(TVOUT_OCR,(cvbs_read_reg(TVOUT_OCR) | TVOUT_OCR_DAC3 | TVOUT_OCR_INREN) &
+		~TVOUT_OCR_DACOUT);
+	auto_detect_bit(CVBS_IN);
+	cvbs_irq_enable(CVBS_IN,true);
+}
+
+  void disable_cvbs_output(void)
+{
+	cvbs_write_reg(TVOUT_EN,cvbs_read_reg(TVOUT_EN) &  ~TVOUT_EN_CVBS_EN);
+	cvbs_write_reg(TVOUT_OCR,cvbs_read_reg(TVOUT_OCR) & ~(TVOUT_OCR_DAC3 | TVOUT_OCR_INREN));
+
+}
+
+
+
+static irqreturn_t cvbs_irq_handler(int irq, void *dev_id)
+{
+	DEBUG_CVBS("[%s start]\n", __func__);
+	
+	
+			//\B2\E5\C8\EB	
+		if (cvbs_pending(CVBS_IN))
+		{
+		cvbs_state = CVBS_IN;
+		DEBUG_CVBS("CVBS is in \n");
+		cvbs_irq_enable(CVBS_IN,false);
+		cvbs_irq_enable(CVBS_OUT,true);
+						
+		cvbs_clear_pending(CVBS_IN);  
+		schedule_work(&cvbs_in_work);					
+		auto_detect_bit(CVBS_OUT);				
+	}
+ if (cvbs_pending(CVBS_OUT))
+	{
+		cvbs_state = CVBS_OUT;
+		DEBUG_CVBS("CVBS is out \n"); 
+		cvbs_irq_enable(CVBS_OUT,false);
+		cvbs_irq_enable(CVBS_IN,true);						 
+		cvbs_clear_pending(CVBS_OUT);
+		schedule_work(&cvbs_out_work);	
+		auto_detect_bit(CVBS_IN);					
+	}
+	
+	DEBUG_CVBS("[%s end]\n", __func__);	
+	return IRQ_HANDLED;
+}
+
+static set_cvbs_status(struct switch_dev *cdev, int state)
+{
+	switch_set_state(cdev, state);
+	if(cvbs.dssdev != NULL 
+		&& cvbs.dssdev->driver != NULL 
+		&& cvbs.dssdev->driver->hot_plug_nodify){
+		cvbs.dssdev->driver->hot_plug_nodify(cvbs.dssdev,state);	
+	}	
+}
+static void do_cvbs_in(struct work_struct *work) 
+{
+	DEBUG_CVBS("[%s start]\n", __func__);
+	if(cvbs.hot_plugin_enable)
+	{
+		set_cvbs_status(&cdev, 1);	
+	}		
+}
+
+static void do_cvbs_out(struct work_struct *work) 
+{
+		DEBUG_CVBS("[%s start]\n", __func__);	
+		if(cvbs.hot_plugin_enable)
+		{
+			set_cvbs_status(&cdev, 0);	
+		}
+
+}
+
+static void cvbs_check_status (struct work_struct *work) 
+{
+	if (first_status)
+	{
+		set_cvbs_status(&cdev, 0);	
+		first_status=false;
+	}
+	if (first_hpt)
+	{
+		first_hpt=false;
+		auto_detect_bit(CVBS_IN);
+		cvbs_irq_enable(CVBS_IN,true);
+	}
+
+
+}
+
+
+
+unsigned long  owl_tvoutpll1_set_rate(void)
+{
+	struct clk *cvbs_clk = NULL;
+	unsigned int cvbs_rate;
+	int ret;
+
+	cvbs_clk = clk_get(NULL, CLKNAME_CVBSPLL);
+	clk_prepare(cvbs_clk);
+	clk_enable(cvbs_clk);
+	cvbs_rate = 432000000;
+	ret = clk_set_rate(cvbs_clk, cvbs_rate);
+	if (ret < 0) {
+		DEBUG_CVBS(KERN_ERR "cvbs clk set error!\n");
+		return ret;
+	}
+	return ret;
+}
+  
+  
+
+
+void configure_pal(void)//pal(576i),pll1:432M,pll0:594M
+{
+
+
+	owl_tvoutpll1_set_rate();
+	cvbs_write_reg(CVBS_MSR,CVBS_MSR_CVBS_PAL_D | CVBS_MSR_CVCKS);   //\C9\E8\D6\C3PAL_D\BA\CDclk
+
+	cvbs_write_reg(CVBS_AL_SEPO,(cvbs_read_reg(CVBS_AL_SEPO) & (~CVBS_AL_SEPO_ALEP_MASK)) |
+			   CVBS_AL_SEPO_ALEP(0x136));
+	cvbs_write_reg(CVBS_AL_SEPO,(cvbs_read_reg(CVBS_AL_SEPO) & (~CVBS_AL_SEPO_ALSP_MASK)) |
+			   CVBS_AL_SEPO_ALSP(0x17));		   
+
+	cvbs_write_reg(CVBS_AL_SEPE,(cvbs_read_reg(CVBS_AL_SEPE) & (~CVBS_AL_SEPE_ALEPEF_MASK)) |
+			   CVBS_AL_SEPE_ALEPEF(0x26f));
+	cvbs_write_reg(CVBS_AL_SEPE,(cvbs_read_reg(CVBS_AL_SEPE) & (~CVBS_AL_SEPE_ALSPEF_MASK)) |
+			   CVBS_AL_SEPE_ALSPEF(0x150));
+
+	cvbs_write_reg(CVBS_AD_SEP,(cvbs_read_reg(CVBS_AD_SEP) & (~CVBS_AD_SEP_ADEP_MASK)) |
+			   CVBS_AD_SEP_ADEP(0x2cf));
+	cvbs_write_reg(CVBS_AD_SEP,(cvbs_read_reg(CVBS_AD_SEP) & (~CVBS_AD_SEP_ADSP_MASK)) |
+			   CVBS_AD_SEP_ADSP(0x0));
+
+}
+
+
+
+void configure_ntsc(void)//ntsc(480i),pll1:432M,pll0:594/1.001
+{
+
+
+	owl_tvoutpll1_set_rate();
+
+	
+	cvbs_write_reg(CVBS_MSR,CVBS_MSR_CVBS_NTSC_M | CVBS_MSR_CVCKS);
+	
+	cvbs_write_reg(CVBS_AL_SEPO,(cvbs_read_reg(CVBS_AL_SEPO) & (~CVBS_AL_SEPO_ALEP_MASK)) |
+			    CVBS_AL_SEPO_ALEP(0xfe)); //0xfe  0x106
+	cvbs_write_reg(CVBS_AL_SEPO,(cvbs_read_reg(CVBS_AL_SEPO) & (~CVBS_AL_SEPO_ALSP_MASK)) |
+			   CVBS_AL_SEPO_ALSP(0x15));	
+
+	cvbs_write_reg(CVBS_AL_SEPE,(cvbs_read_reg(CVBS_AL_SEPE) & (~CVBS_AL_SEPE_ALEPEF_MASK)) |
+			   CVBS_AL_SEPE_ALEPEF(0x20b)); //0x20b 0x20d
+	cvbs_write_reg(CVBS_AL_SEPE,(cvbs_read_reg(CVBS_AL_SEPE) & (~CVBS_AL_SEPE_ALSPEF_MASK)) |
+			   CVBS_AL_SEPE_ALSPEF(0x11c));
+
+	cvbs_write_reg(CVBS_AD_SEP,(cvbs_read_reg(CVBS_AD_SEP) & (~CVBS_AD_SEP_ADEP_MASK)) |
+			   CVBS_AD_SEP_ADEP(0x2cf));
+	cvbs_write_reg(CVBS_AD_SEP,(cvbs_read_reg(CVBS_AD_SEP) & (~CVBS_AD_SEP_ADSP_MASK)) |
+			   CVBS_AD_SEP_ADSP(0x0));
+}
+
+
+int configure_cvbs(int vid)
+{
+
+	switch (vid) {
+	case OWL_TV_MOD_PAL:
+		configure_pal();
+		break;
+		
+	case OWL_TV_MOD_NTSC:
+		configure_ntsc();
+		break;
+		
+	default:
+		return -EINVAL;
+	}
+	cvbs.current_vid=vid;
+	return 0;
+}
+
+void cvbs_show_colorbar(void)
+{
+	DEBUG_CVBS("[%s start]\n", __func__);
+
+	configure_cvbs(OWL_TV_MOD_PAL);
+	
+	/*enable color bar ,cvbs HDAC*/
+	cvbs_write_reg(TVOUT_OCR,cvbs_read_reg(TVOUT_OCR) | TVOUT_OCR_DACOUT | TVOUT_OCR_DAC3 
+		| TVOUT_OCR_INACEN | TVOUT_OCR_INREN);
+	writel(readl(CMU_TVOUTPLL) | CMU_TVOUTPLL_PLL1EN |
+		CMU_TVOUTPLL_TK0SS | CMU_TVOUTPLL_CVBS_PLL1FSS(0x4),CMU_TVOUTPLL);
+
+	/*eable cvbs output*/
+	cvbs_write_reg(TVOUT_EN,cvbs_read_reg(TVOUT_EN) | TVOUT_EN_CVBS_EN);
+
+  DEBUG_CVBS("[%s finished]\n", __func__);
+}
+
+int cvbs_set_preline(int num_preline)
+{
+	//struct cvbs_info *c_inf = cvbs_get_data(pdev); 
+	int temp;
+	int hpn;
+	preline = num_preline;
+	hpn = (num_preline - 1) << 8;
+	cvbs_write_reg(TVOUT_PRL,0xf<<8);
+	temp = cvbs_read_reg(TVOUT_PRL);
+	cvbs_write_reg( TVOUT_PRL,hpn|temp);
+	return 1;
+}
+
+
+
+/**
+ * @tv_mode: see enum TV_MODE_TYPE
+ * This function sets register for CVBS(PAL/NTSC)
+ */
+
+
+
+void cvbs_display_set_vid(struct owl_dss_device *dssdev, int vid)
+{
+	struct owl_video_timings *timings;
+	int id;
+	DEBUG_CVBS("[%s start]\n", __func__);
+	timings = &dssdev->timings;	
+	cvbs.current_vid=vid;
+	
+	mutex_lock(&cvbs.lock);
+	if (vid==OWL_TV_MOD_PAL)
+	{
+		id=0;
+	}
+	else if(vid==OWL_TV_MOD_NTSC)
+	{
+		id=1;
+	}
+	
+	 	timings->x_res 			= 	cvbs_display_modes[id].x_res;
+		timings->y_res 		 	= 	cvbs_display_modes[id].y_res;
+		timings->pixel_clock 	= 	cvbs_display_modes[id].pixel_clock;
+		timings->hsw 		 	= 	cvbs_display_modes[id].hsw;
+		timings->hfp 			= 	cvbs_display_modes[id].hfp;
+		timings->hbp 		 	= 	cvbs_display_modes[id].hbp;
+		timings->vsw 			= 	cvbs_display_modes[id].vsw;
+		timings->vfp 			= 	cvbs_display_modes[id].vfp;
+		timings->vbp 			= 	cvbs_display_modes[id].vbp;	
+	
+	DEBUG_CVBS("[%s finished]\n", __func__);
+	mutex_unlock(&cvbs.lock);
+	
+}
+
+void cvbs_display_get_vid(struct owl_dss_device *dssdev, int *vid)
+{
+  	int i;
+   mutex_lock(&cvbs.lock);
+   
+   	i=cvbs.current_vid;
+   	
+   	*vid = i;   	
+   	
+   	mutex_unlock(&cvbs.lock);
+}
+
+void cvbs_display_set_overscan(struct owl_dss_device *dssdev,u16 over_scan_width,u16 over_scan_height)
+{	
+	mutex_lock(&cvbs.lock);
+	cvbs.overscan_width = over_scan_width;
+	cvbs.overscan_height = over_scan_height;
+	mutex_unlock(&cvbs.lock);
+	
+}
+void cvbs_display_get_overscan(struct owl_dss_device *dssdev, u16 * over_scan_width,u16 * over_scan_height)
+{
+	mutex_lock(&cvbs.lock);
+	*over_scan_width = cvbs.overscan_width;
+	*over_scan_height = cvbs.overscan_height;
+	mutex_unlock(&cvbs.lock);
+}
+static void cvbs_boot_inited(void)
+{
+   // int enable = cvbs_read_reg(TVOUT_EN);
+    int msr    = cvbs_read_reg(CVBS_MSR);
+       
+    if(msr == 0x14)
+    	{ //PAL
+    			cvbs.current_vid=OWL_TV_MOD_PAL;           
+       } else if (msr == 0x10)
+       { //NTSC
+        	cvbs.current_vid=OWL_TV_MOD_NTSC;        
+       }      
+}
+
+void owldss_cvbs_display_enable_hpd(struct owl_dss_device *dssdev, bool enable)
+{
+	if (enable)
+	{
+		if (cvbs_state==CVBS_IN)
+		{
+		set_cvbs_status(&cdev, 1);	
+		}
+	}else
+	{	
+		set_cvbs_status(&cdev, 0);	
+		
+	}
+}
+
+
+int owldss_cvbs_display_enable(struct owl_dss_device *dssdev)
+{
+
+	struct owl_overlay_manager *mgr = dssdev->manager;
+
+	struct owl_video_timings *timings;
+
+	int r = 0;
+	
+	timings = &dssdev->timings;	
+
+	DEBUG_CVBS("ENTER cvbs_display_enable\n");
+
+	mutex_lock(&cvbs.lock);
+
+    	if (mgr == NULL) {
+		DEBUG_CVBS("failed to enable display: no manager\n");
+		r = -ENODEV;
+
+	}
+
+	r = owl_dss_start_device(dssdev);
+	
+	if (r) {
+		DEBUG_CVBS("failed to start device\n");
+		goto err0;
+	}
+		
+	
+	if( cvbs_state==CVBS_IN)
+	{
+		configure_cvbs(cvbs.current_vid);
+		enable_cvbs_output();
+		DEBUG_CVBS("cvbs_boot_inited vid 1 =%d\n",cvbs.current_vid);
+		
+		r = dss_mgr_enable(mgr);
+	
+	if (r)
+		{
+		DEBUG_CVBS("failed to dss_mgr_enable device\n");
+		}
+	}
+	mutex_unlock(&cvbs.lock);
+		
+	return 0;
+	
+err0:	
+	return r;
+}
+
+
+void owldss_cvbs_display_disable(struct owl_dss_device *dssdev)
+{
+	
+	struct owl_overlay_manager *mgr = dssdev->manager;
+
+	DEBUG_CVBS("ENTER owldss_cvbs_display_disable\n");
+	mutex_lock(&cvbs.lock);
+	disable_cvbs_output();
+		
+	dss_mgr_disable(mgr);
+
+	owl_dss_stop_device(dssdev);
+	mdelay(200);
+	mutex_unlock(&cvbs.lock);	
+}
+
+int owldss_cvbs_resume(struct owl_dss_device *dssdev)
+{
+	if(cvbs.is_init){
+		DEBUG_CVBS("owldss_cvbs_resume33 \n");
+		tvout_reset();
+		cvbs_clear_pending(CVBS_IN);
+		cvbs_clear_pending(CVBS_OUT);
+		auto_detect_bit(CVBS_IN);
+		auto_detect_bit(CVBS_OUT);
+		cvbs_irq_enable(CVBS_IN,true);	
+		cvbs_irq_enable(CVBS_OUT,true);	
+		queue_delayed_work(cvbs.wq, &cvbs_check_work,
+				msecs_to_jiffies(2000));
+		
+	}
+	return 0;
+}
+
+int owldss_cvbs_suspend(struct owl_dss_device *dssdev)
+{
+	DEBUG_CVBS("owldss_cvbs_suspend \n");
+	if(cvbs.is_init){
+		cvbs_irq_enable(CVBS_IN,false);
+		cvbs_irq_enable(CVBS_OUT,false);
+		cancel_work_sync(&cvbs_in_work);
+		cancel_work_sync(&cvbs_out_work);
+		cancel_delayed_work_sync(&cvbs_check_work);
+	}
+	return 0;
+}
+
+
+static struct of_device_id owl_cvbs_of_match[] = {
+    { .compatible = "actions,atm7059a-cvbs",},
+      { },
+};
+
+MODULE_DEVICE_TABLE(of, owl_cvbs_of_match);
+
+
+static u32 string_to_data_fmt(const char *name)
+{
+	int i;
+	DEBUG_CVBS("ARRAY_SIZE=%d\n",ARRAY_SIZE(date_fmts));
+	for (i = 0; i < ARRAY_SIZE(date_fmts); i++) {
+		if (!strcmp(date_fmts[i].name, name))
+			return date_fmts[i].data_fmt;
+	}
+
+	return -1;
+}
+
+static int get_cvbs_data(struct platform_device *pdev)
+{
+	struct device_node *of_node;
+	
+	char const *default_mode;
+	char const * over_scan;
+	int index = 1;
+
+	DEBUG_CVBS("%s\n", __func__);
+
+	of_node = pdev->dev.of_node;
+	
+	if (of_property_read_string(of_node, "default_mode", &default_mode)) {
+		default_mode = NULL;
+			DEBUG_CVBS("get default_mode node error\n");
+	}
+	
+	if (of_property_read_u32_array(of_node, "hotplugable", &cvbs.hot_plugin_enable , 1)) {
+		cvbs.hot_plugin_enable = 1;
+		DEBUG_CVBS("get hot_plugin_enable node error\n");
+	}
+	if (!of_property_read_string(of_node, "over_scan", &over_scan)) {		
+		if(over_scan != NULL)
+		{
+			printk("over_scan \n %s",over_scan);
+			sscanf(over_scan,"%d,%d",(int *)(&cvbs.overscan_width),(int *)(&cvbs.overscan_height));
+			printk("cvbs ->overscan_width %d  ,hdmi_data->overscan_height %d \n",cvbs.overscan_width,cvbs.overscan_height);
+		}
+		
+	}
+	
+	 DEBUG_CVBS("get hot_plugin_enable node hotplugable =%d\n",cvbs.hot_plugin_enable);
+
+	index = string_to_data_fmt(default_mode);
+	if(index <= 0 )
+	{
+		index = 1;
+	}
+	cvbs.current_vid = index;
+	
+	return 0;
+}
+
+static int owl_cvbs_probe(struct platform_device *pdev)
+{
+	int r,enable;
+	struct resource * cvbs_mem;
+	
+	cvbs.pdev = pdev;
+	io_cmap();	
+	cvbs_mem = platform_get_resource(cvbs.pdev, IORESOURCE_MEM, 0);
+
+	if (!cvbs_mem) {
+		DEBUG_CVBS("cvbs_mem platform_get_resource ERROR\n");
+		r = -EINVAL;
+		goto err1;
+	}
+	
+	cvbs.base =  ioremap(cvbs_mem->start, resource_size(cvbs_mem));
+
+	if (!cvbs.base){	
+		DEBUG_CVBS("cvbs.cfo.base error\n");
+		r=  -ENOMEM;
+		goto err_ioremap;
+	}	
+	DEBUG_CVBS("cvbs_mem->start  ~~~ %x  resource_size %x\n",cvbs_mem ->start, resource_size(cvbs_mem ));	
+	DEBUG_CVBS("cvbs->base  ~~~ %p \n",cvbs.base);
+
+	mutex_init(&cvbs.lock);
+	
+  	owl_cvbs_create_sysfs(&pdev->dev);
+
+	
+	DEBUG_CVBS("rest probe cvbs  ~~\n");
+	
+	
+	cvbs_irq_enable(CVBS_IN,false);
+
+	r = request_irq(OWL_IRQ_TVOUT, cvbs_irq_handler, 0, "cvbsdev", NULL);	
+	if (r) {
+		DEBUG_CVBS(" register irq failed!\n");
+		return r;
+	} else {
+		DEBUG_CVBS(" register irq ON!\n");
+	}		
+	
+	if(get_cvbs_data(pdev)){
+		DEBUG_CVBS("get_cvbs_data error\n");
+		return -1;
+	}
+	
+	cvbs_boot_inited();
+	
+	DEBUG_CVBS("get vid is %d\n",cvbs.current_vid);
+	
+	enable = cvbs_read_reg(TVOUT_EN);
+	
+	if(!enable)
+	{
+		first_status = true;
+	}
+	cvbs.wq = create_workqueue("atm705a-cvbs");
+	
+	
+	INIT_WORK(&cvbs_in_work, do_cvbs_in);
+	INIT_WORK(&cvbs_out_work, do_cvbs_out);
+	
+	INIT_DELAYED_WORK(&cvbs_check_work, cvbs_check_status);
+	
+	queue_delayed_work(cvbs.wq, &cvbs_check_work,
+				msecs_to_jiffies(3000));
+	
+
+	
+	r = switch_dev_register(&cdev);
+	if (r)
+		goto err1;
+	
+	DEBUG_CVBS(" owl_cvbs_probe is OK!\n");
+	cvbs.is_init = true;
+	return 0;
+err_ioremap:
+err1:
+	return r;	
+	
+}
+
+static int  owl_cvbs_remove(struct platform_device *pdev)
+{ 
+	DEBUG_CVBS("%s start!\n", __func__);
+	disable_cvbs_output();
+	DEBUG_CVBS("%s finished\n", __func__);
+
+	return 0;
+}
+
+static struct platform_driver owl_cvbs_driver = {
+    .driver = {
+        .name           = "owl_cvbs",
+        .owner          = THIS_MODULE,
+        .of_match_table = owl_cvbs_of_match,
+    },
+    .probe              = owl_cvbs_probe,
+    .remove             = owl_cvbs_remove,
+};
+
+int owl_cvbs_init_platform(void)
+{
+    int ret = 0;
+    ret = platform_driver_register(&owl_cvbs_driver);
+    
+    if (ret) {
+        DSSERR("Failed to initialize dsi platform driver ret=%d\n",ret);
+        return ret;
+    }
+    if(!cvbs.is_init){
+    	return -1;
+    }
+    return 0;
+}
+
+
diff --git a/drivers/video/fbdev/owl/displays/cvbs/cvbs.h b/drivers/video/fbdev/owl/displays/cvbs/cvbs.h
new file mode 100755
index 0000000..1a6f0ca
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/cvbs.h
@@ -0,0 +1,125 @@
+/*
+ * hdmi.h
+ *
+ * HDMI header definition for OWL IP.
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _OWL_CVBS_H
+#define _OWL_CVBS_H
+#include <video/owldss.h>
+
+#define CVBS_PRINT
+	#ifdef CVBS_PRINT
+	#define DEBUG_CVBS(format, ...) \
+		do { \
+			printk(KERN_DEBUG "OWL_CVBS: " format, ## __VA_ARGS__); \
+		} while (0)
+	#else
+	#define DEBUG_CVBS(format, ...)
+	#endif
+
+enum VIDEO_ID_TABLE {
+	VID640x480P_60_4VS3 = 1,
+	VID720x480P_60_4VS3,
+	VID720x480P_60_16VS9,
+	VID1280x720P_60_16VS9,
+	VID1920x1080I_60_16VS9,
+	VID720x480I_60_4VS3,
+	VID720x480I_60_16VS9,
+	VID1440x480P_60_4VS3 = 14,
+	VID1440x480P_60_16VS9,
+	VID1920x1080P_60_16VS9,
+	VID720x576P_50_4VS3,
+	VID720x576P_50_16VS9,
+	VID1280x720P_50_16VS9,
+	VID1920x1080I_50_16VS9,
+	VID720x576I_50_4VS3,
+	VID720x576I_50_16VS9,
+	VID1440x576P_50_4VS3 = 29,
+	VID1440x576P_50_16VS9,
+	VID1920x1080P_50_16VS9,
+	VID1920x1080P_24_16VS9,
+	VID1920x1080P_25_16VS9,
+	VID1920x1080P_30_16VS9,
+	VID720x480P_59P94_4VS3 = 72,
+	VID720x480P_59P94_16VS9,
+	VID1280X720P_59P94_16VS9,
+	VID1920x1080I_59P94_16VS9,
+	VID720x480I_59P54_4VS3,
+	VID720x480I_59P54_16VS9,
+	VID1920x1080P_59P94_16VS9 = 86,
+	VID1920x1080P_29P97_16VS9 = 104,
+	VID_MAX
+};
+
+struct cvbs_info {
+	struct platform_device  *pdev;
+	void __iomem	*base;
+	struct owl_dss_device   *dssdev;
+	struct mutex lock;
+	struct owl_videomode *cvbs_display_mode;
+	int current_vid;
+	int hot_plugin_enable;
+	
+	u16 overscan_width;
+	u16 overscan_height;
+	
+	struct workqueue_struct *wq;
+	bool is_init;
+};
+//struct cvbs_info cvbs;
+extern struct cvbs_info cvbs;
+
+enum TV_MODE_TYPE {
+	TV_MODE_PAL = 0,
+	TV_MODE_NTSC = 1,
+	TV_MODE_MAX = 2
+};
+
+enum TV_ENCODER_TYPE {
+	TV_ENCODER_INTERNAL,
+	TV_ENCODER_EXTERNAL,
+	TV_ENCODER_MAX
+};
+
+enum TVOUT_DEV_STATUS {
+	TVOUT_DEV_PLUGOUT,
+	TVOUT_DEV_PLUGIN,
+	TVOUT_DEV_MAX
+};
+enum CVBS_PLUGGING {
+	CVBS_PLUGOUT = 0,
+	CVBS_PLUGIN,
+	CVBS_PLUGGING_MAX
+};
+
+void enable_cvbs_output(void);
+void disable_cvbs_output(void);
+void dump_reg(void);
+void cvbs_display_get_vid(struct owl_dss_device *dssdev, int *vid);
+void cvbs_display_set_vid(struct owl_dss_device *dssdev, int vid);
+int owl_cvbs_create_sysfs(struct device *dev);
+int owldss_cvbs_suspend(struct owl_dss_device *dssdev);
+int owldss_cvbs_resume(struct owl_dss_device *dssdev);
+void cvbs_set_vid(struct owl_dss_device *dssdev,int vid);
+void cvbs_display_set_overscan(struct owl_dss_device *dssdev,u16 over_scan_width,u16 over_scan_height);
+void cvbs_display_get_overscan(struct owl_dss_device *dssdev, u16 * over_scan_width,u16 * over_scan_height);
+void owldss_cvbs_display_disable(struct owl_dss_device *dssdev);
+void owldss_cvbs_display_enable_hpd(struct owl_dss_device *dssdev, bool enable);
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/cvbs/cvbs_ip.h b/drivers/video/fbdev/owl/displays/cvbs/cvbs_ip.h
new file mode 100755
index 0000000..3861707
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/cvbs_ip.h
@@ -0,0 +1,54 @@
+/*
+ * cvbs_ip.h
+ *
+ * CVBS header definition for OWL IP.
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _CVBS_ACTS_OWL_H_
+#define _CVBS_ACTS_OWL_H_
+
+	#define     TVOUT_EN                                                          (0x0000)
+	#define     TVOUT_OCR                                                   	    (0x0004)
+	#define     TVOUT_STA                                                         (0x0008)
+	#define     TVOUT_CCR                                                         (0x000C)
+	#define     TVOUT_BCR                                                         (0x0010)
+	#define     TVOUT_CSCR                                                        (0x0014)
+	#define     TVOUT_PRL                                                         (0x0018)
+	#define     TVOUT_VFALD                                                 		  (0x001C)
+	#define     CVBS_MSR                                                          (0x0020)
+	#define     CVBS_AL_SEPO                                          				    (0x0024)
+	#define     CVBS_AL_SEPE                                          					  (0x0028)
+	#define     CVBS_AD_SEP                                                       (0x002c)
+	#define     CVBS_HUECR                                                        (0x0030)
+	#define     CVBS_SCPCR                                                        (0x0034)
+	#define     CVBS_SCFCR                                                        (0x0038)
+	#define     CVBS_CBACR                                                        (0x003c)
+	#define     CVBS_SACR                                                         (0x0040)
+	
+	/*********************BT*************************/
+	#define     BT_MSR0                                                           (0x0100)
+	#define     BT_MSR1                                                           (0x0104)
+	#define     BT_AL_SEPO                                                        (0x0108)
+	#define     BT_AL_SEPE                                                        (0x010c)
+	#define     BT_AP_SEP                                                         (0x0110)
+	
+	#define     TVOUT_DCR                                                         (0x0070)
+	#define     TVOUT_DDCR                                                        (0x0074)
+	#define     TVOUT_DCORCTL                                                     (0x0078)
+	#define     TVOUT_DRCR                                                        (0x007c)
+#endif
diff --git a/drivers/video/fbdev/owl/displays/cvbs/cvbs_reg.h b/drivers/video/fbdev/owl/displays/cvbs/cvbs_reg.h
new file mode 100755
index 0000000..c73eaee
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/cvbs_reg.h
@@ -0,0 +1,218 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2009 Actions Semi Inc.
+*/
+/*******************************************************************************/
+
+#ifndef __GL5206_TVOUT_H__
+#define __GL5206_TVOUT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/******************************************************************************/
+/* TVOUT_EN */
+/* bit[31:1]  Reserved */
+#define TVOUT_EN_CVBS_EN					(0x1 << 0)
+
+/* TVOUT_OCR */
+/* bit[2:0],bit[6:5],bit[22:13],bit[31:29]  Reserved */
+#define TVOUT_OCR_PI_IRQEN					(0x1 << 12)
+#define TVOUT_OCR_PO_IRQEN					(0x1 << 11)
+#define TVOUT_OCR_INACEN					(0x1 << 10)
+#define TVOUT_OCR_PO_ADEN					(0x1 << 9)
+#define TVOUT_OCR_PI_ADEN					(0x1 << 8)
+#define TVOUT_OCR_INREN						(0x1 << 7)
+#define TVOUT_OCR_DACOUT					(0x1 << 4)
+#define TVOUT_OCR_DAC3						(0x1 << 3)
+
+/* TVOUT_STA */
+/* bit[2:0],bit[6:4]  Reserved */
+#define TVOUT_STA_DAC3DLS					(0x1 << 7)
+#define TVOUT_STA_DAC3ILS					(0x1 << 3)
+
+
+/* TVOUT_CCR */
+/* bit[31:4]  Reserved */
+#define TVOUT_CCR_COTCTL_MASK				(0xF << 0)
+#define TVOUT_CCR_COTCTL(x)					(((x) & 0xF) << 0)
+
+/* TVOUT_BCR */
+/* bit[31:10]  Reserved */
+#define TVOUT_BCR_BRGCTL_MASK				(0x3FF << 0)
+#define TVOUT_BCR_BRGCTL(x)					(((x) & 0x3FF) << 0)
+
+/* TVOUT_CSCR */
+/* bit[31:6]  Reserved */
+#define TVOUT_CSCR_CSATCTL_MASK				(0x3F << 0)
+#define TVOUT_CSCR_CSATCTL(x)				(((x) & 0x3F) << 0)
+
+/*+++++++++TVOUT_PRL+++++++++*/
+/* bit[31:12],bit[7:0]  Reserved */
+#define TVOUT_PRL_CPN_MASK				(0xF << 8)
+#define TVOUT_PRL_CPN(x)				(((x) & 0xF) << 8)
+
+/*+++++++++TVOUT_VFALD+++++++++*/
+/* bit[31:12],bit[7:0]  Reserved */
+#define TVOUT_PRL_VFALD_MASK				(0xF << 8)
+#define TVOUT_PRL_VFALD(x)				(((x) & 0xF) << 8)
+
+/* CVBS_MSR */
+/* bit[31:7]  Reserved */
+#define CVBS_MSR_SCEN						(0x1 << 6)
+#define CVBS_MSR_APNS_MASK					(0x1 << 5)
+#define CVBS_MSR_APNS_BT470					(0x0 << 5)
+#define CVBS_MSR_APNS_BT656					(0x1 << 5)
+#define CVBS_MSR_CVCKS						(0x1 << 4)
+#define CVBS_MSR_CVBS_MASK					(0xF << 0)
+#define CVBS_MSR_CVBS_NTSC_M					(0x0 << 0)
+#define CVBS_MSR_CVBS_NTSC_J					(0x1 << 0)
+#define CVBS_MSR_CVBS_PAL_NC					(0x2 << 0)
+#define CVBS_MSR_CVBS_PAL_BGH					(0x3 << 0)
+#define CVBS_MSR_CVBS_PAL_D					(0x4 << 0)
+#define CVBS_MSR_CVBS_PAL_I					(0x5 << 0)
+#define CVBS_MSR_CVBS_PAL_M					(0x6 << 0)
+#define CVBS_MSR_CVBS_PAL_N					(0x7 << 0)
+
+/* CVBS_AL_SEPO */
+/* bit[31:26]  Reserved */
+#define CVBS_AL_SEPO_ALEP_MASK				(0x3FF << 16)
+#define CVBS_AL_SEPO_ALEP(x)				(((x) & 0x3FF) << 16)
+/* bit[15:10]  Reserved */
+#define CVBS_AL_SEPO_ALSP_MASK				(0x3FF << 0)
+#define CVBS_AL_SEPO_ALSP(x)				(((x) & 0x3FF) << 0)
+
+/* CVBS_AL_SEPE */
+/* bit[31:26]  Reserved */
+#define CVBS_AL_SEPE_ALEPEF_MASK			(0x3FF << 16)
+#define CVBS_AL_SEPE_ALEPEF(x)				(((x) & 0x3FF) << 16)
+/* bit[15:10]  Reserved */
+#define CVBS_AL_SEPE_ALSPEF_MASK			(0x3FF << 0)
+#define CVBS_AL_SEPE_ALSPEF(x)				(((x) & 0x3FF) << 0)
+
+/* CVBS_AD_SEP */
+/* bit[31:26]  Reserved */
+#define CVBS_AD_SEP_ADEP_MASK				(0x3FF << 16)
+#define CVBS_AD_SEP_ADEP(x)					(((x) & 0x3FF) << 16)
+/* bit[15:10]  Reserved */
+#define CVBS_AD_SEP_ADSP_MASK				(0x3FF << 0)
+#define CVBS_AD_SEP_ADSP(x)					(((x) & 0x3FF) << 0)
+
+/* CVBS_HUECR */
+/* bit[31:8]  Reserved */
+#define CVBS_HUECR_HUECTL_MASK				(0xFF << 0)
+#define CVBS_HUECR_HUECTL(x)				(((x) & 0xFF) << 0)
+
+/* CVBS_SCPCR */
+/* bit[31:12]  Reserved */
+#define CVBS_SCPCR_SCPC_MASK				(0xFFF << 0)
+#define CVBS_SCPCR_SCPC(x)					(((x) & 0xFFF) << 0)
+
+/* CVBS_SCFCR */
+/* bit[31:5]  Reserved */
+#define CVBS_SCFCR_SCFCR_MASK				(0x1F << 0)
+#define CVBS_SCFCR_SCFCR(x)					(((x) & 0x1F) << 0)
+
+/* CVBS_CBACR */
+/* bit[31:4]  Reserved */
+#define CVBS_CBACR_CBURAM_MASK				(0xF << 0)
+#define CVBS_CBACR_CBURAM(x)				(((x) & 0xF) << 0)
+
+/* CVBS_SACR */
+/* bit[31:7]  Reserved */
+#define CVBS_SACR_SYNCAM_MASK				(0x7F << 0)
+#define CVBS_SACR_SYNCAM(x)					(((x) & 0x7F) << 0)
+
+
+/* ++++++++BT_MSR0+++++++ */
+/* bit[31:1]  Reserved */
+#define BT_MSR0_BTEN					(0x1 << 0)
+
+/* ++++++++BT_MSR1+++++++ */
+/* bit[31:3],bit[0] Reserved */
+#define BT_MSR1_PNMS					(0x1 << 1)
+#define BT_MSR1_PAES					(0x1 << 2)
+
+
+/* +++++++BT_AL_SEPO+++++++++ */
+/* bit[31:25]  Reserved */
+#define BT_AL_SEPO_LEPO_MASK				(0x1FF << 16)
+#define BT_AL_SEPO_LEPO(x)				(((x) & 0x1FF) << 16)
+/* bit[15:8]  Reserved */
+#define BT_AL_SEPO_LSPO_MASK				(0xFF << 0)
+#define BT_AL_SEPO_LSPO(x)				(((x) & 0xFF) << 0)
+
+/* +++++++BT_AL_SEPE+++++++++ */
+/* bit[31:26]  Reserved */
+#define BT_AL_SEPE_LEPO_MASK				(0x3FF << 16)
+#define BT_AL_SEPE_LEPO(x)				(((x) & 0x3FF) << 16)
+/* bit[15:10]  Reserved */
+#define BT_AL_SEPE_LSPO_MASK				(0x3FF << 0)
+#define BT_AL_SEPE_LSPO(x)				(((x) & 0x3FF) << 0)
+
+/* +++++++BT_AP_SEP+++++++++ */
+/* bit[31:26]  Reserved */
+#define BT_AP_SEP_ADEP_MASK				(0x3FF << 16)
+#define BT_AP_SEP_ADEP(x)				(((x) & 0x3FF) << 16)
+/* bit[15:10]  Reserved */
+#define BT_AP_SEP_ADSP_MASK				(0x3FF << 0)
+#define BT_AP_SEP_ADSP(x)				(((x) & 0x3FF) << 0)
+
+
+
+/* TVOUT_DCR */
+/* bit[31:24],bit[18:4]   Reserved */
+#define TVOUT_DCR_CVBS_STA_MASK				(0x1F << 19)
+#define TVOUT_DCR_OSIGS_MASK				(0x1F << 0)
+
+/* TVOUT_DDCR */
+/* bit[31:21]  Reserved */
+#define TVOUT_DDCR_DCKCAES_MASK				(0x1 << 20)
+#define TVOUT_DDCR_DCKCAES_PE				(0x0 << 20)
+#define TVOUT_DDCR_DCKCAES_NE				(0x1 << 20)
+/* bit[19:18]  Reserved */
+#define TVOUT_DDCR_YDLVLS_MASK				(0x3 << 16)
+#define TVOUT_DDCR_YDLVLS(X)				(((x) & 0x3) << 16)
+#define TVOUT_DDCR_SCOTEN					(0x1 << 11)
+#define TVOUT_DDCR_CORMODE_MASK				(0x3 << 9)
+#define TVOUT_DDCR_CORMODE(x)				(((x) & 0x3) << 9)
+#define TVOUT_DDCR_COREN					(0x1 << 8)
+#define TVOUT_DDCR_HDACUR_MASK				(0xF << 4)
+#define TVOUT_DDCR_HDACUR(x)				(((x) & 0xF) << 4)
+/* bit[3:1]  Reserved */
+#define TVOUT_DDCR_TDACEN					(0x1 << 0)
+
+/* TVOUT_DCORCTL \B1仯*/
+#define TVOUT_DCORCTL_CORAMP_MASK			(0xFFFF << 16)
+#define TVOUT_DCORCTL_CORAMP(x)				(((x) & 0xFFFF) << 16)
+#define TVOUT_DCORCTL_CORFREQ_MASK			(0xFFFF << 0)
+#define TVOUT_DCORCTL_CORFREQ(x)			(((x) & 0xFFFF) << 0)
+
+/* TVOUT_DRCR \B1仯*/
+/* bit[31:21]  Reserved */
+#define TVOUT_DRCR_ROMTEN				(0x1 << 24)
+#define TVOUT_DRCR_ROMDAT_MASK				(0xFFFFFF << 0)
+
+/*CMU_TVOUTPLL*/
+#define CMU_TVOUTPLL_PLL1_DPLLEN        (1 << 19)
+#define CMU_TVOUTPLL_PLL0_DPCLM(x)      (((x) << 16) & 0x3)
+
+#define CMU_TVOUTPLL_PLL1EN            (1 << 11)
+#define CMU_TVOUTPLL_CVBS_PLL1FSS(x)   (((x) & 0x7)  << 8)
+#define CMU_TVOUTPLL_CVBS_CLK108M_EN	(1 << 7)
+#define CMU_TVOUTPLL_TK0SS            	(1 << 6)
+/* bit2 reserved */
+#define CMU_TVOUTPLL_CLK0(x)		(((x) << 4) & 0x3)
+#define CMU_TVOUTPLL_PLL0EN             (1 << 3)
+/* bit2 reserved */
+#define CMU_TVOUTPLL_PLL0FSS(x)       (((x) << 0) & 0x3)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* ifndef __ATV230x_TVOUT_H__ */
diff --git a/drivers/video/fbdev/owl/displays/cvbs/cvbs_sysfs.c b/drivers/video/fbdev/owl/displays/cvbs/cvbs_sysfs.c
new file mode 100755
index 0000000..31f67c4
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/cvbs_sysfs.c
@@ -0,0 +1,120 @@
+/*
+ * dsi_sysfs.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+
+#include "cvbs.h"
+
+
+
+
+/*static ssize_t show_dsi_dump(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	dsihw_fs_dump_regs(dev);
+	return 0;
+}
+
+static ssize_t test_dsi_fs(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	test_fs_dsi(dev);
+	return 0;
+}
+*/
+static ssize_t dump_cvbs_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	dump_reg();
+	DEBUG_CVBS("test cvbs\n");
+	return 0;
+}
+
+
+static ssize_t show_cvbs_vid(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	
+	return snprintf(buf, PAGE_SIZE, "%d\n", cvbs.current_vid);
+}
+
+static ssize_t store_cvbs_vid(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+		
+		owldss_cvbs_display_disable(cvbs.dssdev);
+		cvbs.dssdev->driver->set_vid(cvbs.dssdev, val);
+		owldss_cvbs_display_enable(cvbs.dssdev);	
+
+	return r ? r : count;
+}
+
+
+
+
+static struct device_attribute asoc_cvbs_attrs[] = {
+	__ATTR(reg_dump, S_IRUGO, dump_cvbs_reg, NULL),
+	__ATTR(vid, S_IRUGO | S_IWUSR, show_cvbs_vid, store_cvbs_vid),
+};
+
+int owl_cvbs_create_sysfs(struct device *dev)
+{
+	int r, t;
+
+	for (t = 0; t < ARRAY_SIZE(asoc_cvbs_attrs); t++) 
+	{
+		r = device_create_file(dev, &asoc_cvbs_attrs[t]);
+
+		if (r) {
+			dev_err(dev, "failed to create sysfs file\n");
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+void asoc_cvbs_remove_sysfs(struct device *dev)
+{
+	int  t;
+	
+	for (t = 0; t < ARRAY_SIZE(asoc_cvbs_attrs); t++) 
+	{
+		device_remove_file(dev, &asoc_cvbs_attrs[t]);
+	}
+}
+
diff --git a/drivers/video/fbdev/owl/displays/cvbs/panel-cvbs.c b/drivers/video/fbdev/owl/displays/cvbs/panel-cvbs.c
new file mode 100755
index 0000000..ba7b540
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/cvbs/panel-cvbs.c
@@ -0,0 +1,245 @@
+/*
+ * Generic EDP Panels support
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu at canonical.com>
+ *
+ * LCD panel driver for Sharp LQ043T1DG01
+ *
+ * Copyright (C) 2009 Actions Inc
+ * Author: Vaibhav Hiremath <hvaibhav at ti.com>
+ *
+ * LCD panel driver for Toppoly TDO35S
+ *
+ * Copyright (C) 2009 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike at compulab.co.il>
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <mach/bootdev.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "../../dss/dss_features.h"
+#include "cvbs.h"
+
+static struct {
+	struct mutex lock;
+} cvbs_panel;
+
+
+static int  cvbs_panel_enable(struct owl_dss_device *dssdev)
+{
+	int ret;
+
+	DEBUG_CVBS("cvbs_panel_enable\n");
+	mutex_lock(&cvbs_panel.lock);
+	
+	ret = owldss_cvbs_display_enable(dssdev);
+	
+	dssdev->state = OWL_DSS_DISPLAY_ACTIVE;
+	mutex_unlock(&cvbs_panel.lock);
+
+	return ret;
+}
+
+static void cvbs_panel_disable(struct owl_dss_device *dssdev)
+{
+	DEBUG_CVBS("cvbs_panel_disable\n");
+	mutex_lock(&cvbs_panel.lock);
+	
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE) {
+		
+		owldss_cvbs_display_disable(dssdev);
+
+		dssdev->state = OWL_DSS_DISPLAY_DISABLED;		
+	}
+
+	mutex_unlock(&cvbs_panel.lock);
+
+}
+
+static void cvbs_enable_hpd(struct owl_dss_device *dssdev,bool enable)
+{
+	DEBUG_CVBS("cvbs_enable_hpt\n");
+	mutex_lock(&cvbs_panel.lock);
+	
+	owldss_cvbs_display_enable_hpd(dssdev, enable);
+
+	mutex_unlock(&cvbs_panel.lock);
+}
+			
+			
+static void cvbs_panel_get_timings(struct owl_dss_device *dssdev,struct owl_video_timings *timings)
+{	
+	mutex_lock(&cvbs_panel.lock);
+		
+	*timings = dssdev->timings;
+		
+	mutex_unlock(&cvbs_panel.lock);
+	
+}
+
+static void cvbs_panel_set_timings(struct owl_dss_device *dssdev,struct owl_video_timings *timings)
+{		
+	mutex_lock(&cvbs_panel.lock);
+		
+	dssdev->timings = *timings;
+		
+	mutex_unlock(&cvbs_panel.lock);
+
+}
+
+ void cvbs_set_vid(struct owl_dss_device *dssdev,
+			int vid)
+{
+	DEBUG_CVBS("cvbs_set_vid\n");
+	mutex_lock(&cvbs_panel.lock);
+	
+	cvbs_display_set_vid(dssdev,vid);
+	
+	mutex_unlock(&cvbs_panel.lock);
+}
+
+static void cvbs_get_vid(struct owl_dss_device *dssdev,
+			int *vid)
+{
+	mutex_lock(&cvbs_panel.lock);
+	
+	cvbs_display_get_vid(dssdev, vid);
+	
+	mutex_unlock(&cvbs_panel.lock);
+}
+static void cvbs_get_over_scan(struct owl_dss_device *dssdev, 
+			u16 * over_scan_width,u16 * over_scan_height)
+{
+
+	mutex_lock(&cvbs_panel.lock);
+	
+	cvbs_display_get_overscan(dssdev, over_scan_width,over_scan_height);
+	
+	mutex_unlock(&cvbs_panel.lock);
+}
+
+static void cvbs_set_over_scan(struct owl_dss_device *dssdev,
+			u16 over_scan_width,u16 over_scan_height)
+{
+
+	mutex_lock(&cvbs_panel.lock);
+	
+	cvbs_display_set_overscan(dssdev, over_scan_width,over_scan_height);
+	
+	mutex_unlock(&cvbs_panel.lock);
+}
+
+
+static int cvbs_panel_suspend(struct owl_dss_device *dssdev)
+{
+	
+
+	mutex_lock(&cvbs_panel.lock);
+	
+	owldss_cvbs_suspend(dssdev);
+	
+	mutex_unlock(&cvbs_panel.lock);
+	return 0;
+}
+
+static int cvbs_panel_resume(struct owl_dss_device *dssdev)
+{
+
+	mutex_lock(&cvbs_panel.lock);
+	
+	owldss_cvbs_resume(dssdev);
+	
+	mutex_unlock(&cvbs_panel.lock);
+	
+	return 0;
+}
+
+static int cvbs_panel_probe(struct owl_dss_device *dssdev)
+{
+
+	
+	cvbs.dssdev = dssdev;
+	
+	cvbs_display_set_vid(dssdev, cvbs.current_vid);
+
+	DEBUG_CVBS("cvbs_panel_probe\n");
+   
+	return 0;
+}
+
+static void __exit cvbs_panel_remove(struct owl_dss_device *dssdev)
+{
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	kfree(drv_data);
+
+	dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+
+
+static struct owl_dss_driver cvbs_driver = {
+	.probe		= cvbs_panel_probe,
+	.remove		= cvbs_panel_remove,
+	.suspend		  = cvbs_panel_suspend,
+	.resume 		  = cvbs_panel_resume,
+	.enable			  = cvbs_panel_enable,
+	.disable		  = cvbs_panel_disable,
+	.set_vid   	 	  = cvbs_set_vid,
+	.get_vid    	  = cvbs_get_vid,
+	.enable_hpd		  = cvbs_enable_hpd,
+	.get_timings	= cvbs_panel_get_timings,
+	.set_timings	= cvbs_panel_set_timings,
+	.get_over_scan = cvbs_get_over_scan,
+	.set_over_scan = cvbs_set_over_scan,
+	.driver         = {
+		.name   = "cvbs_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init cvbs_panel_drv_init(void)
+{
+	int r = -1; 
+
+	DEBUG_CVBS("generic_cvbs_panel_drv_init \n");
+	mutex_init(&cvbs_panel.lock);
+	
+	r = owl_cvbs_init_platform();
+	
+	if(r){
+		printk("generic_cvbs_panel_drv_init r %d \n",r);
+		return r;
+	}
+	 
+	return owl_dss_register_driver(&cvbs_driver);
+}
+
+static void __exit cvbs_panel_drv_exit(void)
+{
+	owl_dss_unregister_driver(&cvbs_driver);
+}
+
+module_init(cvbs_panel_drv_init);
+module_exit(cvbs_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/displays/dsi/Kconfig b/drivers/video/fbdev/owl/displays/dsi/Kconfig
new file mode 100755
index 0000000..982469d
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_OWL_DSI
+	tristate "OWL dsi support"
+	depends on ARCH_OWL
+	---help---
+	  Say Y here if you need dsi controller in your system.
+
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
diff --git a/drivers/video/fbdev/owl/displays/dsi/Makefile b/drivers/video/fbdev/owl/displays/dsi/Makefile
new file mode 100755
index 0000000..8c10b20
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_OWL_DSI) += owl_dsi.o
+
+owl_dsi-y := panel-mipi.o dsihw.o dsi_sysfs.o dsi_cmd.o
+
diff --git a/drivers/video/fbdev/owl/displays/dsi/dsi.h b/drivers/video/fbdev/owl/displays/dsi/dsi.h
new file mode 100755
index 0000000..69cf4b7
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/dsi.h
@@ -0,0 +1,35 @@
+
+
+#ifndef __OWL_DSI_H
+#define __OWL_DSI_H
+
+#include <linux/platform_device.h>
+#include <video/owldss.h>
+
+	#define DSI_PRINTa
+	#ifdef DSI_PRINT
+	#define DEBUG_DSI(format, ...) \
+		do { \
+			printk(KERN_ERR "OWL_DSI: " format, ## __VA_ARGS__); \
+		} while (0)
+	#else
+	#define DEBUG_DSI(format, ...)
+	#endif
+
+	/*dsihw.c*/
+	void dsihw_fs_dump_regs(struct device *dev);
+	void test_fs_dsi(struct device *dev);
+	void test_fs_longcmd(struct device *dev);
+
+	void dsihw_send_long_packet(struct platform_device *pdev, int data_type, int word_cnt, int * send_data, int trans_mode);
+	void dsihw_send_short_packet(struct platform_device *pdev,int data_type, int sp_data, int trans_mode);
+	void owl_dsi_select_video_timings(struct owl_dss_device *dssdev, u32 num,
+                                   struct owl_video_timings *timings);
+	/*dsi_sysfs.c*/
+	int owl_dsi_create_sysfs(struct device *dev);
+
+	/*dsi_cmd.c*/
+	void send_cmd(struct platform_device *pdev);
+	void send_cmd_test(struct platform_device *pdev);
+	
+#endif 
diff --git a/drivers/video/fbdev/owl/displays/dsi/dsi_cmd.c b/drivers/video/fbdev/owl/displays/dsi/dsi_cmd.c
new file mode 100755
index 0000000..b3ff051
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/dsi_cmd.c
@@ -0,0 +1,87 @@
+
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+
+#include "dsihw.h"
+#include "dsi.h"
+
+#define LONG_CMD_MODE 0x39
+#define SHORT_CMD_MODE 0x05
+
+#define POWER_MODE  0x01
+
+void send_long_cmd(struct platform_device *pdev, char *pcmd, int cnt)
+{
+	dsihw_send_long_packet(pdev, LONG_CMD_MODE,cnt,(unsigned int *)pcmd,POWER_MODE);	
+}
+
+void send_short_cmd(struct platform_device *pdev, int cmd)
+{
+	dsihw_send_short_packet(pdev, SHORT_CMD_MODE,cmd,POWER_MODE);  
+}
+
+void send_short_cmd_1(struct platform_device *pdev, int cmd, int singnal)
+{
+	dsihw_send_short_packet(pdev, singnal,cmd,POWER_MODE);  
+}
+
+
+/*
+1. 如需发长包命令
+	首先调用start_long_cmd
+	在发完最后一个长命令后调用end_long_cmd
+
+2. 长包格式
+	pakg[0] cmd
+	pakg[1] data1
+	pakg[2] data2
+	.       .
+	.       .
+	send_long_cmd(pakg, 4); 第一个参数是指针,第二个参数是传输个数
+	
+3. 短包格式
+	send_short_cmd(cmd);
+	exp: send_short_cmd(0x11);
+	
+4. 需要用到毫秒延时
+	mdelay(100); //100毫秒的延时
+*/
+void send_cmd(struct platform_device *pdev)
+{
+/*	char pakg[100];
+	
+	start_long_cmd();
+	pakg[0] = 0xbf; 
+	pakg[1] = 0x93; 
+	pakg[2] = 0x61; 
+	pakg[3] = 0xf4; 
+	send_long_cmd(pakg, 4);
+	pakg[0] = 0xbf; 
+	pakg[1] = 0x93; 
+	send_long_cmd(pakg, 2);	
+	end_long_cmd();
+	
+*/	
+	send_short_cmd(pdev, 0x11);
+	mdelay(200);
+	send_short_cmd(pdev, 0x29);
+	mdelay(200);
+	send_short_cmd_1(pdev, 0, 0x32);
+	mdelay(200);
+}
+
+
+void send_cmd_test(struct platform_device *pdev)
+{
+	char pakg[100];
+	
+	pakg[0] = 0xbf; 
+	pakg[1] = 0x93; 
+	pakg[2] = 0x61; 
+	pakg[3] = 0xf4; 
+	send_long_cmd(pdev, pakg, 4);
+	pakg[0] = 0xbf; 
+	pakg[1] = 0x93; 
+	send_long_cmd(pdev, pakg, 2);	
+}
diff --git a/drivers/video/fbdev/owl/displays/dsi/dsi_sysfs.c b/drivers/video/fbdev/owl/displays/dsi/dsi_sysfs.c
new file mode 100755
index 0000000..330393b
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/dsi_sysfs.c
@@ -0,0 +1,90 @@
+/*
+ * dsi_sysfs.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+
+#include "dsihw.h"
+#include "dsi.h"
+
+static ssize_t show_dsi_dump(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	dsihw_fs_dump_regs(dev);
+	return 0;
+}
+
+static ssize_t test_dsi_fs(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	test_fs_dsi(dev);
+	return 0;
+}
+
+static ssize_t test_fs_dsi_cmd(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	test_fs_longcmd(dev);
+	return 0;
+}
+
+static struct device_attribute asoc_dsi_attrs[] = {
+	__ATTR(reg_dump, S_IRUGO, show_dsi_dump, NULL),
+	__ATTR(test_dsi, S_IRUGO, test_dsi_fs, NULL),
+	__ATTR(longcmd_test, S_IRUGO, test_fs_dsi_cmd, NULL),
+};
+
+int owl_dsi_create_sysfs(struct device *dev)
+{
+	int r, t;
+
+	for (t = 0; t < ARRAY_SIZE(asoc_dsi_attrs); t++) 
+	{
+		r = device_create_file(dev, &asoc_dsi_attrs[t]);
+
+		if (r) {
+			dev_err(dev, "failed to create sysfs file\n");
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+void asoc_dsi_remove_sysfs(struct device *dev)
+{
+	int  t;
+	
+	for (t = 0; t < ARRAY_SIZE(asoc_dsi_attrs); t++) 
+	{
+		device_remove_file(dev, &asoc_dsi_attrs[t]);
+	}
+}
+
diff --git a/drivers/video/fbdev/owl/displays/dsi/dsihw.c b/drivers/video/fbdev/owl/displays/dsi/dsihw.c
new file mode 100755
index 0000000..959d909
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/dsihw.c
@@ -0,0 +1,1222 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/dsi.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "DSI"
+#include <mach/bootdev.h>
+#include <linux/kernel.h> 
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <mach/clkname.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/fb.h>
+#include <linux/dmaengine.h> 
+#include <linux/dma-mapping.h> 
+#include <linux/dma-direction.h> 
+#include <asm/cacheflush.h>
+#include <asm/outercache.h>
+#include <mach/hdmac-owl.h>
+
+
+#include <video/owldss.h>
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+#include "dsihw.h"
+#include "dsi.h"
+
+#define POWER_REGULATOR_NAME        "dsivcc"
+
+void  *reg_sps_ldo_ctl = 0;	
+void  *cmu_dsipll_clk = 0;
+	
+struct dma_test
+{
+	unsigned char *dma_buf_a;
+	unsigned char *dma_buf_b;
+	dma_addr_t dma_phys_a;
+	dma_addr_t dma_phys_b;
+	struct dma_chan *chan;
+	struct dma_device *dev;
+	enum dma_ctrl_flags flags;
+	struct dma_async_tx_descriptor *dma_desc;
+
+	int callback_control;
+	unsigned int total;
+	
+	unsigned int slave_id_fifo0_tx;
+	struct completion	dma_complete;
+};
+
+struct dma_test *dma_gl;
+
+struct owl_dsi_gpio {
+    int gpio;
+    int active_low;
+};
+
+struct owl_videomode {
+    u32                     refresh;
+    u32                     xres;
+    u32                     yres;
+
+    /*in pico second, 0.000 000 000 001s*/
+    u32                     pixclock;
+
+    u32                     left_margin;
+    u32                     right_margin;
+    u32                     upper_margin;
+    u32                     lower_margin;
+    u32                     hsync_len;
+    u32                     vsync_len;
+
+    /*0: FB_VMODE_NONINTERLACED, 1:FB_VMODE_INTERLACED*/
+    u32                     vmode;
+};
+	
+struct owl_dsi_reg {
+    u32                     dsi_ctrl;
+    u32                     dsi_size;
+    u32                     dsi_color;
+    u32                     dsi_rgbht0;
+    u32                     dsi_rgbht1;		
+	u32                     dsi_rgbvt0;
+    u32                     dsi_rgbvt1;
+    u32                     dsi_pack_cfg;
+    u32                     dsi_pack_header;
+	u32						dsi_vedio_cfg;
+    u32                     dsi_phy_t0;		
+	u32                     dsi_phy_t1;
+    u32                     dsi_phy_t2;
+    u32                     dsi_phy_ctrl;
+    u32                     dsi_pin_map;
+	u32 					cmu_dsipll_clk;
+};
+
+struct dsi_data {
+	
+    struct platform_device  *pdev;
+    void __iomem            *base;
+    struct owl_dss_device   *dssdev;
+
+    struct clk              *dsi_clk;
+    struct regulator        *dsi_power;
+
+    /* the followings are strict with DTS */
+    struct owl_dsi_gpio    power_gpio;
+	struct owl_dsi_gpio    reset_gpio;
+	
+    u32                     port_type;
+
+    u32                     data_width;
+
+    u32                     num_modes;
+    struct owl_videomode   *modes;
+	
+	struct owl_dsi_reg     *regs;
+    /* end of strict with DTS */
+
+    bool                    dsi_enabled;
+    
+    struct mutex            lock;
+};
+
+static bool boot_dsi_inited;
+static struct platform_device *dsi_pdev_map[MAX_NUM_LCD];
+
+static void dma_callback(void *param)
+{
+	struct dma_test *dmatest = param;
+
+	complete(&dmatest->dma_complete);		
+	DEBUG_DSI("dma_callback~~~~~dmatest  %p\n", dmatest);
+	return;
+}
+
+static int start_dma(struct dma_test *dmatest, int *pbuf, int len)
+{
+
+	dma_addr_t dma_addr;
+	dma_cookie_t cookie = -EINVAL;
+	DEBUG_DSI("start dma dmatest->chan %p   pbuf  %p dma_gl->dma_buf_a %p!!!!\n", dmatest->chan, pbuf, dma_gl->dma_buf_a);
+	dma_addr = dma_map_single(dmatest->chan->device->dev, pbuf, len, DMA_MEM_TO_DEV);
+	DEBUG_DSI("dma_map_single end!!!!\n");
+	if (dma_addr)
+		dmatest->dma_desc = dmaengine_prep_slave_single(dmatest->chan, dma_addr, len,
+			DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+			
+	DEBUG_DSI("device_prep_dma_memcpy end!!!!\n");
+	if (!dmatest->dma_desc) {
+		pr_err("Not able to get desc for TX\n");
+		if (dmatest->chan) {
+			dma_release_channel(dmatest->chan);
+			dmatest->chan = NULL;
+		}		
+		goto out;
+	}
+
+	dmatest->dma_desc->callback = dma_callback;
+	dmatest->dma_desc->callback_param = dmatest;
+	DEBUG_DSI("dmaengine_submit !!!!\n");
+	cookie = dmaengine_submit(dmatest->dma_desc);
+	DEBUG_DSI("dma_async_issue_pending !!!!\n");
+	dma_async_issue_pending(dmatest->chan);
+	DEBUG_DSI("dma_async_issue_pending end !!!!\n");
+
+	DEBUG_DSI("dma end!!!!\n");
+
+out:
+	dma_unmap_single(dmatest->chan->device->dev, dma_addr, len, DMA_MEM_TO_DEV);
+	return -ENODEV;	
+}
+
+int dma_init(void)
+{
+	int ret;
+	dma_cap_mask_t mask;
+	struct owl_dma_slave *acts_slave;
+	struct dma_slave_config cfg;	
+	
+	DEBUG_DSI("gl++++dmatest_init start \n");
+	dma_gl = kzalloc(sizeof(struct dma_test), GFP_KERNEL);
+	DEBUG_DSI("dma_gl  kzalloc end \n");
+	
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_gl->chan = dma_request_channel(mask, NULL, NULL);
+	if (!dma_gl->chan) {
+		pr_err("Failed to request DMA channel\n");
+		goto err;
+	}
+	dma_gl->dev = dma_gl->chan->device;
+	DEBUG_DSI("%s: TX: got channel %p   id %d\n", __func__, dma_gl->chan, dma_gl->chan->chan_id);
+		
+	acts_slave = devm_kzalloc(dma_gl->dev->dev, sizeof(*acts_slave), GFP_KERNEL);
+	DEBUG_DSI("acts_slave %p \n", acts_slave );	
+	if (!acts_slave) {
+		pr_err("Not able to alloc struct acts_dma_slave\n");
+		goto err;
+	}
+	acts_slave->dma_dev = dma_gl->dev->dev;
+	acts_slave->trans_type = SLAVE;
+	acts_slave->mode = 0x00010224;
+	dma_gl->chan->private = acts_slave;
+	
+	memset(&cfg, 0, sizeof(cfg));
+	cfg.direction = DMA_MEM_TO_DEV;
+	cfg.dst_addr = 0xb0220030;
+	cfg.src_addr = 0xb0220030;
+	cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
+	cfg.device_fc = false;
+	ret = dmaengine_slave_config(dma_gl->chan, &cfg);
+	if (ret < 0)
+	{
+		DEBUG_DSI("dmaengine_slave_config ret %x\n", ret);
+		goto err;
+	}	
+	
+	init_completion(&dma_gl->dma_complete);
+	DEBUG_DSI("gl++++dma_init end\n");
+	return 0;
+
+err:
+	if (dma_gl->chan) {
+		dma_release_channel(dma_gl->chan);
+		dma_gl->chan = NULL;
+	}		
+	return -ENODEV;		
+
+}
+
+inline struct dsi_data *dsihw_get_dsidrv_data(struct platform_device *pdev)
+{
+	return dev_get_drvdata(&pdev->dev);
+}
+
+inline void dsihw_write_reg(struct platform_device *pdev,const u16 index, u32 val)
+{
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+	//DEBUG_DSI("dsihw_write_reg  ~~~ %p index %d\n",dsi->base,index);
+	writel(val, dsi->base + index);
+}
+
+inline u32 dsihw_read_reg(struct platform_device *pdev,const u16 index)
+{
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+	//DEBUG_DSI("dsihw_read_reg  ~~~ %p index %d\n",dsi->base,index);
+	return readl(dsi->base + index);
+}
+
+void dsihw_dump_regs(struct platform_device *pdev){
+	
+#define DUMPREG(name,r) printk("%s %08x\n",name,dsihw_read_reg(pdev, r))
+
+     DUMPREG("DSI_CTRL  	value is ", DSI_CTRL);
+     DUMPREG("DSI_SIZE  	value is ", DSI_SIZE);
+     DUMPREG("DSI_COLOR  	value is ", DSI_COLOR);
+	 DUMPREG("DSI_VIDEO_CFG value is ", DSI_VIDEO_CFG);
+     DUMPREG("DSI_RGBHT0  	value is ", DSI_RGBHT0);
+     DUMPREG("DSI_RGBHT1  	value is ", DSI_RGBHT1);
+     DUMPREG("DSI_RGBVT0  	value is ", DSI_RGBVT0);
+     DUMPREG("DSI_RGBVT1  	value is ", DSI_RGBVT1);
+     DUMPREG("DSI_TIMEOUT 	value is ", DSI_TIMEOUT);     
+     DUMPREG("DSI_TR_STA  	value is ", DSI_TR_STA);
+     DUMPREG("DSI_INT_EN  	value is ", DSI_INT_EN);
+     DUMPREG("DSI_ERROR_REPORT  value is ", DSI_ERROR_REPORT);
+     DUMPREG("DSI_FIFO_ODAT  value is ", DSI_FIFO_ODAT);     
+     DUMPREG("DSI_FIFO_IDAT  value is ", DSI_FIFO_IDAT);
+     DUMPREG("DSI_IPACK  value is ", DSI_IPACK);
+     DUMPREG("DSI_PACK_CFG  value is ", DSI_PACK_CFG);     
+     DUMPREG("DSI_PACK_HEADER  value is ", DSI_PACK_HEADER);
+     DUMPREG("DSI_TX_TRIGGER  value is ", DSI_TX_TRIGGER);
+     DUMPREG("DSI_RX_TRIGGER  value is ", DSI_RX_TRIGGER);
+     DUMPREG("DSI_LANE_CTRL  value is ", DSI_LANE_CTRL);
+     DUMPREG("DSI_LANE_STA  value is ", DSI_LANE_STA);
+     DUMPREG("DSI_PHY_T0  value is ", DSI_PHY_T0);
+     DUMPREG("DSI_PHY_T1  value is ", DSI_PHY_T1);
+     DUMPREG("DSI_PHY_T2  value is ", DSI_PHY_T2);
+     DUMPREG("DSI_APHY_DEBUG0  value is ", DSI_APHY_DEBUG0);         
+     DUMPREG("DSI_APHY_DEBUG1  value is ", DSI_APHY_DEBUG1);
+     DUMPREG("DSI_SELF_TEST  value is ", DSI_SELF_TEST);
+     DUMPREG("DSI_PIN_MAP  value is ", DSI_PIN_MAP);
+     DUMPREG("DSI_PHY_CTRL  value is ", DSI_PHY_CTRL);     
+     DUMPREG("DSI_FT_TEST  value is ", DSI_FT_TEST); 
+
+}
+
+static int wait_lanes_stop(void)
+{
+	u32 tmp;
+	int cnt = 1000;
+	
+	struct platform_device *pdev = dsi_pdev_map[0] ;
+	do {
+		tmp = dsihw_read_reg(pdev, DSI_LANE_STA);
+		if ((tmp & (1 << 12)) || (tmp & (1 << 5)))
+			break;
+
+		udelay(2);
+	} while (--cnt);
+
+	if (cnt <= 0) {
+		printk("lanes cannot STOP\n");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int dsihw_set_dsi_clk(void)
+{
+	u32 reg_val=0;
+    struct platform_device *pdev = dsi_pdev_map[0] ;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+	reg_val = dsi->regs->cmu_dsipll_clk;
+	writel(reg_val, cmu_dsipll_clk);	
+
+	return 0;
+}
+
+static void dsihw_phy_config(struct platform_device *pdev)
+{	
+	int tmp,cmt=1000;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	DEBUG_DSI("phy set start %p \n", pdev);
+	tmp = 0x1300;
+	dsihw_write_reg(pdev,DSI_CTRL, tmp);	
+
+
+	tmp = dsi->regs->dsi_phy_t0;
+	dsihw_write_reg(pdev,DSI_PHY_T0, tmp);	
+	
+
+	tmp = dsi->regs->dsi_phy_t1;
+	dsihw_write_reg(pdev,DSI_PHY_T1, tmp);	
+
+	tmp = dsi->regs->dsi_phy_t2;
+	dsihw_write_reg(pdev,DSI_PHY_T2, tmp);	
+	
+	tmp = dsi->regs->dsi_phy_ctrl;
+	dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);	
+	
+	tmp = 0x688;
+	dsihw_write_reg(pdev,DSI_PIN_MAP, tmp);	
+
+	
+	tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);
+	tmp |= (1<<24);
+	dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+	
+	mdelay(20);
+	tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);
+	tmp |= ((1<<25)|(1<<28));
+	dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+	
+	while ((!(dsihw_read_reg(pdev,DSI_PHY_CTRL) & (1 << 31))) && --cmt)
+	udelay(2);
+	
+	
+	udelay(100);
+	tmp=dsihw_read_reg(pdev,DSI_PHY_CTRL);
+	if(tmp&0x02000000){
+		
+		printk("ERR : dsi cal fail!!\n");
+
+		tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);//disable calibrate
+		tmp &= (~(1<<25));
+		dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+		
+		tmp = dsihw_read_reg(pdev,DSI_LANE_CTRL); //force clock lane 
+		tmp |= ((1<<1)|(1<<4));
+		dsihw_write_reg(pdev,DSI_LANE_CTRL, tmp);
+		
+		tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);   //Select output node 
+		tmp |= (3<<2);
+		dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+		
+		tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);  //Disable (D-PHY is 
+		tmp &= (~(1<<24));
+		dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+		
+		tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);//Enable (D-PHY is 
+		tmp |= (1<<24);
+		dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+
+	}
+	
+	wait_lanes_stop();
+	
+	mdelay(2);
+	dsihw_write_reg(pdev,DSI_TR_STA,0x3);//Clear LP1 & LP0 Error
+	
+	tmp = dsi->regs->dsi_pin_map;
+	dsihw_write_reg(pdev,DSI_PIN_MAP, tmp);
+	
+	DEBUG_DSI("phy set end~~~~\n");   
+	
+	/*data0 line ,clk line in stop state */
+	wait_lanes_stop();
+	
+	tmp = dsihw_read_reg(pdev,DSI_CTRL);
+	tmp |= 0x40;
+	dsihw_write_reg(pdev,DSI_CTRL, tmp);	
+	/*data0 line ,clk line in stop state */	
+	wait_lanes_stop();
+}
+
+static void dsihw_video_config(struct platform_device *pdev)
+{	
+	int tmp;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	//tmp = 0x13d0; //default color
+	tmp = dsi->regs->dsi_ctrl;
+	dsihw_write_reg(pdev,DSI_CTRL, tmp);	
+
+	tmp = dsi->regs->dsi_size;
+	dsihw_write_reg(pdev,DSI_SIZE, tmp);	
+
+	tmp = dsi->regs->dsi_color;
+	dsihw_write_reg(pdev,DSI_COLOR, tmp);	
+
+	tmp = dsi->regs->dsi_rgbht0;
+	dsihw_write_reg(pdev,DSI_RGBHT0, tmp);	
+
+	tmp = dsi->regs->dsi_rgbht1;
+	dsihw_write_reg(pdev,DSI_RGBHT1, tmp);	
+
+	tmp = dsi->regs->dsi_rgbvt0;
+	dsihw_write_reg(pdev,DSI_RGBVT0, tmp);	
+
+	tmp = dsi->regs->dsi_rgbvt1;
+	dsihw_write_reg(pdev,DSI_RGBVT1, tmp);	
+
+	tmp = dsi->regs->dsi_pack_cfg;
+	dsihw_write_reg(pdev,DSI_PACK_CFG, tmp);	
+
+	tmp = dsi->regs->dsi_pack_header;
+	dsihw_write_reg(pdev,DSI_PACK_HEADER, tmp);	
+
+	tmp = dsi->regs->dsi_vedio_cfg;
+	dsihw_write_reg(pdev,DSI_VIDEO_CFG, tmp);	
+}
+
+static int dsihw_power_enable(struct platform_device *dsidev, bool enable) {
+    int ret = 0;
+	int temp;
+    struct dsi_data *dsi = dsihw_get_dsidrv_data(dsidev);
+
+    if (enable) {
+        if (gpio_is_valid(dsi->power_gpio.gpio)) {
+            gpio_direction_output(dsi->power_gpio.gpio,
+                                  !dsi->power_gpio.active_low);
+        }
+
+        if (dsi->dsi_power) {
+            ret = regulator_enable(dsi->dsi_power);
+        }
+		
+		temp = readl(reg_sps_ldo_ctl);
+		temp |= (1<<11);
+		writel(temp, reg_sps_ldo_ctl);	
+		mdelay(50);			
+		
+		if (gpio_is_valid(dsi->reset_gpio.gpio)){
+			printk("reset_gpio  is ok  %d\n", dsi->reset_gpio.active_low);
+		//	gpio_direction_output(dsi->reset_gpio.gpio,
+      //                            !dsi->reset_gpio.active_low);
+			mdelay(30);					  
+	        gpio_direction_output(dsi->reset_gpio.gpio,
+                                  dsi->reset_gpio.active_low);
+			mdelay(60);
+	        gpio_direction_output(dsi->reset_gpio.gpio,
+                                  !dsi->reset_gpio.active_low);
+		}
+    } else {
+        if (gpio_is_valid(dsi->power_gpio.gpio)) {
+            gpio_direction_output(dsi->power_gpio.gpio,
+                                  dsi->power_gpio.active_low);
+        }
+         mdelay(50);
+      /*  if (gpio_is_valid(dsi->reset_gpio.gpio)){
+			
+		        gpio_direction_output(dsi->reset_gpio.gpio,
+                                  dsi->reset_gpio.active_low);
+				mdelay(20);
+	       */
+	//       printk("reset is no control######################\n");
+		//}
+    }
+
+    return ret;
+}
+
+void dsihw_send_short_packet(struct platform_device *pdev,int data_type, int sp_data, int trans_mode)
+{
+	int tmp;	
+	int cnt = 100;
+	DEBUG_DSI("send short start\n");
+	tmp = dsihw_read_reg(pdev,DSI_CTRL);
+	tmp &= 0xffffefff;
+	dsihw_write_reg(pdev,DSI_CTRL, tmp);	
+	
+	dsihw_write_reg(pdev,DSI_PACK_HEADER, sp_data);	
+	
+	tmp = (data_type << 8) | (trans_mode << 14);
+	dsihw_write_reg(pdev,DSI_PACK_CFG, tmp);	
+	mdelay(2);
+	
+	tmp = dsihw_read_reg(pdev,DSI_PACK_CFG);
+	tmp |= 1 ;
+	dsihw_write_reg(pdev,DSI_PACK_CFG, tmp);	
+		
+	while ((!(dsihw_read_reg(pdev, DSI_TR_STA) & (1 << 19))) && --cnt)
+		udelay(2);
+	
+	dsihw_write_reg(pdev,DSI_TR_STA, 0x80000);
+	DEBUG_DSI("send short end\n");
+
+}
+
+void dsihw_send_long_packet(struct platform_device *pdev, int data_type, int word_cnt, int * send_data, int trans_mode)
+{	
+
+	u32 val=0;
+	int tmp,word_cnt_tmp;
+	int cnt = 100;
+	int timeout;
+	DEBUG_DSI("dsihw_send_long_packet pdev %p\n", pdev);
+	if((dma_gl==NULL)||(dma_gl->chan==NULL)){
+		if(dma_init()){
+			pr_err("dma_gl->chan==NULL!!!!\n");
+			return;		
+		}	
+	}
+	
+	tmp = dsihw_read_reg(pdev,DSI_CTRL);
+	tmp &= 0xffffefff;
+	dsihw_write_reg(pdev,DSI_CTRL, tmp);	
+	trans_mode = 0x1;
+
+	word_cnt_tmp=word_cnt%4==0? word_cnt:((word_cnt-word_cnt%4)+4);//Ҫ\C7\F3word\B6\D4\C6\EB	
+	DEBUG_DSI("start dma\n");
+	start_dma(dma_gl, send_data, word_cnt_tmp);
+	DEBUG_DSI("end dma\n");
+		
+	dsihw_write_reg(pdev, DSI_PACK_HEADER,word_cnt);
+	dsihw_write_reg(pdev, DSI_PACK_CFG,(data_type << 8) | 0x40000 | (trans_mode << 14));
+	udelay(15);
+	//msleep(1);
+	tmp = dsihw_read_reg(pdev,DSI_PACK_CFG);
+	DEBUG_DSI("tmp = %x\n", tmp);
+	dsihw_write_reg(pdev,DSI_PACK_CFG, tmp+1);
+
+	//Transmit Complete
+	while ((!(dsihw_read_reg(pdev, DSI_TR_STA) & (1 << 19))) && --cnt)
+		udelay(2);
+	
+	timeout = wait_for_completion_timeout(&dma_gl->dma_complete,msecs_to_jiffies(500));
+    if(timeout==0){
+		printk("err: dma  not done\n");
+	}
+	
+	DEBUG_DSI("Transmit Complete\n");
+	
+	//Clear TCIP
+	val = REG_SET_VAL(val, 1, 19, 19);	
+	
+	dsihw_write_reg(pdev,DSI_TR_STA, val);	
+	
+	dsihw_write_reg(pdev,DSI_TR_STA, 0xfff);
+
+}
+
+static void dsihw_single_enable(struct platform_device *pdev, bool enable)
+{
+	int tmp;
+	if(enable){
+		tmp = dsihw_read_reg(pdev,DSI_VIDEO_CFG);	
+		tmp |= 0x01;
+		dsihw_write_reg(pdev,DSI_VIDEO_CFG, tmp);		
+	}else{
+		tmp = dsihw_read_reg(pdev,DSI_VIDEO_CFG);	
+		tmp &= (~0x01);
+		dsihw_write_reg(pdev,DSI_VIDEO_CFG, tmp);		
+		
+		tmp = dsihw_read_reg(pdev,DSI_PHY_CTRL);
+		tmp &= (~0x01<<24);
+		dsihw_write_reg(pdev,DSI_PHY_CTRL, tmp);
+	}
+
+}
+
+static void dsihw_display_init_dsi(void)
+{
+	struct platform_device *pdev = dsi_pdev_map[0] ;
+	DEBUG_DSI("test dsi pdev %p\n", pdev);
+
+	dsihw_power_enable(pdev, true);
+	dsihw_set_dsi_clk();	
+	dsihw_phy_config(pdev);
+	send_cmd(pdev);
+	dsihw_video_config(pdev);	
+	dsihw_single_enable(pdev, true);
+	DEBUG_DSI("dsihw_display_init_dsi end\n");
+}
+
+static int dsihw_get_clocks(struct platform_device *pdev)
+{
+#if 0	
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	clk = clk_get(&pdev->dev, "lcd");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get fck\n");
+		return PTR_ERR(clk);
+	}
+
+	dsi->dsi_clk = clk;
+#endif 
+	return 0;
+}
+
+static void dsihw_put_clocks(struct platform_device *pdev)
+{
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	if (dsi->dsi_clk)
+		clk_put(dsi->dsi_clk);
+
+}
+
+static int dsihw_parse_gpio(struct device_node *of_node,
+                             const char *propname,
+                             struct owl_dsi_gpio *gpio)
+{
+    enum of_gpio_flags flags;
+    int                gpio_num;
+
+    gpio_num = of_get_named_gpio_flags(of_node, propname, 0, &flags);
+    if (gpio_num >= 0) {
+        gpio->gpio = gpio_num;
+    } else {
+        gpio->gpio = -1;
+    }
+
+    gpio->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+    DEBUG_DSI("%s, gpio = %d\n", __func__, gpio->gpio);
+    DEBUG_DSI("%s, active low = %d\n", __func__, gpio->active_low);
+
+    return 0;
+}
+
+
+static int dsihw_parse_params(struct platform_device *pdev,
+                               struct dsi_data *dsi)
+{
+    struct device_node      *of_node;
+    char                    propname[20];
+    struct device_node      *mode_node;
+	struct owl_dsi_reg    	*reg_val;
+	struct owl_videomode 	*vmode;
+    int                      ret;
+
+    of_node = pdev->dev.of_node;
+
+    /* 
+     * power gpio
+     */
+    dsihw_parse_gpio(of_node, "dsi_power_gpios", &dsi->power_gpio);
+    if (dsi->power_gpio.gpio < 0) {
+        DSSERR("%s, fail to get dsi power gpio\n", __func__);
+    }
+		
+	 /* 
+     * reset gpio
+     */
+    dsihw_parse_gpio(of_node, "dsi_reset_gpios", &dsi->reset_gpio);
+    if (dsi->reset_gpio.gpio < 0) {
+        DSSERR("%s, fail to get lcd reset gpio\n", __func__);
+    }
+
+
+    /* 
+     * interface timing
+     */
+	 
+
+    dsi->port_type = 5;
+
+    if (of_property_read_u32(of_node, "data_width", &dsi->data_width)) {
+        return -EINVAL;
+    }
+    DEBUG_DSI("data_width = %d\n", dsi->data_width);
+	
+    /* 
+     * video mode
+     */
+	sprintf(propname, "hw-set");
+    DEBUG_DSI("propname = %s\n", propname);
+	mode_node = of_parse_phandle(of_node, propname, 0);
+	if (!mode_node) {
+		return -EINVAL;
+	}
+	
+	reg_val = kzalloc(sizeof(struct owl_dsi_reg), GFP_KERNEL);
+	if (!reg_val) {
+        return -EINVAL;
+    }
+
+    if (of_property_read_u32(mode_node, "dsi_ctrl", &reg_val->dsi_ctrl)) {
+		ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_ctrl = %x\n", reg_val->dsi_ctrl);
+	
+	if (of_property_read_u32(mode_node, "dsi_size", &reg_val->dsi_size)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_size = %x\n", reg_val->dsi_size);
+	
+	if (of_property_read_u32(mode_node, "dsi_color", &reg_val->dsi_color)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_color = %x\n", reg_val->dsi_color);
+	
+	if (of_property_read_u32(mode_node, "dsi_rgbht0", &reg_val->dsi_rgbht0)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_rgbht0 = %x\n", reg_val->dsi_rgbht0);
+	
+	if (of_property_read_u32(mode_node, "dsi_rgbht1", &reg_val->dsi_rgbht1)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_rgbht1 = %x\n", reg_val->dsi_rgbht1);
+	
+	if (of_property_read_u32(mode_node, "dsi_rgbvt0", &reg_val->dsi_rgbvt0)) {
+		ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_rgbvt0 = %x\n", reg_val->dsi_rgbvt0);
+	
+	if (of_property_read_u32(mode_node, "dsi_rgbvt1", &reg_val->dsi_rgbvt1)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_rgbvt1 = %x\n", reg_val->dsi_rgbvt1);
+	
+	if (of_property_read_u32(mode_node, "dsi_pack_cfg", &reg_val->dsi_pack_cfg)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_pack_cfg = %x\n", reg_val->dsi_pack_cfg);
+	
+	if (of_property_read_u32(mode_node, "dsi_pack_header", &reg_val->dsi_pack_header)) {
+		ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_pack_header = %x\n", reg_val->dsi_pack_header);
+	
+	if (of_property_read_u32(mode_node, "dsi_vedio_cfg", &reg_val->dsi_vedio_cfg)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_vedio_cfg = %x\n", reg_val->dsi_vedio_cfg);
+	
+	if (of_property_read_u32(mode_node, "dsi_phy_t0", &reg_val->dsi_phy_t0)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_phy_t0 = %x\n", reg_val->dsi_phy_t0);
+	
+	if (of_property_read_u32(mode_node, "dsi_phy_t1", &reg_val->dsi_phy_t1)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_phy_t1 = %x\n", reg_val->dsi_phy_t1);
+	
+	if (of_property_read_u32(mode_node, "dsi_phy_t2", &reg_val->dsi_phy_t2)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_phy_t2 = %x\n", reg_val->dsi_phy_t2);
+	
+	if (of_property_read_u32(mode_node, "dsi_phy_ctrl", &reg_val->dsi_phy_ctrl)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_phy_ctrl = %x\n", reg_val->dsi_phy_ctrl);
+	
+	if (of_property_read_u32(mode_node, "dsi_pin_map", &reg_val->dsi_pin_map)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("dsi_pin_map = %x\n", reg_val->dsi_pin_map);
+	
+	if (of_property_read_u32(mode_node, "cmu_dsipll_clk", &reg_val->cmu_dsipll_clk)) {
+        ret = -EINVAL;
+        goto parse_reg_fail;
+    }
+    DEBUG_DSI("cmu_dsipll_clk = %x\n", reg_val->cmu_dsipll_clk);
+	
+	dsi->regs         = reg_val;
+	
+    /* get  mode */
+	sprintf(propname, "videomode-0");
+    DEBUG_DSI("propname = %s\n", propname);
+	mode_node = of_parse_phandle(of_node, propname, 0);
+	if (!mode_node) {
+		return -EINVAL;
+	}
+	
+    /* alloc memory */
+    vmode = kzalloc(sizeof(struct owl_videomode), GFP_KERNEL);
+    if (!vmode) {
+        return -EINVAL;
+    }
+
+	if (of_property_read_u32(mode_node, "refresh", &vmode->refresh)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("refresh = %d\n", vmode->refresh);
+
+	if (of_property_read_u32(mode_node, "xres", &vmode->xres)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("xres = %d\n", vmode->xres);
+
+	if (of_property_read_u32(mode_node, "yres", &vmode->yres)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("yres = %d\n", vmode->yres);
+
+	if (of_property_read_u32(mode_node, "pixclock", &vmode->pixclock)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("pixclock = %d\n", vmode->pixclock);
+
+	if (of_property_read_u32(mode_node, "left_margin", &vmode->left_margin)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("left_margin = %d\n", vmode->left_margin);
+
+	if (of_property_read_u32(mode_node, "right_margin", &vmode->right_margin)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("right_margin = %d\n", vmode->right_margin);
+
+	if (of_property_read_u32(mode_node, "upper_margin", &vmode->upper_margin)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("upper_margin = %d\n", vmode->upper_margin);
+
+	if (of_property_read_u32(mode_node, "lower_margin", &vmode->lower_margin)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("lower_margin = %d\n", vmode->lower_margin);
+
+	if (of_property_read_u32(mode_node, "hsync_len", &vmode->hsync_len)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("hsync_len = %d\n", vmode->hsync_len);
+
+	if (of_property_read_u32(mode_node, "vsync_len", &vmode->vsync_len)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("vsync_len = %d\n", vmode->vsync_len);
+
+	if (of_property_read_u32(mode_node, "vmode", &vmode->vmode)) {
+		ret = -EINVAL;
+		goto parse_mode_fail;
+	}
+	DEBUG_DSI("vmode = %d\n", vmode->vmode);
+  
+    dsi->modes         = vmode;
+
+    return 0;
+
+parse_mode_fail:
+    kfree(vmode);
+parse_reg_fail:
+	kfree(reg_val);
+    return ret;
+}
+
+void owl_dsi_select_video_timings(struct owl_dss_device *dssdev, u32 num,
+                                   struct owl_video_timings *timings)
+{
+
+    struct platform_device *pdev = dsi_pdev_map[0] ;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+    struct owl_videomode *mode = dsi->modes;
+
+    timings->x_res          = mode->xres;
+    timings->y_res          = mode->yres;
+    timings->pixel_clock    = PICOS2KHZ(mode->pixclock);
+    timings->hfp            = mode->left_margin;
+    timings->hbp            = mode->right_margin;
+    timings->vfp            = mode->upper_margin;
+    timings->vbp            = mode->lower_margin;
+    timings->hsw            = mode->hsync_len;
+    timings->vsw            = mode->vsync_len;
+	
+	timings->data_width     = 24;
+	switch(dsi->data_width){
+		case 0:
+		timings->data_width     = 24;
+		break;
+		case 1:
+		timings->data_width     = 18;
+		break;
+		case 2:
+		timings->data_width     = 16;
+		break;
+	}
+	
+    return;
+}
+
+static bool dsihw_check_boot_dsi_inited(struct platform_device *pdev) {
+
+	boot_dsi_inited = dsihw_read_reg(pdev,DSI_VIDEO_CFG)&0x01;	
+	
+    return boot_dsi_inited;
+}
+
+
+int owl_dsi_display_enable(struct owl_dss_device *dssdev)
+{
+	int r=0;
+    struct platform_device *pdev = dsi_pdev_map[0] ;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	mutex_lock(&dsi->lock);
+
+	if (dssdev->manager == NULL) {
+		DSSERR("failed to enable display: no manager\n");
+		goto err_start_dev;
+	}
+	
+	r = owl_dss_start_device(dssdev);	
+	if (r) {
+		DSSERR("failed to start device\n");
+		goto err_start_dev;
+	}
+	
+	r = dss_mgr_enable(dssdev->manager);
+	
+	if (r)
+		goto err_mgr_enable;
+		
+	
+	if(!dsihw_check_boot_dsi_inited(pdev)){
+		dsihw_display_init_dsi();	
+		dsihw_single_enable(pdev,true);	
+		
+	}
+	
+	mutex_unlock(&dsi->lock);
+
+	DEBUG_DSI("gl++++owl_dsi_display_enable end\n");	
+	return 0;
+	
+err_mgr_enable:
+err_start_dev:
+	mutex_unlock(&dsi->lock);
+	return r;
+}
+
+void owl_dsi_display_disable(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct platform_device *pdev = dsi_pdev_map[0] ;
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+	
+	dsihw_single_enable(pdev,false);	
+	
+	dss_mgr_disable(dssdev->manager);
+
+	if(dsi->dsi_power){
+		r = regulator_disable(dsi->dsi_power);
+		if (r){
+		}
+	}
+	
+	dsihw_power_enable(pdev, false);
+
+	owl_dss_stop_device(dssdev);
+}
+
+void io_map(void)
+{
+	cmu_dsipll_clk = ioremap(0xb0160028, 4);	
+	reg_sps_ldo_ctl  = ioremap(0xb01b0108, 4);
+}
+
+/* DSI HW IP initialisation */
+static int owl_dsihw_probe(struct platform_device *pdev)
+{
+	int r;
+	struct resource *dsi_mem;
+	struct dsi_data *dsi;
+	printk("owl_dsihw_probe\n");
+	
+
+	DEBUG_DSI("owl_dsihw_probe called \n");
+	dsi = kzalloc(sizeof(*dsi), GFP_KERNEL);
+	if (!dsi) {
+		r = -ENOMEM;
+		goto err_alloc;
+	}
+
+	dsi->pdev = pdev;
+	dsi_pdev_map[0] = pdev;
+	dev_set_drvdata(&pdev->dev, dsi);
+	
+	io_map();
+
+	mutex_init(&dsi->lock);
+
+	r = dsihw_get_clocks(pdev);
+	if (r)
+		goto err_get_clk;
+
+	pm_runtime_enable(&pdev->dev);
+
+	dsi_mem = platform_get_resource(dsi->pdev, IORESOURCE_MEM, 0);
+	
+	if (!dsi_mem) {
+		DSSERR("can't get IORESOURCE_MEM DSI\n");
+		r = -EINVAL;
+		goto err_ioremap;
+	}	
+	
+	dsi->base = ioremap(dsi_mem->start, resource_size(dsi_mem));
+	if (!dsi->base) {
+		DSSERR("can't ioremap dsi \n");
+		r = -ENOMEM;
+		goto err_ioremap;
+	}
+	DEBUG_DSI("dsi_mem->start  ~~~ %x  resource_size %x\n",dsi_mem->start, resource_size(dsi_mem));	
+	DEBUG_DSI("dsi->base  ~~~ %p \n",dsi->base);	
+	
+	owl_dsi_create_sysfs(&pdev->dev);	
+
+    r = dsihw_parse_params(pdev, dsi);
+    if (r) {
+        DSSERR("%s, parse dsi params error\n", __func__);
+        goto err_parse_params;
+    }
+
+    /*
+     * configure gpio
+     */
+    if (gpio_is_valid(dsi->power_gpio.gpio)) {
+        r = gpio_request(dsi->power_gpio.gpio, NULL);
+        if (r) {
+            DSSERR("%s, request power gpio failed\n", __func__);
+            goto err_parse_params;
+        }
+    } 
+    if (gpio_is_valid(dsi->reset_gpio.gpio)) {
+        r = gpio_request(dsi->reset_gpio.gpio, NULL);
+        if (r) {
+            DSSERR("%s, request reset_gpio failed\n", __func__);
+            goto err_parse_params;
+        }
+    } 
+	
+    dsi->dsi_power = regulator_get(&pdev->dev, POWER_REGULATOR_NAME);
+    if (IS_ERR(dsi->dsi_power)) {
+        dsi->dsi_power = NULL;
+    }
+    DEBUG_DSI("%s, dsi_power: %p\n", __func__, dsi->dsi_power);
+
+	if(!dsihw_check_boot_dsi_inited(pdev)){
+		dsihw_display_init_dsi();
+	}
+	
+    DSSINFO("owl_dsihw_probe called  ok ~~~~~~~~~~~~~\n");
+    return 0;
+
+err_parse_params:
+	iounmap(dsi->base);
+err_ioremap:
+	pm_runtime_disable(&pdev->dev);
+err_get_clk:
+	kfree(dsi);
+err_alloc:
+	return r;
+}
+
+static int owl_dsihw_remove(struct platform_device *pdev)
+{
+	struct dsi_data *dsi = dsihw_get_dsidrv_data(pdev);
+
+	pm_runtime_disable(&pdev->dev);
+
+	dsihw_put_clocks(pdev);
+
+	if (dsi->dsi_power != NULL) {
+		regulator_put(dsi->dsi_power);
+		dsi->dsi_power = NULL;
+	}
+
+	iounmap(dsi->base);
+
+	kfree(dsi);
+
+    dsi->dsi_enabled = false;
+    return 0;
+}
+
+static struct of_device_id owl_dsihw_of_match[] = {
+    { .compatible = "actions,owl-dsi", },
+    { },
+};
+
+
+static struct platform_driver owl_dsi_driver = {
+    .driver = {
+        .name           = "owl_dsihw",
+        .owner          = THIS_MODULE,
+        .of_match_table = owl_dsihw_of_match,
+    },
+    .probe              = owl_dsihw_probe,
+    .remove             = owl_dsihw_remove,
+};
+
+int owl_dsi_init_platform(void)
+{
+    int ret = 0;
+	
+   if (owl_get_boot_mode() == OWL_BOOT_MODE_UPGRADE) {
+		printk("product process  not need to DSI modules!\n");
+		return -1;
+	}
+    ret = platform_driver_register(&owl_dsi_driver);
+    
+    if (ret) {
+        DSSERR("Failed to initialize dsi platform driver\n");
+        return ret;
+    }
+    return 0;
+}
+
+int owl_dsi_uninit_platform(void)
+{   
+    platform_driver_unregister(&owl_dsi_driver);
+    
+    return 0;
+}
+
+void dsihw_fs_dump_regs(struct device *dev)
+{
+	
+	struct dsi_data * data = dev_get_drvdata(dev);
+	dsihw_dump_regs(data->pdev);
+
+}
+
+void test_fs_dsi(struct device *dev)
+{
+	struct platform_device *pdev = dsi_pdev_map[0] ;
+	dsihw_single_enable(pdev,false);	
+	dsihw_display_init_dsi();
+}
+
+void test_fs_longcmd(struct device *dev)
+{
+	struct dsi_data * data = dev_get_drvdata(dev);
+	send_cmd_test(data->pdev);
+}
+
diff --git a/drivers/video/fbdev/owl/displays/dsi/dsihw.h b/drivers/video/fbdev/owl/displays/dsi/dsihw.h
new file mode 100755
index 0000000..1ca55cb
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/dsihw.h
@@ -0,0 +1,141 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/lcdchw.h
+ *
+ * Copyright (C) 2011 Actions
+ * Author: Hui Wang <wanghui at actions-semi.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __OWL_DSIHW_H
+#define __OWL_DSIHW_H
+
+#include <linux/platform_device.h>
+#include <video/owldss.h>
+
+
+#define GL5206
+
+#ifdef GL5209
+
+	#define    DSIHW_REG_MEM_BASE                                                0xb0220000
+	#define    DSIHW_REG_MEM_END                                                 0xb022008a
+	
+	#define     DSI_CTRL                                                          (0x0000)
+	#define     DSI_SIZE                                                          (0x0004)
+	#define     DSI_COLOR                                                         (0x0008)
+	#define     DSI_VIDEO_CFG                                                     (0x000C)
+	#define     DSI_RGBHT0                                                        (0x0010)
+	#define     DSI_RGBHT1                                                        (0x0014)
+	#define     DSI_RGBVT0                                                        (0x0018)
+	#define     DSI_RGBVT1                                                        (0x001c)
+	#define     DSI_TIMEOUT                                                       (0x0020)
+	#define     DSI_TR_STA                                                        (0x0024)
+	#define     DSI_INT_EN                                                        (0x0028)
+	#define     DSI_ERROR_REPORT                                                  (0x002c)
+	#define     DSI_FIFO_ODAT                                                     (0x0030)
+	#define     DSI_FIFO_IDAT                                                     (0x0034)
+	#define     DSI_IPACK                                                         (0x0038)
+	#define     DSI_PACK_CFG                                                      (0x0040)
+	#define     DSI_PACK_HEADER                                                   (0x0044)
+	#define     DSI_TX_TRIGGER                                                    (0x0048)
+	#define     DSI_RX_TRIGGER                                                    (0x004c)
+	#define     DSI_LANE_CTRL                                                     (0x0050)
+	#define     DSI_LANE_STA                                                      (0x0054)
+	#define     DSI_PHY_T0                                                        (0x0060)
+	#define     DSI_PHY_T1                                                        (0x0064)
+	#define     DSI_PHY_T2                                                        (0x0068)
+	#define     DSI_APHY_DEBUG0                                                   (0x0070)
+	#define     DSI_APHY_DEBUG1                                                   (0x0074)
+	#define     DSI_SELF_TEST                                                     (0x0078)
+	#define     DSI_LANE_SWAP                                                     (0x007c)
+	#define     DSI_PHY_CTRL                                                      (0x0080)
+	#define     DSI_FT_TEST                                                       (0x0088)
+			
+#endif
+
+
+#ifdef GL5206
+
+	#define    DSIHW_REG_MEM_BASE                                                0xb0220000
+	#define    DSIHW_REG_MEM_END                                                 0xb022008a
+	
+	#define     DSI_CTRL                                                          (0x0000)
+	#define     DSI_SIZE                                                          (0x0004)
+	#define     DSI_COLOR                                                         (0x0008)
+	#define     DSI_VIDEO_CFG                                                     (0x000C)
+	#define     DSI_RGBHT0                                                        (0x0010)
+	#define     DSI_RGBHT1                                                        (0x0014)
+	#define     DSI_RGBVT0                                                        (0x0018)
+	#define     DSI_RGBVT1                                                        (0x001c)
+	#define     DSI_TIMEOUT                                                       (0x0020)
+	#define     DSI_TR_STA                                                        (0x0024)
+	#define     DSI_INT_EN                                                        (0x0028)
+	#define     DSI_ERROR_REPORT                                                  (0x002c)
+	#define     DSI_FIFO_ODAT                                                     (0x0030)
+	#define     DSI_FIFO_IDAT                                                     (0x0034)
+	#define     DSI_IPACK                                                         (0x0038)
+	#define     DSI_PACK_CFG                                                      (0x0040)
+	#define     DSI_PACK_HEADER                                                   (0x0044)
+	#define     DSI_TX_TRIGGER                                                    (0x0048)
+	#define     DSI_RX_TRIGGER                                                    (0x004c)
+	#define     DSI_LANE_CTRL                                                     (0x0050)
+	#define     DSI_LANE_STA                                                      (0x0054)
+	#define     DSI_PHY_T0                                                        (0x0060)
+	#define     DSI_PHY_T1                                                        (0x0064)
+	#define     DSI_PHY_T2                                                        (0x0068)
+	#define     DSI_APHY_DEBUG0                                                   (0x0070)
+	#define     DSI_APHY_DEBUG1                                                   (0x0074)
+	#define     DSI_SELF_TEST                                                     (0x0078)
+	#define     DSI_PIN_MAP                                                    	  (0x007c)
+	#define     DSI_PHY_CTRL                                                      (0x0080)
+	#define     DSI_FT_TEST                                                       (0x0088)	
+	
+	
+	
+	#define    DMA_REG_MEM_BASE                                                0xB0260000
+	#define    DMA_REG_MEM_END                                                 0xB0260c00	
+	#define    n   4
+	
+	#define    DMA_IRQ_PD0                                                		(0x0000)	
+	
+	#define     DMA0_BASE                                                         0x0100
+	#define     DMA0_MODE                                                         (DMA0_BASE*n+0x0000)
+	#define     DMA0_SOURCE                                                       (DMA0_BASE*n+0x0004)
+	#define     DMA0_DESTINATION                                                  (DMA0_BASE*n+0x0008)
+	#define     DMA0_FRAME_LEN                                                    (DMA0_BASE*n+0x000C)
+	#define     DMA0_FRAME_CNT                                                    (DMA0_BASE*n+0x0010)
+	#define     DMA0_REMAIN_FRAME_CNT                                             (DMA0_BASE*n+0x0014)
+	#define     DMA0_REMAIN_CNT                                                   (DMA0_BASE*n+0x0018)
+	#define     DMA0_SOURCE_STRIDE                                                (DMA0_BASE*n+0x001C)
+	#define     DMA0_DESTINATION_STRIDE                                           (DMA0_BASE*n+0x0020)
+	#define     DMA0_START                                                        (DMA0_BASE*n+0x0024)
+	#define     DMA0_PAUSE                                                        (DMA0_BASE*n+0x0028)
+	#define     DMA0_CHAINED_CTL                                                  (DMA0_BASE*n+0x002C)
+	#define     DMA0_CONSTANT                                                     (DMA0_BASE*n+0x0030)
+	#define     DMA0_LINKLIST_CTL                                                 (DMA0_BASE*n+0x0034)
+	#define     DMA0_NEXT_DESCRIPTOR                                              (DMA0_BASE*n+0x0038)
+	#define     DMA0_CURRENT_DESCRIPTOR_NUM                                       (DMA0_BASE*n+0x003C)
+	#define     DMA0_INT_CTL                                                      (DMA0_BASE*n+0x0040)
+	#define     DMA0_INT_STATUS                                                   (DMA0_BASE*n+0x0044)
+	#define     DMA0_CURRENT_SOURCE_POINTER                                       (DMA0_BASE*n+0x0048)
+	#define     DMA0_CURRENT_DESTINATION_POINTER                                  (DMA0_BASE*n+0x004C)
+
+#endif
+
+#ifdef GL5203
+	
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/dsi/panel-mipi.c b/drivers/video/fbdev/owl/displays/dsi/panel-mipi.c
new file mode 100755
index 0000000..a51cea6
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/dsi/panel-mipi.c
@@ -0,0 +1,251 @@
+/*
+ * Generic EDP Panels support
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu at canonical.com>
+ *
+ * LCD panel driver for Sharp LQ043T1DG01
+ *
+ * Copyright (C) 2009 Actions Inc
+ * Author: Vaibhav Hiremath <hvaibhav at ti.com>
+ *
+ * LCD panel driver for Toppoly TDO35S
+ *
+ * Copyright (C) 2009 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike at compulab.co.il>
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <video/owldss.h>
+
+#include "dsi.h"
+
+struct panel_config {
+	struct owl_video_timings timings;
+
+	//enum owl_panel_config config;
+
+	int power_on_delay;
+	
+	int power_off_delay;
+
+	/*
+	 * Used to match device to panel configuration
+	 * when use generic panel driver
+	 */
+	const char *name;
+
+	int (*platform_enable)(struct owl_dss_device *dssdev);
+	
+	void (*platform_disable)(struct owl_dss_device *dssdev);
+};
+
+/* Panel configurations */
+static struct panel_config generic_dsi_panels[] = {
+	/* fpga rgb lcd  */
+	{
+		{
+			.x_res		= 800,
+			.y_res		= 480,
+
+			.pixel_clock	= 9000,
+
+			.hsw		= 28,
+			.hfp		= 20,
+			.hbp		= 80,
+
+			.vsw		= 3,
+			.vfp		= 13,
+			.vbp		= 32,
+		},
+
+		//.config			= OWL_DSS_LCD_TFT,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "sharp_lq",
+	},	
+};
+
+struct panel_drv_data {
+
+	struct owl_dss_device *dssdev;
+
+	struct panel_config *panel_config;
+};
+
+extern enum owl_display_type get_current_display_type(void);
+
+static int generic_dsi_panel_power_on(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE)
+		return 0;
+
+	r = owl_dsi_display_enable(dssdev);
+	
+	if (r)
+		goto err0;
+
+	/* wait couple of vsyncs until enabling the LCD */
+	if (panel_config->power_on_delay)
+		msleep(panel_config->power_on_delay);
+
+	if (panel_config->platform_enable) {
+		r = panel_config->platform_enable(dssdev);
+		if (r)
+			goto err1;
+	}
+
+	return 0;
+err1:
+	owl_dsi_display_disable(dssdev);
+err0:
+	return r;
+}
+
+static void generic_dsi_panel_power_off(struct owl_dss_device *dssdev)
+{
+
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state != OWL_DSS_DISPLAY_ACTIVE)
+		return;
+
+	if (panel_config->platform_disable)
+		panel_config->platform_disable(dssdev);
+
+	/* wait couple of vsyncs after disabling the LCD */
+	if (panel_config->power_off_delay)
+		msleep(panel_config->power_off_delay);
+
+	owl_dsi_display_disable(dssdev);
+}
+
+static int generic_dsi_panel_probe(struct owl_dss_device *dssdev)
+{
+
+	struct panel_config *panel_config = NULL;
+	struct panel_drv_data *drv_data = NULL;
+
+	dev_dbg(&dssdev->dev, "probe\n");
+
+    panel_config = &generic_dsi_panels[0];
+    
+	if (!panel_config)
+		return -EINVAL;
+		
+	owl_dsi_select_video_timings(dssdev, 0, &panel_config->timings);
+
+	dssdev->timings = panel_config->timings;
+
+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	drv_data->dssdev = dssdev;
+	drv_data->panel_config = panel_config;
+
+	dev_set_drvdata(&dssdev->dev, drv_data);
+
+	return 0;
+}
+
+static void __exit generic_dsi_panel_remove(struct owl_dss_device *dssdev)
+{
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	dev_dbg(&dssdev->dev, "remove\n");
+
+	kfree(drv_data);
+
+	dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+extern void owl_backlight_set_onoff(int onoff);
+static int generic_dsi_panel_enable(struct owl_dss_device *dssdev)
+{
+	int r = 0;
+
+	r = generic_dsi_panel_power_on(dssdev);
+	if (r)
+		return r;
+
+	dssdev->state = OWL_DSS_DISPLAY_ACTIVE;
+
+	/* at last enable backlight */
+	owl_backlight_set_onoff(1);
+	
+	return 0;
+}
+
+static void generic_dsi_panel_disable(struct owl_dss_device *dssdev)
+{
+	/* disable backlight first */
+    owl_backlight_set_onoff(0);
+		msleep(10);
+	generic_dsi_panel_power_off(dssdev);
+
+	dssdev->state = OWL_DSS_DISPLAY_DISABLED;
+}
+
+static void generic_dsi_panel_get_timings(struct owl_dss_device *dssdev, struct owl_video_timings *timings)
+{
+	*timings = dssdev->timings;
+}
+
+static struct owl_dss_driver dsi_driver = {
+	.probe		= generic_dsi_panel_probe,
+	.remove		= __exit_p(generic_dsi_panel_remove),
+
+	.enable		= generic_dsi_panel_enable,
+	.disable	= generic_dsi_panel_disable,
+	.get_timings	= generic_dsi_panel_get_timings,
+
+
+	.driver         = {
+		.name   = "generic_dsi_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init generic_dsi_panel_drv_init(void)
+{
+	printk("generic_dsi_panel_drv_init \n");
+	owl_dsi_init_platform();
+	if(get_current_display_type()==OWL_DISPLAY_TYPE_DSI){
+		printk("current type dsi \n");
+		owl_dss_register_driver(&dsi_driver);
+	}
+	return 0;
+}
+
+static void __exit generic_dsi_panel_drv_exit(void)
+{
+	owl_dss_unregister_driver(&dsi_driver);
+	owl_dsi_uninit_platform();
+}
+
+module_init(generic_dsi_panel_drv_init);
+module_exit(generic_dsi_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/displays/edp/edphw.c b/drivers/video/fbdev/owl/displays/edp/edphw.c
new file mode 100755
index 0000000..4bd71ad
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/edp/edphw.c
@@ -0,0 +1,709 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/edp.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "EDP"
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "../owldss.h"
+#include "../dss/dss_features.h"
+#include "../dss/dss.h"
+#include "edphw.h"
+
+struct edp_data {
+	
+	struct platform_device * pdev;
+	
+	struct regulator *edp_power;
+	
+	bool edp_power_enabled;
+	
+	struct mutex lock;
+	
+	struct owl_dss_device *dssdev;
+	
+	struct clk *edp_clk;
+	
+	int (*enable_pads)(int edp_id, unsigned lane_mask);
+	
+	void (*disable_pads)(int edp_id, unsigned lane_mask);
+		
+	void __iomem	*base;
+	
+};
+
+static struct platform_device *edp_pdev_map[MAX_NUM_LCD];
+
+inline struct edp_data *edphw_get_edpdrv_data(struct platform_device *edpdev)
+{
+	return dev_get_drvdata(&edpdev->dev);
+}
+
+inline void edphw_write_reg(struct platform_device *edpdev,const u16 index, u32 val)
+{
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+	DSSDBG("edphw_write_reg  ~~~ %p index %d\n",edp->base,index);
+	writel(val, edp->base + index);
+}
+
+inline u32 edphw_read_reg(struct platform_device *edpdev,const u16 index)
+{
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+	DSSDBG("edphw_read_reg  ~~~ %p index %d\n",edp->base,index);
+	return readl(edp->base + index);
+}
+
+void edphw_dump_regs(struct platform_device *edpdev){
+	
+#define DUMPREG(r) DSSDBG("%08x ~~ %08x\n",r,edphw_read_reg(edpdev,r))
+     DUMPREG(EDP_LNK_LANE_COUNT);
+     DUMPREG(EDP_LNK_ENHANCED);
+     DUMPREG(EDP_LNK_TRAP);
+     DUMPREG(EDP_LNK_QUAL_PAT);
+     DUMPREG(EDP_LNK_SCR_CTRL);
+     DUMPREG(EDP_LNK_DSPR_CTRL);
+     DUMPREG(EDP_LNK_SCR_RST);
+     DUMPREG(EDP_LNK_PANEL_SRF);
+     
+     DUMPREG(EDP_CORE_TX_EN);
+     DUMPREG(EDP_CORE_MSTREAM_EN);
+     DUMPREG(EDP_CORE_SSTREAM_EN);
+     DUMPREG(EDP_CORE_FSCR_RST);     
+     DUMPREG(EDP_CORE_USER_CFG);
+     DUMPREG(EDP_CORE_CAPS);
+     DUMPREG(EDP_CORE_ID);
+     
+     DUMPREG(EDP_AUX_COMD);
+     DUMPREG(EDP_AUX_WR_FIFO);
+     DUMPREG(EDP_AUX_ADDR);
+     DUMPREG(EDP_AUX_CLK_DIV);
+     DUMPREG(EDP_AUX_STATE);
+     DUMPREG(EDP_AUX_RPLY_DAT);
+     DUMPREG(EDP_AUX_RPLY_CODE);
+     DUMPREG(EDP_AUX_RPLY_COUNT);
+     DUMPREG(EDP_AUX_INT_STAT);         
+     DUMPREG(EDP_AUX_INT_MASK);
+     DUMPREG(EDP_AUX_RPLY_DAT_CNT);
+     DUMPREG(EDP_AUX_STATUS);
+     DUMPREG(EDP_AUX_RCLK_WIDTH);
+     
+     DUMPREG(EDP_MSTREAM_HTOTAL);
+     DUMPREG(EDP_MSTREAM_VTOTAL);
+     DUMPREG(EDP_MSTREAM_POLARITY);
+     DUMPREG(EDP_MSTREAM_HSWIDTH);
+     DUMPREG(EDP_MSTREAM_VSWIDTH);
+     DUMPREG(EDP_MSTREAM_HRES);
+     DUMPREG(EDP_MSTREAM_VRES);
+     DUMPREG(EDP_MSTREAM_HSTART);     
+     DUMPREG(EDP_MSTREAM_VSTART);
+     DUMPREG(EDP_MSTREAM_MISC0);
+     DUMPREG(EDP_MSTREAM_MISC1);
+     DUMPREG(EDP_M_VID);
+     DUMPREG(EDP_N_VID);
+     DUMPREG(EDP_USER_PIXEL_WIDTH);
+     DUMPREG(EDP_USER_DATA_COUNT);
+     DUMPREG(EDP_MSTREAM_INTERLACED);
+     DUMPREG(EDP_USER_SYNC_POLARITY);
+     
+     DUMPREG(EDP_PHY_RESET);
+     DUMPREG(EDP_PHY_PREEM_L0);
+     DUMPREG(EDP_PHY_PREEM_L1);
+     DUMPREG(EDP_PHY_PREEM_L2);
+     DUMPREG(EDP_PHY_PREEM_L3);
+     DUMPREG(EDP_PHY_VSW_L0);
+     DUMPREG(EDP_PHY_VSW_L1);
+     DUMPREG(EDP_PHY_VSW_L2);
+     DUMPREG(EDP_PHY_VSW_L3);
+     DUMPREG(EDP_PHY_VSW_AUX);
+     DUMPREG(EDP_PHY_PWR_DOWN);     
+     DUMPREG(EDP_PHY_CAL_CONFIG);
+     DUMPREG(EDP_PHY_CAL_CTRL);
+     DUMPREG(EDP_PHY_CTRL);
+
+     DUMPREG(EDP_SDB_LANE_SELECT);
+     DUMPREG(EDP_SDB_WRITE_INDEX);     
+     DUMPREG(EDP_SDB_DATA_COUNT);
+     DUMPREG(EDP_SDB_DATA);
+     DUMPREG(EDP_SDB_READY);     
+     DUMPREG(EDP_SDB_BUSY);
+     
+     DUMPREG(EDP_RGB_CTL);     
+     DUMPREG(EDP_RGB_STATUS);
+     DUMPREG(EDP_RGB_COLOR);
+     DUMPREG(EDP_DEBUG);
+
+}
+
+static int edphw_enable_pads(int dsi_id, unsigned lane_mask)
+{
+
+	return 0;
+}
+
+static void edphw_disable_pads(int dsi_id, unsigned lane_mask)
+{
+
+}
+
+static int edphw_set_edp_clk(struct platform_device *edpdev, bool is_tft,unsigned long pck_req, unsigned long *fck, int *lck_div,
+		int *pck_div)
+{
+	return 0;
+}
+
+static void edphw_aux_write(struct platform_device *edpdev, u16 addr,u16 data)
+{
+	u32 temp;
+	
+	edphw_write_reg(edpdev,EDP_AUX_ADDR,addr);
+	
+	edphw_write_reg(edpdev,EDP_AUX_WR_FIFO,data);	
+	
+	edphw_write_reg(edpdev,EDP_AUX_COMD,0x08<<8); //aux write, 1byte
+	
+	do{
+		temp = edphw_read_reg(edpdev,EDP_AUX_STATE);	
+		
+	}while(temp&(1<<1));		//if 1, request is in progress
+	
+	temp =edphw_read_reg(edpdev,EDP_AUX_RPLY_CODE);	
+}	
+
+static u16 edphw_aux_read(struct platform_device *edpdev,u16 addr)
+{
+	u32 temp;
+	
+	edphw_write_reg(edpdev,EDP_AUX_ADDR,addr);
+	
+	edphw_write_reg(edpdev,EDP_AUX_COMD,0x09<<8); //aux read, 1byte
+	
+	do{
+		
+		temp = edphw_read_reg(edpdev,EDP_AUX_STATE);	
+		
+	}while(!(temp&(1<<2)));		//if 1, reply is in progress
+	
+	temp = edphw_read_reg(edpdev,EDP_AUX_RPLY_CODE);	
+	temp = edphw_read_reg(edpdev,EDP_AUX_RPLY_COUNT);	
+	temp = edphw_read_reg(edpdev,EDP_AUX_RPLY_DAT_CNT);	
+	temp = edphw_read_reg(edpdev,EDP_AUX_RPLY_DAT);	
+	
+	return(temp);
+}
+
+
+static void edphw_set_size(struct platform_device *edpdev, u16 width, u16 height)
+{
+	u32 val;
+	
+	BUG_ON((width > (1 << 14)) || (height > (1 << 14)));
+	
+	val = REG_VAL(width, 14, 0);
+	
+	edphw_write_reg(edpdev,EDP_MSTREAM_HRES, val);
+	
+	val = REG_VAL(height, 14, 0);
+	
+	edphw_write_reg(edpdev,EDP_MSTREAM_VRES, val);
+}
+
+static void edphw_set_timings(struct platform_device *edpdev,u16 width, u16 height, u16 hbp ,u16 hfp, u16 hsw, u16 vbp ,u16 vfp, u16 vsw)
+{	
+
+	BUG_ON((hbp > (1 << 15)) || (hfp > (1 << 15)) || (hsw > (1 << 15)));	
+	
+	BUG_ON((vbp > (1 << 15)) || (vfp > (1 << 15)) || (vsw > (1 << 15)));
+	   
+    edphw_write_reg(edpdev,EDP_MSTREAM_HSWIDTH, hsw);    
+    edphw_write_reg(edpdev,EDP_MSTREAM_HSTART, hbp);
+    edphw_write_reg(edpdev,EDP_MSTREAM_HTOTAL, hsw + hbp + width + hfp);
+    	
+	edphw_write_reg(edpdev,EDP_MSTREAM_VSWIDTH, vsw);    
+    edphw_write_reg(edpdev,EDP_MSTREAM_VSTART, vbp);
+    edphw_write_reg(edpdev,EDP_MSTREAM_VTOTAL, vsw + vbp + height + vfp);    
+	
+}
+
+static void edphw_phy_config(struct platform_device *edpdev)
+{	
+	   
+    edphw_write_reg(edpdev,EDP_PHY_PREEM_L0, 0);    
+    edphw_write_reg(edpdev,EDP_PHY_PREEM_L1, 0);
+    edphw_write_reg(edpdev,EDP_PHY_PREEM_L2, 0);
+    edphw_write_reg(edpdev,EDP_PHY_PREEM_L3, 0);
+    
+    edphw_write_reg(edpdev,EDP_PHY_VSW_L0, 0);    
+    edphw_write_reg(edpdev,EDP_PHY_VSW_L1, 0);
+    edphw_write_reg(edpdev,EDP_PHY_VSW_L2, 0);
+    edphw_write_reg(edpdev,EDP_PHY_VSW_L3, 0);
+    	
+	edphw_write_reg(edpdev,EDP_PHY_VSW_AUX, 0);//set the aux channel voltage swing 400mV	
+	
+	edphw_write_reg(edpdev,EDP_PHY_CTRL, 0); //set no Mirror,polarity not changed
+	
+}
+static void edphw_link_config(struct platform_device *edpdev)
+{	
+	edphw_write_reg(edpdev,EDP_AUX_CLK_DIV,24);	//set aux clock 1MHz;
+	edphw_write_reg(edpdev,EDP_LNK_LANE_COUNT,0x01);	//set 1 lane	
+	edphw_write_reg(edpdev,EDP_LNK_SCR_RST,0x00);		//eDP enable, use only for embedded application		
+	edphw_write_reg(edpdev,EDP_LNK_SCR_CTRL,0x00);	//enable internal scramble	
+}
+static void edphw_link_training(struct platform_device *edpdev)
+{	
+	u32 temp ;   
+    edphw_aux_write(edpdev,0x100,0x06);	//1.62G
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x100);
+	mdelay(50);
+	edphw_aux_write(edpdev,0x101,0x01);	//1 lane
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x101);
+	mdelay(50);
+	
+	edphw_aux_write(edpdev,0x102,0x01 | (1<<5));		//set Sink training pattern, disable scramble
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x102);
+		
+	edphw_aux_write(edpdev,0x103,0x00);	//lane0 level 3,1.0V
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x103);
+
+   //source config	
+	//edphw_aux_write(edpdev,CMU_EDPCLK,0x70300|0);	//0:1.62G; 1:2.7G ; 4:5.4G
+	edphw_aux_write(edpdev,EDP_LNK_TRAP,1);					
+	edphw_aux_write(edpdev,EDP_LNK_SCR_CTRL,0x01);	//disable internal scramble
+	mdelay(50);
+
+	temp=edphw_aux_read(edpdev,0x202);
+
+   //pattern2	
+	edphw_aux_write(edpdev,0x102,2|(1<<5));		//set Sink training pattern, disable scramble
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x102);
+    edphw_write_reg(edpdev,EDP_LNK_TRAP,2);				//pattern2	
+
+	mdelay(50);
+
+	temp=edphw_aux_read(edpdev,0x202);
+
+	edphw_aux_write(edpdev,0x102,0x00);		//no training pattern now,enable scramble
+	mdelay(50);
+	temp=edphw_aux_read(edpdev,0x102);
+	
+	edphw_write_reg(edpdev,EDP_LNK_TRAP,0x00);	//training off
+	edphw_write_reg(edpdev,EDP_LNK_SCR_CTRL,0x00);	//enable internal scramble
+	
+}
+
+static void edphw_tx_init(struct platform_device *edpdev)
+{	
+	edphw_write_reg(edpdev,EDP_CORE_TX_EN,0x00);		//disable trasmitter output
+	edphw_write_reg(edpdev,EDP_PHY_PWR_DOWN,0x00);	//power enable,pull the PHY out of power down		
+	edphw_write_reg(edpdev,EDP_PHY_RESET,0x00);	//pull the PHY out of reset
+	mdelay(1);			//wait for mdelay complete
+	edphw_write_reg(edpdev,EDP_CORE_TX_EN,0x01);	//enab	
+}
+
+static void edphw_set_lnk_lane_cnt(struct platform_device *edpdev,u8 lane)
+{	
+
+	BUG_ON((lane > (1 << 4)));
+	
+    edphw_write_reg(edpdev,EDP_LNK_LANE_COUNT, lane);      
+	
+}
+
+static void edphw_set_lnk_enhanced(struct platform_device *edpdev,bool enable)
+{	
+    edphw_write_reg(edpdev,EDP_LNK_ENHANCED, enable);     
+	
+}
+
+static void edphw_set_default_color(struct platform_device *edpdev, u32 color)
+{	
+	edphw_write_reg(edpdev,EDP_RGB_COLOR, color);
+}
+
+
+static void edphw_set_single_fromat(struct platform_device *edpdev,u8 format)
+{	
+	u32 val;
+		
+	val = edphw_read_reg(edpdev,EDP_MSTREAM_MISC0);
+	
+	val = REG_SET_VAL(val, format, 2, 1);
+		
+	edphw_write_reg(edpdev,EDP_MSTREAM_MISC0, val);
+
+}
+
+static void edphw_set_date_width(struct platform_device *edpdev,u8 bit_per_pix)
+{	
+	u32 val;
+		
+	val = edphw_read_reg(edpdev,EDP_MSTREAM_MISC0);
+	
+	val = REG_SET_VAL(val, bit_per_pix, 7, 5);
+		
+	edphw_write_reg(edpdev,EDP_MSTREAM_MISC0, val);	
+
+}
+static void edphw_set_yuv_bt(struct platform_device *edpdev,u8 bt_yuv)
+{	
+	u32 val;
+		
+	val = edphw_read_reg(edpdev,EDP_MSTREAM_MISC0);
+	
+	val = REG_SET_VAL(val, bt_yuv, 4, 4);
+		
+	edphw_write_reg(edpdev,EDP_MSTREAM_MISC0, val);	
+
+}
+static void edphw_set_micro_packet_size(struct platform_device *edpdev,u8 size)
+{	
+	u32 val;
+	
+	BUG_ON(size > (1 << 6));	
+	
+	val = edphw_read_reg(edpdev,EDP_MTRANSFER_UNIT);
+	
+	val = REG_SET_VAL(val, size, 6, 0);
+		
+	edphw_write_reg(edpdev,EDP_MTRANSFER_UNIT, val);	
+
+}
+
+
+static void edphw_set_rb_swap(struct platform_device *edpdev, bool rb_swap)
+{	
+	u32 val;
+		
+	val = edphw_read_reg(edpdev,EDP_RGB_CTL);
+	
+	val = REG_SET_VAL(val, rb_swap, 1, 1);
+		
+	edphw_write_reg(edpdev,EDP_RGB_CTL, val);
+}
+
+static void edphw_set_single_from(struct platform_device *edpdev, u8 single)
+{	
+	u32 val;
+		
+	val = edphw_read_reg(edpdev,EDP_RGB_CTL);
+	
+	val = REG_SET_VAL(val, single, 1, 1);
+		
+	edphw_write_reg(edpdev,EDP_RGB_CTL, val);
+}
+
+static void edphw_single_enable(struct platform_device *edpdev, bool enable)
+{	
+	u32 val;
+	//start calibrate	
+	val = edphw_read_reg(edpdev,EDP_PHY_CAL_CTRL);
+	
+	val = REG_SET_VAL(val, enable, 8, 8);
+		
+	edphw_write_reg(edpdev,EDP_PHY_CAL_CTRL, val);
+	
+	//Enable the main stream
+	val = edphw_read_reg(edpdev,EDP_CORE_MSTREAM_EN);
+	
+	val = REG_SET_VAL(val, enable, 0, 0);
+		
+	edphw_write_reg(edpdev,EDP_CORE_MSTREAM_EN, val);
+	
+	//enable RGB interface	
+	val = edphw_read_reg(edpdev,EDP_RGB_CTL);
+	
+	val = REG_SET_VAL(val, enable, 0, 0);
+		
+	edphw_write_reg(edpdev,EDP_RGB_CTL, val);	
+}
+
+static void edphw_display_init_edp(struct owl_dss_device *dssdev)
+{
+	struct platform_device * edpdev = edp_pdev_map[0];
+	struct owl_video_timings * timings = &(dssdev->timings);
+	
+	BUG_ON(!timings);
+	
+	edphw_set_size(edpdev,timings->x_res,timings->y_res);
+
+	edphw_set_timings(edpdev,timings->x_res,timings->y_res,timings->hbp ,timings->hfp, timings->hsw, timings->vbp ,timings->vfp, timings->vsw);
+
+	edphw_set_default_color(edpdev,0);
+	
+	edphw_set_single_fromat(edpdev,0);
+	
+	edphw_set_rb_swap(edpdev,0);
+	
+	edphw_set_single_from(edpdev,0x02);
+	
+	edphw_phy_config(edpdev);
+	
+	edphw_tx_init(edpdev);
+	
+	edphw_link_config(edpdev);
+
+}
+
+static int edphw_get_clocks(struct platform_device *edpdev)
+{
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+	struct clk *clk;
+#if 0
+	clk = clk_get(&edpdev->dev, "lcd");
+	if (IS_ERR(clk)) {
+		DSSERR("can't get fck\n");
+		return PTR_ERR(clk);
+	}
+
+	edp->edp_clk = clk;
+#endif 
+	return 0;
+}
+static void edphw_put_clocks(struct platform_device *edpdev)
+{
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+
+	if (edp->edp_clk)
+		clk_put(edp->edp_clk);
+
+}
+int owl_edp_display_enable(struct owl_dss_device *dssdev)
+{
+	int r;
+
+    struct platform_device *edpdev = edp_pdev_map[0] ;
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+	
+	mutex_lock(&edp->lock);
+	
+	if (dssdev->manager == NULL) {
+		DSSERR("failed to enable display: no manager\n");
+		return -ENODEV;
+	}
+
+	r = owl_dss_start_device(dssdev);
+	
+	if (r) {
+		DSSERR("failed to start device\n");
+		goto err_start_dev;
+	}
+	
+	if(edp->edp_power){
+		r = regulator_enable(edp->edp_power);
+		if (r)
+			goto err_reg_enable;
+	}
+
+	edphw_display_init_edp(dssdev);
+	
+	
+	r = dss_mgr_enable(dssdev->manager);
+	
+	if (r)
+		goto err_mgr_enable;
+		
+	edphw_single_enable(edpdev,true);	
+	
+	mutex_unlock(&edp->lock);
+	edphw_dump_regs(edpdev);
+	return 0;
+	
+err_mgr_enable:
+err_reg_enable:
+err_get_edp:	
+err_start_dev:
+	mutex_unlock(&edp->lock);
+	return r;
+}
+
+void owl_edp_display_disable(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct platform_device *edpdev = edp_pdev_map[0] ;
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+	
+	edphw_single_enable(edpdev,false);	
+	
+	dss_mgr_disable(dssdev->manager);
+
+	if(edp->edp_power){
+		r = regulator_disable(edp->edp_power);
+		if (r){
+		}
+	}
+
+	owl_dss_stop_device(dssdev);
+}
+
+/* EDP HW IP initialisation */
+static int owl_edphw_probe(struct platform_device *edpdev)
+{
+	int r;
+	struct resource *edp_mem;
+	struct edp_data *edp;
+	DSSDBG("owl_edphw_probe called \n");
+	edp = kzalloc(sizeof(*edp), GFP_KERNEL);
+	if (!edp) {
+		r = -ENOMEM;
+		goto err_alloc;
+	}
+
+	edp->pdev = edpdev;
+	edp_pdev_map[0] = edpdev;
+	dev_set_drvdata(&edpdev->dev, edp);
+
+	edp->enable_pads = edphw_enable_pads;
+	edp->disable_pads = edphw_disable_pads;
+
+	mutex_init(&edp->lock);
+
+	r = edphw_get_clocks(edpdev);
+	if (r)
+		goto err_get_clk;
+
+	pm_runtime_enable(&edpdev->dev);
+
+	edp_mem = platform_get_resource(edp->pdev, IORESOURCE_MEM, 0);
+	
+	if (!edp_mem) {
+		DSSERR("can't get IORESOURCE_MEM DSI\n");
+		r = -EINVAL;
+		goto err_ioremap;
+	}	
+	
+	edp->base = ioremap(edp_mem->start, resource_size(edp_mem));
+	if (!edp->base) {
+		DSSERR("can't ioremap edp \n");
+		r = -ENOMEM;
+		goto err_ioremap;
+	}
+	DSSDBG("edp->base  ~~~ %p \n",edp->base);	
+		
+	//dsi_calc_clock_param_ranges(edpdev);
+	DSSDBG("owl_edphw_probe called  ok ~~~~~~~~~~~~~\n");
+	return 0;
+
+err_get_dsi:
+	iounmap(edp->base);
+err_ioremap:
+	pm_runtime_disable(&edpdev->dev);
+err_get_clk:
+	kfree(edp);
+err_alloc:
+	return r;
+}
+
+static int owl_edphw_remove(struct platform_device *edpdev)
+{
+	struct edp_data *edp = edphw_get_edpdrv_data(edpdev);
+
+	pm_runtime_disable(&edpdev->dev);
+
+	edphw_put_clocks(edpdev);
+
+	if (edp->edp_power != NULL) {
+		if (edp->edp_power_enabled) {
+			regulator_disable(edp->edp_power);
+			edp->edp_power_enabled = false;
+		}
+		regulator_put(edp->edp_power);
+		edp->edp_power = NULL;
+	}
+
+	iounmap(edp->base);
+
+	kfree(edp);
+
+	return 0;
+}
+
+static struct resource asoc_edphw_resources[] = {
+	{
+		.start = EDPHW_REG_MEM_BASE,
+		.end = EDPHW_REG_MEM_END,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device asoc_edphw_devices = {
+    .name           = "owl_edphw",
+    .num_resources  = ARRAY_SIZE(asoc_edphw_resources),
+    .resource       = asoc_edphw_resources
+};
+
+
+static struct platform_driver asoc_edphw_driver = {
+	.probe          = owl_edphw_probe,
+	.remove         = owl_edphw_remove,
+	.driver         = {
+		.name   = "owl_edphw",
+		.owner  = THIS_MODULE,
+	},
+};
+
+int owl_edp_init_platform(void)
+{
+	int r;
+	
+	r = platform_device_register(&asoc_edphw_devices);
+	if (r) {
+		DSSERR("Failed to initialize edp platform devices\n");
+		goto err_device;
+	}
+	
+	r = platform_driver_register(&asoc_edphw_driver);
+	
+	if (r) {
+		DSSERR("Failed to initialize edp platform driver\n");
+		goto err_driver;
+	}
+	return 0;
+err_driver:
+	platform_device_unregister(&asoc_edphw_devices);
+err_device:
+	return r;
+}
+
+int owl_edp_uninit_platform(void)
+{   
+	platform_device_unregister(&asoc_edphw_devices);
+	
+	platform_driver_unregister(&asoc_edphw_driver);
+	
+    return 0;
+}
diff --git a/drivers/video/fbdev/owl/displays/edp/edphw.h b/drivers/video/fbdev/owl/displays/edp/edphw.h
new file mode 100755
index 0000000..03c206b
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/edp/edphw.h
@@ -0,0 +1,259 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/lcdchw.h
+ *
+ * Copyright (C) 2011 Actions
+ * Author: Hui Wang <wanghui at actions-semi.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __ASOC_LCDCHW_REG_H
+#define __ASOC_LCDCHW_REG_H
+
+
+#define GL5209 
+
+#ifdef GL5209
+
+    #define    EDPHW_REG_MEM_BASE                                                0xE0190000
+    #define    EDPHW_REG_MEM_END                                                 0xE0190510
+        
+	#define     EDP_LNK_LANE_COUNT                                                (0x0004)
+	#define     EDP_LNK_ENHANCED                                                  (0x0008)
+	#define     EDP_LNK_TRAP                                                      (0x000c)
+	#define     EDP_LNK_QUAL_PAT                                                  (0x0010)
+	#define     EDP_LNK_SCR_CTRL                                                  (0x0014)
+	#define     EDP_LNK_DSPR_CTRL                                                 (0x0018)
+	#define     EDP_LNK_SCR_RST                                                   (0x001c)
+	#define     EDP_LNK_PANEL_SRF                                                 (0x0020)
+	#define     EDP_CORE_TX_EN                                                    (0x0080)
+	#define     EDP_CORE_MSTREAM_EN                                               (0x0084)
+	#define     EDP_CORE_SSTREAM_EN                                               (0x0088)
+	#define     EDP_CORE_FSCR_RST                                                 (0x00C0)
+	#define     EDP_CORE_USER_CFG                                                 (0x00C4)
+	#define     EDP_CORE_CAPS                                                     (0x00F8)
+	#define     EDP_CORE_ID                                                       (0x00FC)
+	#define     EDP_AUX_COMD                                                      (0x0100)
+	#define     EDP_AUX_WR_FIFO                                                   (0x0104)
+	#define     EDP_AUX_ADDR                                                      (0x0108)
+	#define     EDP_AUX_CLK_DIV                                                   (0x010C)
+	#define     EDP_AUX_STATE                                                     (0x0130)
+	#define     EDP_AUX_RPLY_DAT                                                  (0x0134)
+	#define     EDP_AUX_RPLY_CODE                                                 (0x0138)
+	#define     EDP_AUX_RPLY_COUNT                                                (0x013C)
+	#define     EDP_AUX_INT_STAT                                                  (0x0140)
+	#define     EDP_AUX_INT_MASK                                                  (0x0144)
+	#define     EDP_AUX_RPLY_DAT_CNT                                              (0x0148)
+	#define     EDP_AUX_STATUS                                                    (0x014C)
+	#define     EDP_AUX_RCLK_WIDTH                                                (0x0150)
+	#define     EDP_MSTREAM_HTOTAL                                                (0x0180)
+	#define     EDP_MSTREAM_VTOTAL                                                (0x0184)
+	#define     EDP_MSTREAM_POLARITY                                              (0x0188)
+	#define     EDP_MSTREAM_HSWIDTH                                               (0x018C)
+	#define     EDP_MSTREAM_VSWIDTH                                               (0x0190)
+	#define     EDP_MSTREAM_HRES                                                  (0x0194)
+	#define     EDP_MSTREAM_VRES                                                  (0x0198)
+	#define     EDP_MSTREAM_HSTART                                                (0x019C)
+	#define     EDP_MSTREAM_VSTART                                                (0x01A0)
+	#define     EDP_MSTREAM_MISC0                                                 (0x01A4)
+	#define     EDP_MSTREAM_MISC1                                                 (0x01A8)
+	#define     EDP_M_VID                                                         (0x01AC)
+	#define     EDP_MTRANSFER_UNIT                                                (0x01B0)
+	#define     EDP_N_VID                                                         (0x01B4)
+	#define     EDP_USER_PIXEL_WIDTH                                              (0x01B8)
+	#define     EDP_USER_DATA_COUNT                                               (0x01BC)
+	#define     EDP_MSTREAM_INTERLACED                                            (0x01C0)
+	#define     EDP_USER_SYNC_POLARITY                                            (0x01C4)
+	#define     EDP_PHY_RESET                                                     (0x0200)
+	#define     EDP_PHY_PREEM_L0                                                  (0x0204)
+	#define     EDP_PHY_PREEM_L1                                                  (0x0208)
+	#define     EDP_PHY_PREEM_L2                                                  (0x020C)
+	#define     EDP_PHY_PREEM_L3                                                  (0x0210)
+	#define     EDP_PHY_VSW_L0                                                    (0x0214)
+	#define     EDP_PHY_VSW_L1                                                    (0x0218)
+	#define     EDP_PHY_VSW_L2                                                    (0x021C)
+	#define     EDP_PHY_VSW_L3                                                    (0x0220)
+	#define     EDP_PHY_VSW_AUX                                                   (0x0224)
+	#define     EDP_PHY_PWR_DOWN                                                  (0x0228)
+	#define     EDP_PHY_CAL_CONFIG                                                (0x022C)
+	#define     EDP_PHY_CAL_CTRL                                                  (0x0230)
+	#define     EDP_PHY_CTRL                                                      (0x0234)
+	#define     EDP_SDB_LANE_SELECT                                               (0x0300)
+	#define     EDP_SDB_WRITE_INDEX                                               (0x0304)
+	#define     EDP_SDB_DATA_COUNT                                                (0x0308)
+	#define     EDP_SDB_DATA                                                      (0x030C)
+	#define     EDP_SDB_READY                                                     (0x0310)
+	#define     EDP_SDB_BUSY                                                      (0x0314)
+	#define     EDP_RGB_CTL                                                       (0x0500)
+	#define     EDP_RGB_STATUS                                                    (0x0504)
+	#define     EDP_RGB_COLOR                                                     (0x0508)
+	#define     EDP_DEBUG                                                         (0x050C)
+			
+#endif
+
+
+#ifdef GL5206
+	#define    EDPHW_REG_MEM_BASE                                                0xE0190000
+    #define    EDPHW_REG_MEM_END                                                 0xE0190510
+        
+	#define     EDP_LNK_LANE_COUNT                                                (0x0004)
+	#define     EDP_LNK_ENHANCED                                                  (0x0008)
+	#define     EDP_LNK_TRAP                                                      (0x000c)
+	#define     EDP_LNK_QUAL_PAT                                                  (0x0010)
+	#define     EDP_LNK_SCR_CTRL                                                  (0x0014)
+	#define     EDP_LNK_DSPR_CTRL                                                 (0x0018)
+	#define     EDP_LNK_SCR_RST                                                   (0x001c)
+	#define     EDP_LNK_PANEL_SRF                                                 (0x0020)
+	#define     EDP_CORE_TX_EN                                                    (0x0080)
+	#define     EDP_CORE_MSTREAM_EN                                               (0x0084)
+	#define     EDP_CORE_SSTREAM_EN                                               (0x0088)
+	#define     EDP_CORE_FSCR_RST                                                 (0x00C0)
+	#define     EDP_CORE_USER_CFG                                                 (0x00C4)
+	#define     EDP_CORE_CAPS                                                     (0x00F8)
+	#define     EDP_CORE_ID                                                       (0x00FC)
+	#define     EDP_AUX_COMD                                                      (0x0100)
+	#define     EDP_AUX_WR_FIFO                                                   (0x0104)
+	#define     EDP_AUX_ADDR                                                      (0x0108)
+	#define     EDP_AUX_CLK_DIV                                                   (0x010C)
+	#define     EDP_AUX_STATE                                                     (0x0130)
+	#define     EDP_AUX_RPLY_DAT                                                  (0x0134)
+	#define     EDP_AUX_RPLY_CODE                                                 (0x0138)
+	#define     EDP_AUX_RPLY_COUNT                                                (0x013C)
+	#define     EDP_AUX_INT_STAT                                                  (0x0140)
+	#define     EDP_AUX_INT_MASK                                                  (0x0144)
+	#define     EDP_AUX_RPLY_DAT_CNT                                              (0x0148)
+	#define     EDP_AUX_STATUS                                                    (0x014C)
+	#define     EDP_AUX_RCLK_WIDTH                                                (0x0150)
+	#define     EDP_MSTREAM_HTOTAL                                                (0x0180)
+	#define     EDP_MSTREAM_VTOTAL                                                (0x0184)
+	#define     EDP_MSTREAM_POLARITY                                              (0x0188)
+	#define     EDP_MSTREAM_HSWIDTH                                               (0x018C)
+	#define     EDP_MSTREAM_VSWIDTH                                               (0x0190)
+	#define     EDP_MSTREAM_HRES                                                  (0x0194)
+	#define     EDP_MSTREAM_VRES                                                  (0x0198)
+	#define     EDP_MSTREAM_HSTART                                                (0x019C)
+	#define     EDP_MSTREAM_VSTART                                                (0x01A0)
+	#define     EDP_MSTREAM_MISC0                                                 (0x01A4)
+	#define     EDP_MSTREAM_MISC1                                                 (0x01A8)
+	#define     EDP_M_VID                                                         (0x01AC)
+	#define     EDP_MTRANSFER_UNIT                                                (0x01B0)
+	#define     EDP_N_VID                                                         (0x01B4)
+	#define     EDP_USER_PIXEL_WIDTH                                              (0x01B8)
+	#define     EDP_USER_DATA_COUNT                                               (0x01BC)
+	#define     EDP_MSTREAM_INTERLACED                                            (0x01C0)
+	#define     EDP_USER_SYNC_POLARITY                                            (0x01C4)
+	#define     EDP_PHY_RESET                                                     (0x0200)
+	#define     EDP_PHY_PREEM_L0                                                  (0x0204)
+	#define     EDP_PHY_PREEM_L1                                                  (0x0208)
+	#define     EDP_PHY_PREEM_L2                                                  (0x020C)
+	#define     EDP_PHY_PREEM_L3                                                  (0x0210)
+	#define     EDP_PHY_VSW_L0                                                    (0x0214)
+	#define     EDP_PHY_VSW_L1                                                    (0x0218)
+	#define     EDP_PHY_VSW_L2                                                    (0x021C)
+	#define     EDP_PHY_VSW_L3                                                    (0x0220)
+	#define     EDP_PHY_VSW_AUX                                                   (0x0224)
+	#define     EDP_PHY_PWR_DOWN                                                  (0x0228)
+	#define     EDP_PHY_CAL_CONFIG                                                (0x022C)
+	#define     EDP_PHY_CAL_CTRL                                                  (0x0230)
+	#define     EDP_PHY_CTRL                                                      (0x0234)
+	#define     EDP_SDB_LANE_SELECT                                               (0x0300)
+	#define     EDP_SDB_WRITE_INDEX                                               (0x0304)
+	#define     EDP_SDB_DATA_COUNT                                                (0x0308)
+	#define     EDP_SDB_DATA                                                      (0x030C)
+	#define     EDP_SDB_READY                                                     (0x0310)
+	#define     EDP_SDB_BUSY                                                      (0x0314)
+	#define     EDP_RGB_CTL                                                       (0x0500)
+	#define     EDP_RGB_STATUS                                                    (0x0504)
+	#define     EDP_RGB_COLOR                                                     (0x0508)
+	#define     EDP_DEBUG                                                         (0x050C)
+
+#endif
+
+#ifdef GL5203
+	#define    EDPHW_REG_MEM_BASE                                                0xE0190000
+    #define    EDPHW_REG_MEM_END                                                 0xE0190510
+        
+	#define     EDP_LNK_LANE_COUNT                                                (0x0004)
+	#define     EDP_LNK_ENHANCED                                                  (0x0008)
+	#define     EDP_LNK_TRAP                                                      (0x000c)
+	#define     EDP_LNK_QUAL_PAT                                                  (0x0010)
+	#define     EDP_LNK_SCR_CTRL                                                  (0x0014)
+	#define     EDP_LNK_DSPR_CTRL                                                 (0x0018)
+	#define     EDP_LNK_SCR_RST                                                   (0x001c)
+	#define     EDP_LNK_PANEL_SRF                                                 (0x0020)
+	#define     EDP_CORE_TX_EN                                                    (0x0080)
+	#define     EDP_CORE_MSTREAM_EN                                               (0x0084)
+	#define     EDP_CORE_SSTREAM_EN                                               (0x0088)
+	#define     EDP_CORE_FSCR_RST                                                 (0x00C0)
+	#define     EDP_CORE_USER_CFG                                                 (0x00C4)
+	#define     EDP_CORE_CAPS                                                     (0x00F8)
+	#define     EDP_CORE_ID                                                       (0x00FC)
+	#define     EDP_AUX_COMD                                                      (0x0100)
+	#define     EDP_AUX_WR_FIFO                                                   (0x0104)
+	#define     EDP_AUX_ADDR                                                      (0x0108)
+	#define     EDP_AUX_CLK_DIV                                                   (0x010C)
+	#define     EDP_AUX_STATE                                                     (0x0130)
+	#define     EDP_AUX_RPLY_DAT                                                  (0x0134)
+	#define     EDP_AUX_RPLY_CODE                                                 (0x0138)
+	#define     EDP_AUX_RPLY_COUNT                                                (0x013C)
+	#define     EDP_AUX_INT_STAT                                                  (0x0140)
+	#define     EDP_AUX_INT_MASK                                                  (0x0144)
+	#define     EDP_AUX_RPLY_DAT_CNT                                              (0x0148)
+	#define     EDP_AUX_STATUS                                                    (0x014C)
+	#define     EDP_AUX_RCLK_WIDTH                                                (0x0150)
+	#define     EDP_MSTREAM_HTOTAL                                                (0x0180)
+	#define     EDP_MSTREAM_VTOTAL                                                (0x0184)
+	#define     EDP_MSTREAM_POLARITY                                              (0x0188)
+	#define     EDP_MSTREAM_HSWIDTH                                               (0x018C)
+	#define     EDP_MSTREAM_VSWIDTH                                               (0x0190)
+	#define     EDP_MSTREAM_HRES                                                  (0x0194)
+	#define     EDP_MSTREAM_VRES                                                  (0x0198)
+	#define     EDP_MSTREAM_HSTART                                                (0x019C)
+	#define     EDP_MSTREAM_VSTART                                                (0x01A0)
+	#define     EDP_MSTREAM_MISC0                                                 (0x01A4)
+	#define     EDP_MSTREAM_MISC1                                                 (0x01A8)
+	#define     EDP_M_VID                                                         (0x01AC)
+	#define     EDP_MTRANSFER_UNIT                                                (0x01B0)
+	#define     EDP_N_VID                                                         (0x01B4)
+	#define     EDP_USER_PIXEL_WIDTH                                              (0x01B8)
+	#define     EDP_USER_DATA_COUNT                                               (0x01BC)
+	#define     EDP_MSTREAM_INTERLACED                                            (0x01C0)
+	#define     EDP_USER_SYNC_POLARITY                                            (0x01C4)
+	#define     EDP_PHY_RESET                                                     (0x0200)
+	#define     EDP_PHY_PREEM_L0                                                  (0x0204)
+	#define     EDP_PHY_PREEM_L1                                                  (0x0208)
+	#define     EDP_PHY_PREEM_L2                                                  (0x020C)
+	#define     EDP_PHY_PREEM_L3                                                  (0x0210)
+	#define     EDP_PHY_VSW_L0                                                    (0x0214)
+	#define     EDP_PHY_VSW_L1                                                    (0x0218)
+	#define     EDP_PHY_VSW_L2                                                    (0x021C)
+	#define     EDP_PHY_VSW_L3                                                    (0x0220)
+	#define     EDP_PHY_VSW_AUX                                                   (0x0224)
+	#define     EDP_PHY_PWR_DOWN                                                  (0x0228)
+	#define     EDP_PHY_CAL_CONFIG                                                (0x022C)
+	#define     EDP_PHY_CAL_CTRL                                                  (0x0230)
+	#define     EDP_PHY_CTRL                                                      (0x0234)
+	#define     EDP_SDB_LANE_SELECT                                               (0x0300)
+	#define     EDP_SDB_WRITE_INDEX                                               (0x0304)
+	#define     EDP_SDB_DATA_COUNT                                                (0x0308)
+	#define     EDP_SDB_DATA                                                      (0x030C)
+	#define     EDP_SDB_READY                                                     (0x0310)
+	#define     EDP_SDB_BUSY                                                      (0x0314)
+	#define     EDP_RGB_CTL                                                       (0x0500)
+	#define     EDP_RGB_STATUS                                                    (0x0504)
+	#define     EDP_RGB_COLOR                                                     (0x0508)
+	#define     EDP_DEBUG                                                         (0x050C)
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/edp/panel-retina-fpga.c b/drivers/video/fbdev/owl/displays/edp/panel-retina-fpga.c
new file mode 100755
index 0000000..dfc469e
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/edp/panel-retina-fpga.c
@@ -0,0 +1,233 @@
+/*
+ * Generic EDP Panels support
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu at canonical.com>
+ *
+ * LCD panel driver for Sharp LQ043T1DG01
+ *
+ * Copyright (C) 2009 Actions Inc
+ * Author: Vaibhav Hiremath <hvaibhav at ti.com>
+ *
+ * LCD panel driver for Toppoly TDO35S
+ *
+ * Copyright (C) 2009 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike at compulab.co.il>
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include "../owldss.h"
+
+struct panel_config {
+	struct owl_video_timings timings;
+
+	//enum owl_panel_config config;
+
+	int power_on_delay;
+	
+	int power_off_delay;
+
+	/*
+	 * Used to match device to panel configuration
+	 * when use generic panel driver
+	 */
+	const char *name;
+
+	int (*platform_enable)(struct owl_dss_device *dssdev);
+	
+	void (*platform_disable)(struct owl_dss_device *dssdev);
+};
+
+/* Panel configurations */
+static struct panel_config generic_edp_panels[] = {
+	/* fpga rgb lcd  */
+	{
+		{
+			.x_res		= 1280,
+			.y_res		= 800,
+
+			.pixel_clock	= 9000,
+
+			.hsw		= 48,
+			.hfp		= 23,
+			.hbp		= 64,
+
+			.vsw		= 3,
+			.vfp		= 15,
+			.vbp		= 12,
+		},
+
+		//.config			= OWL_DSS_LCD_TFT,
+		.power_on_delay		= 50,
+		.power_off_delay	= 100,
+		.name			= "sharp_lq",
+	},	
+};
+
+struct panel_drv_data {
+
+	struct owl_dss_device *dssdev;
+
+	struct panel_config *panel_config;
+};
+
+
+static int generic_edp_panel_power_on(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE)
+		return 0;
+
+	r = owl_edp_display_enable(dssdev);
+	
+	if (r)
+		goto err0;
+
+	/* wait couple of vsyncs until enabling the LCD */
+	if (panel_config->power_on_delay)
+		msleep(panel_config->power_on_delay);
+
+	if (panel_config->platform_enable) {
+		r = panel_config->platform_enable(dssdev);
+		if (r)
+			goto err1;
+	}
+
+	return 0;
+err1:
+	owl_edp_display_disable(dssdev);
+err0:
+	return r;
+}
+
+static void generic_edp_panel_power_off(struct owl_dss_device *dssdev)
+{
+
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state != OWL_DSS_DISPLAY_ACTIVE)
+		return;
+
+	if (panel_config->platform_disable)
+		panel_config->platform_disable(dssdev);
+
+	/* wait couple of vsyncs after disabling the LCD */
+	if (panel_config->power_off_delay)
+		msleep(panel_config->power_off_delay);
+
+	owl_edp_display_disable(dssdev);
+}
+
+static int generic_edp_panel_probe(struct owl_dss_device *dssdev)
+{
+
+	struct panel_config *panel_config = NULL;
+	struct panel_drv_data *drv_data = NULL;
+
+	dev_dbg(&dssdev->dev, "probe\n");
+
+    panel_config = &generic_edp_panels[0];
+    
+	if (!panel_config)
+		return -EINVAL;
+
+	dssdev->timings = panel_config->timings;
+
+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	drv_data->dssdev = dssdev;
+	drv_data->panel_config = panel_config;
+
+	dev_set_drvdata(&dssdev->dev, drv_data);
+
+	return 0;
+}
+
+static void __exit generic_edp_panel_remove(struct owl_dss_device *dssdev)
+{
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	dev_dbg(&dssdev->dev, "remove\n");
+
+	kfree(drv_data);
+
+	dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+static int generic_edp_panel_enable(struct owl_dss_device *dssdev)
+{
+	int r = 0;
+
+	r = generic_edp_panel_power_on(dssdev);
+	if (r)
+		return r;
+
+	dssdev->state = OWL_DSS_DISPLAY_ACTIVE;
+
+	return 0;
+}
+
+static void generic_edp_panel_disable(struct owl_dss_device *dssdev)
+{
+	generic_edp_panel_power_off(dssdev);
+
+	dssdev->state = OWL_DSS_DISPLAY_DISABLED;
+}
+
+static void generic_edp_panel_get_timings(struct owl_dss_device *dssdev, struct owl_video_timings *timings)
+{
+	*timings = dssdev->timings;
+}
+
+static struct owl_dss_driver edp_driver = {
+	.probe		= generic_edp_panel_probe,
+	.remove		= __exit_p(generic_edp_panel_remove),
+
+	.enable		= generic_edp_panel_enable,
+	.disable	= generic_edp_panel_disable,
+	.get_timings	= generic_edp_panel_get_timings,
+
+	.driver         = {
+		.name   = "generic_edp_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init generic_edp_panel_drv_init(void)
+{
+	owl_edp_init_platform();
+	return owl_dss_register_driver(&edp_driver);
+}
+
+static void __exit generic_edp_panel_drv_exit(void)
+{
+	owl_dss_unregister_driver(&edp_driver);
+	owl_edp_uninit_platform();
+}
+
+module_init(generic_edp_panel_drv_init);
+module_exit(generic_edp_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/displays/hdmi/Kconfig b/drivers/video/fbdev/owl/displays/hdmi/Kconfig
new file mode 100755
index 0000000..3bd8aff
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/Kconfig
@@ -0,0 +1,13 @@
+config VIDEO_OWL_NO_DVI
+	bool "video no dvi"
+
+config VIDEO_OWL_HDMI
+	tristate "OWL hdmi support"
+	---help---
+	  Actions OWL Soc hdmi controller support.
+
+	  Say Y here if you need it in your system.
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/Makefile b/drivers/video/fbdev/owl/displays/hdmi/Makefile
new file mode 100755
index 0000000..e9f0638
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_OWL_HDMI) += owl_hdmi.o
+
+owl_hdmi-y := hdmi.o hdmi_edid.o hdmi_ip.o hdmi_packet.o hdmi_panel.o hdmi_sysfs.o hdcp.o hdmi_cec.o hdmi_cec_ctrl.o
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/cec.h b/drivers/video/fbdev/owl/displays/hdmi/cec.h
new file mode 100755
index 0000000..7892647
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/cec.h
@@ -0,0 +1,100 @@
+/*
+ * cec.h
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: HaiYu Huang  <huanghaiyu at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+
+#ifndef _OWL_HDMI_CEC_H_
+#define _OWL_HDMI_CEC_H_ __FILE__
+
+/*****************************************************************************
+ * This file includes declarations for external functions of
+ * Samsung TVOUT-related hardware. So only external functions
+ * to be used by higher layer must exist in this file.
+ *
+ * Higher layer must use only the declarations included in this file.
+ ****************************************************************************/
+
+#define to_tvout_plat(d) (to_platform_device(d)->dev.platform_data)
+
+
+#ifndef hdmi_cec_dbg
+#ifdef CONFIG_TV_DEBUG
+#define hdmi_cec_dbg(fmt, ...)					\
+		printk(KERN_DEBUG "[%s] %s(): " fmt,		\
+			"HDMI-CEC", __func__, ##__VA_ARGS__)
+#else
+#define hdmi_cec_dbg(fmt, ...)
+#endif
+#endif
+
+enum s5p_tvout_endian {
+	TVOUT_LITTLE_ENDIAN = 0,
+	TVOUT_BIG_ENDIAN = 1
+};
+
+enum cec_state {
+	STATE_RX,
+	STATE_TX,
+	STATE_DONE,
+	STATE_ERROR
+};
+
+struct cec_rx_struct {
+	spinlock_t lock;
+	wait_queue_head_t waitq;
+	atomic_t state;
+	u8 *buffer;
+	unsigned int size;
+};
+
+struct cec_tx_struct {
+	wait_queue_head_t waitq;
+	atomic_t state;
+};
+
+extern struct cec_rx_struct cec_rx_struct;
+extern struct cec_tx_struct cec_tx_struct;
+
+void hdmi_cec_hw_init(void);
+void hdmi_cec_set_divider(void);
+void hdmi_cec_enable_rx(void);
+void hdmi_cec_disable_rx(void);
+void hdmi_cec_enable_tx(void);
+void hdmi_cec_disable_tx(void);
+void hdmi_cec_mask_rx_interrupts(void);
+void hdmi_cec_unmask_rx_interrupts(void);
+void hdmi_cec_mask_tx_interrupts(void);
+void hdmi_cec_unmask_tx_interrupts(void);
+void hdmi_cec_reset(void);
+void hdmi_cec_tx_reset(void);
+void hdmi_cec_rx_reset(void);
+void hdmi_cec_threshold(void);
+void hdmi_cec_set_tx_state(enum cec_state state);
+void hdmi_cec_set_rx_state(enum cec_state state);
+void hdmi_cec_copy_packet(char *data, size_t count);
+void hdmi_cec_set_addr(u32 addr);
+u32  hdmi_cec_get_status(void);
+void hdmi_cec_clr_pending_tx(void);
+void hdmi_cec_clr_pending_rx(void);
+u8 hdmi_cec_get_rx_header(void);
+void hdmi_cec_get_rx_buf(u32 size, u8 *buffer);
+int hdmi_cec_mem_probe(struct platform_device *pdev);
+
+#endif /* _OWL_HDMI_CEC_H_ */
diff --git a/drivers/video/fbdev/owl/displays/hdmi/cec_reg.h b/drivers/video/fbdev/owl/displays/hdmi/cec_reg.h
new file mode 100755
index 0000000..30e724f
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/cec_reg.h
@@ -0,0 +1,103 @@
+#ifndef __CEC_REG_H__
+#define __CEC_REG_H__
+                                 
+//--------------Bits Location------------------------------------------//
+//--------------HDMI-------------------------------------------//
+//--------------Register Address---------------------------------------//
+#define  HDMI_BASE                                                         0xB02C0000
+#define  HDMI_VICTL                                                        (0x0000)
+#define  HDMI_VIVSYNC                                                      (0x0004)
+#define  HDMI_VIVHSYNC                                                     (0x0008)
+#define  HDMI_VIALSEOF                                                     (0x000C)
+#define  HDMI_VIALSEEF                                                     (0x0010)
+#define  HDMI_VIADLSE                                                      (0x0014)
+#define  HDMI_AIFRAMEC                                                     (0x0020)
+#define  HDMI_AICHSTABYTE0TO3                                              (0x0024)
+#define  HDMI_AICHSTABYTE4TO7                                              (0x0028)
+#define  HDMI_AICHSTABYTE8TO11                                             (0x002C)
+#define  HDMI_AICHSTABYTE12TO15                                            (0x0030)
+#define  HDMI_AICHSTABYTE16TO19                                            (0x0034)
+#define  HDMI_AICHSTABYTE20TO23                                            (0x0038)
+#define  HDMI_AICHSTASCN                                                   (0x003C)
+#define  HDMI_VR                                                           (0x0050)
+#define  HDMI_CR                                                           (0x0054)
+#define  HDMI_SCHCR                                                        (0x0058)
+#define  HDMI_ICR                                                          (0x005C)
+#define  HDMI_SCR                                                          (0x0060)
+#define  HDMI_LPCR                                                         (0x0064)
+#define  HDCP_CR                                                           (0x0068)
+#define  HDCP_SR                                                           (0x006C)
+#define  HDCP_ANLR                                                         (0x0070)
+#define  HDCP_ANMR                                                         (0x0074)
+#define  HDCP_ANILR                                                        (0x0078)
+#define  HDCP_ANIMR                                                        (0x007C)
+#define  HDCP_DPKLR                                                        (0x0080)
+#define  HDCP_DPKMR                                                        (0x0084)
+#define  HDCP_LIR                                                          (0x0088)
+#define  HDCP_SHACR                                                        (0x008C)
+#define  HDCP_SHADR                                                        (0x0090)
+#define  HDCP_ICR                                                          (0x0094)
+#define  HDCP_KMMR                                                         (0x0098)
+#define  HDCP_KMLR                                                         (0x009C)
+#define  HDCP_MILR                                                         (0x00A0)
+#define  HDCP_MIMR                                                         (0x00A4)
+#define  HDCP_KOWR                                                         (0x00A8)
+#define  HDCP_OWR                                                          (0x00AC)
+#define  TMDS_STR0                                                         (0x00B8)
+#define  TMDS_STR1                                                         (0x00BC)
+#define  TMDS_EODR0                                                        (0x00C0)
+#define  TMDS_EODR1                                                        (0x00C4)
+#define  HDMI_ASPCR                                                        (0x00D0)
+#define  HDMI_ACACR                                                        (0x00D4)
+#define  HDMI_ACRPCR                                                       (0x00D8)
+#define  HDMI_ACRPCTSR                                                     (0x00DC)
+#define  HDMI_ACRPPR                                                       (0x00E0)
+#define  HDMI_GCPCR                                                        (0x00E4)
+#define  HDMI_RPCR                                                         (0x00E8)
+#define  HDMI_RPRBDR                                                       (0x00EC)
+#define  HDMI_OPCR                                                         (0x00F0)
+#define  HDMI_DIPCCR                                                       (0x00F4)
+#define  HDMI_ORP6PH                                                       (0x00F8)
+#define  HDMI_ORSP6W0                                                      (0x00FC)
+#define  HDMI_ORSP6W1                                                      (0x0100)
+#define  HDMI_ORSP6W2                                                      (0x0104)
+#define  HDMI_ORSP6W3                                                      (0x0108)
+#define  HDMI_ORSP6W4                                                      (0x010C)
+#define  HDMI_ORSP6W5                                                      (0x0110)
+#define  HDMI_ORSP6W6                                                      (0x0114)
+#define  HDMI_ORSP6W7                                                      (0x0118)
+#define  HDMI_CECCR                                                        (0x011C)
+#define  HDMI_CECRTCR                                                      (0x0120)
+#define  HDMI_CECRXCR                                                      (0x0124)
+#define  HDMI_CECTXCR                                                      (0x0128)
+#define  HDMI_CECTXDR                                                      (0x012C)
+#define  HDMI_CECRXDR                                                      (0x0130)
+#define  HDMI_CECRXTCR                                                     (0x0134)
+#define  HDMI_CECTXTCR0                                                    (0x0138)
+#define  HDMI_CECTXTCR1                                                    (0x013C)
+#define  HDMI_CRCCR                                                        (0x0140)
+#define  HDMI_CRCDOR                                                       (0x0144)
+#define  HDMI_TX_1                                                         (0x0154)
+#define  HDMI_TX_2                                                         (0x0158)
+#define  CEC_DDC_HPD                                                       (0x015C)
+
+
+#define CES_RX_CTRL_ENABLE                                                    (1 << 15)
+#define CES_RX_CTRL_RESET                                                     (1 << 14)
+#define CES_RX_IRQ_ENABLE                                                     (1 << 12)
+#define CES_RX_EOM                                                            (1 << 7)
+#define CES_RX_IRQ_PENDDING                                                   (1 << 6)
+#define CES_RX_FIFO_RRROR                                                     (1 << 5)
+#define CES_RX_FIFO_NUM_MASK                                                  (1 << 5)
+
+#define CES_TX_ADDR_EN                                                        (1 << 20)   
+#define CES_TX_CTRL_ENABLE                                                    (1 << 15)
+#define CES_TX_CTRL_RESET                                                     (1 << 14)
+#define CES_TX_IRQ_ENABLE                                                     (1 << 12)
+#define CES_TX_EOM                                                            (1 << 7)
+#define CES_TX_IRQ_PENDDING                                                   (1 << 6)
+#define CES_TX_FIFO_RRROR                                                     (1 << 5)
+#define CES_TX_FIFO_NUM_MASK                                                  (1 << 5)
+#define CES_TX_CTRL_BCAST                                                     (0x0f << 8)
+#endif  //__CEC_REG_H__
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdcp.c b/drivers/video/fbdev/owl/displays/hdmi/hdcp.c
new file mode 100755
index 0000000..c98c881
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdcp.c
@@ -0,0 +1,1310 @@
+/*
+ * hdmi_edid.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+ 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/ctype.h>
+#include <linux/init.h>
+#include <asm/atomic.h>
+#include <linux/kthread.h>
+#include <linux/miscdevice.h>
+#include <mach/switch.h>
+#include <linux/sysfs.h>
+
+#include <mach/storage_access.h>
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+
+#define owl_hdmi_write(a, b)  hdmi.ip_data.ops->write_reg(&hdmi.ip_data, b, a)
+#define owl_hdmi_read(a)  hdmi.ip_data.ops->read_reg(&hdmi.ip_data, a)
+
+/*HDCP authen*/
+#define HDCP_XMT_LINK_H0    0
+#define HDCP_XMT_LINK_H1    1
+#define HDCP_XMT_AUTH_A0    2
+#define HDCP_XMT_AUTH_A1    3
+#define HDCP_XMT_AUTH_A2    4
+#define HDCP_XMT_AUTH_A3    5
+#define HDCP_XMT_AUTH_A4    6
+#define HDCP_XMT_AUTH_A5    7
+#define HDCP_XMT_AUTH_A6    8
+#define HDCP_XMT_AUTH_A7    9
+#define HDCP_XMT_AUTH_A8    10
+#define HDCP_XMT_AUTH_A9    11
+#define HDCP_XMT_AUTH_A9_1  12
+
+#define HDCP_FAIL_TIMES       50
+
+unsigned char key_r0[40][7];
+
+unsigned char aksv[6] = { 
+    0x10,  
+    0x1e, 
+    0xc8, 
+    0x42, 
+    0xdd, 
+    0xd9 
+};
+
+//#define READ_HDCP_KEY_FROM_NATIVE
+
+#ifdef READ_HDCP_KEY_FROM_NATIVE
+char test_keyr0[40][15] ={
+    "aa6197eb701e4e",
+    "780717d2d425d3",
+    "7c4f7efe39f44d",
+    "1e05f28f0253bd",
+    "d614c6ccb090ee",
+    "82f7f2803ffefc",
+    "4ae2ebe12741d7",
+    "e203695a82311c",
+    "4537b3e7f9f557",
+    "b02d715e2961ed",
+    "cd6e0ab9834016",
+    "d64fd9edfdd35b",
+    "3a13f170726840",
+    "4f52fb759d6f92",
+    "2afc1d08b4221f",
+    "b99db2a29aea40",
+    "2020da8eb3282a",
+    "0b4c6aee4aa771",
+    "edeef811ec6ac0",
+    "8f451ad92112f3",
+    "705e2fddc47e6e",
+    "6efc72aaa3348f",
+    "7debb76130fb0e",
+    "5fd1a853c40f52",
+    "70168fbeaeba3c",
+    "a0cb8f3162d198",
+    "5ed0a9eef0c1ed",
+    "fa18541a02d283",
+    "0661135d19feec",
+    "da6b02ca363cf3",
+    "dd7142f81e832f",
+    "cd3490a48be99a",
+    "0e08bceaeec81a",
+    "9b0d183dbbbbf3",
+    "7788f601c07e57",
+    "4e7271a716e4aa",
+    "f510b293bec62a",
+    "16158c6a1f3c84",
+    "33656236296f06",
+    "a5438e67d72d80",
+};
+#else
+unsigned char test_keyr0[40][15];
+#endif
+
+#define M0_LENGTH       8
+#define BSTATUS_LENGTH  2
+#define KSV_LENGTH      5
+#define KSV_RESERVED  3
+#define KEY_COL_LENGTH 7
+#define KEY_ARRAY_LENGTH 40
+#define KEY_LENGTH      280
+#define VERIFY_LENGTH 20
+#define MAX_SHA_1_INPUT_LENGTH  704
+
+#define MISC_INFO_TYPE_HDCP             STORAGE_DATA_TYPE_HDCP
+
+#define swapl(x)	((((x)&0x000000ff)<<24)+(((x)&0x0000ff00)<<8)+(((x)&0x00ff0000)>>8)+(((x)&0xff000000)>>24))
+#define SXOLN(n,x)	((x<<n)|(x>>(32-n)))    //x leftrotate n
+#define SXORN(n,x)	((x>>n)|(x<<(32-n)))    //x rightrotate n
+#define hLen    20   //sha_1 160bit
+
+int hdcp_timer_interval = 50;       
+int hdcp_timer_error_interval = 100;
+
+//store aksv key
+void hdcp_set_aksv(unsigned char* _aksv) {
+    int i = 0;
+    for (i = 0; i < 5; i++) {
+        aksv[i] = _aksv[i];
+    }
+}
+
+//key
+void hdcp_set_key(unsigned char *key) {
+    int i = 0, j = 0;
+    for (j = 0; j < 40; j++) {
+        for (i = 0; i < 7; i++) {
+            key_r0[j][i] = key[j * 7 + i];
+        }
+    }
+}
+
+
+int hdcp_anlay_SRM(unsigned char *srm, unsigned char *srm_buf) {
+    unsigned int tmp = 0;
+    int j = 0, i = 0, k = 0;
+    if (srm != NULL) {
+        tmp = srm[0];
+    }
+    if ((srm != NULL) && (srm_buf != NULL)) {
+        if ((tmp & 0x80) != 0) { //hdcp flag
+            tmp = srm[8];
+            HDCP_DEBUG("there are %d device Number\n", tmp);
+            for (i = 1; i <= (int) tmp; i++) {
+                for (j = 4; j >= 0; j--) {
+                    srm_buf[j + (i - 1) * 5] = srm[9 + k];
+                    k++;
+                }
+            }
+
+            return tmp;
+        } else {
+            return -1;
+        }
+    } else {
+        return -1;
+    }
+
+}
+
+
+/*
+  * check if Bksv is valid, need have 20 "1"  and 20 "0"
+  */
+int Check_Bksv_Invalid(void) {
+    int i, j;
+    unsigned char counter = 0;
+    unsigned char invalid_bksv[4][5] = {
+        {0x0b,0x37,0x21,0xb4,0x7d},
+        {0xf4,0xc8,0xde,0x4b,0x82},
+        {0x23,0xde,0x5c,0x43,0x93},
+        {0x4e,0x4d,0xc7,0x12,0x7c},
+    };
+
+    for (i = 0; i < 5; i++) {
+        for (j = 0; j < 8; j++) {
+            if (((hdmi.ip_data.hdcp.Bksv[i] >> j) & 0x1) != 0) {
+                counter++;
+            }
+        }
+    }
+
+    if (counter != 20) {
+        DEBUG_ERR("[%s]fail  0x%x 0x%x 0x%x 0x%x 0x%x\n", __func__, hdmi.ip_data.hdcp.Bksv[0], hdmi.ip_data.hdcp.Bksv[1], \
+		hdmi.ip_data.hdcp.Bksv[2], hdmi.ip_data.hdcp.Bksv[3], hdmi.ip_data.hdcp.Bksv[4]);
+        return 0;
+    }
+
+    for (i = 0; i < 4; i++) {
+        for(j = 0; j < 5; j++) {
+            if (invalid_bksv[i][j] != hdmi.ip_data.hdcp.Bksv[j]) {
+                break;
+            }
+			if(j==4)
+				return 0;
+        }
+    }
+
+    HDCP_DEBUG("[%s]successful!\n", __func__);
+    return 1;
+}
+
+
+unsigned char sha_1(unsigned char *sha_output, unsigned char *M_input, int len) {
+    unsigned int Kt[4] = {
+        0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6 
+    };
+    
+    unsigned int h[5] = {
+        0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476,0xc3d2e1f0 
+    };
+
+    int t, n, n_block;
+    unsigned int Ft, x, temp;
+    unsigned int A, B, C, D, E;
+    int i, j;
+    unsigned char *sha_input;
+    unsigned char *out_temp;
+    unsigned int W[80];
+	sha_input=kmalloc(700, GFP_KERNEL);
+	if(NULL==sha_input)
+	{
+		return ENOMEM;
+	}
+    memset(sha_input, 0, 700);
+
+    for (i = 0; i < len; i++)
+        sha_input[i] = M_input[i];
+
+    /* do message padding */
+    n_block = (len * 8 + 1 + 64) / 512 + 1;
+    sha_input[len] = 0x80;
+    HDCP_DEBUG("n_block=%d\n", n_block);
+    /* set len */
+
+    sha_input[(n_block - 1) * 64 + 60] = (unsigned char)(
+            ((len * 8) & 0xff000000) >> 24);
+    sha_input[(n_block - 1) * 64 + 61] = (unsigned char)(
+            ((len * 8) & 0x00ff0000) >> 16);
+    sha_input[(n_block - 1) * 64 + 62] = (unsigned char)(((len * 8) & 0x0000ff00) >> 8);
+    sha_input[(n_block - 1) * 64 + 63] = (unsigned char)((len * 8) & 0x000000ff);
+
+    for (j = 0; j < n_block; j++) {
+        HDCP_DEBUG("\nBlock %d\n", j);
+        for (i = 0; i < 64; i++) {
+            if ((i % 16 == 0) && (i != 0))
+                HDCP_DEBUG("\n0x%2x,", sha_input[j * 64 + i]);
+            else
+                HDCP_DEBUG("0x%2x,", sha_input[j * 64 + i]);
+        }
+    }
+    HDCP_DEBUG("SHA sha_input end\n");
+
+    for (n = 0; n < n_block; n++) {
+        for (t = 0; t < 16; t++) {
+            x = *((unsigned int *) &sha_input[n * 64 + t * 4]);
+            W[t] = swapl(x);
+//          if (t%2 == 0)
+//              HDCP_DEBUG("\n");
+//          HDCP_DEBUG("x=0x%x,W[%d]=0x%x\t",x,t,W[t]);
+        }
+//      HDCP_DEBUG("\n");   
+        for (t = 16; t < 80; t++) {
+            x = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
+            W[t] = SXOLN(1, x);
+//          HDCP_DEBUG("W[%d]=0x%x\t",t,W[t]);
+//          if (t % 3 == 0)
+//              HDCP_DEBUG("\n");
+        }
+
+        A = h[0];
+        B = h[1];
+        C = h[2];
+        D = h[3];
+        E = h[4];
+
+        for (t = 0; t < 80; t++) {
+            if (t >= 0 && t <= 19)
+                Ft = (B & C) | ((~B) & D);
+            else if (t >= 20 && t <= 39)
+                Ft = B ^ C ^ D;
+            else if (t >= 40 && t <= 59)
+                Ft = (B & C) | (B & D) | (C & D);
+            else
+                Ft = (B ^ C ^ D);
+
+            temp = SXOLN(5, A) + Ft + E + W[t] + Kt[t / 20]; //temp = S^5(A) + f(t;B,C,D) + E + W(t) + K(t)
+
+            E = D;
+            D = C;
+            C = SXOLN(30, B); //C = S^30(B)
+            B = A;
+            A = temp;
+        }
+
+        h[0] += A; // H0 = H0 + A
+        h[1] += B; // H1 = H1 + B
+        h[2] += C; //H2 = H2 + C
+        h[3] += D; //H3 = H3 + D
+        h[4] += E; //H4 = H4 + E
+    }
+
+    HDCP_DEBUG("\noutput original sha_input:\n");
+    for (i = 0; i < hLen / 4; i++)
+        HDCP_DEBUG("0x%x\t", h[i]);
+
+    HDCP_DEBUG("\nconvert to little endien\n");
+    for (i = 0; i < hLen / 4; i++) {
+        h[i] = swapl(h[i]);
+        HDCP_DEBUG("0x%x\t", h[i]);
+    }
+    HDCP_DEBUG("\n");
+
+    /* copy to output pointer */
+    out_temp = (unsigned char *) h;
+    HDCP_DEBUG("out_temp:\n");
+    for (i = 0; i < hLen; i++) {
+        sha_output[i] = out_temp[i];
+        HDCP_DEBUG("0x%x\t", out_temp[i]);
+    }
+    HDCP_DEBUG("\n");
+	kfree(sha_input);
+    return 0;
+}
+
+int check_one_number(unsigned char data)
+{
+    int num = 0, i;
+    for(i=0;i<8;i++) {
+	if ((data >> i) & 0x1) {
+		num ++;
+	}
+    }
+    return num;
+}
+
+int hdcp_SetKm(unsigned char *key, int pnt) {
+    unsigned int tmp;
+    unsigned char dKey[11];
+    dKey[0] = key[0] ^ pnt;
+    dKey[1] = ~key[1] ^ dKey[0];
+    dKey[2] = key[2] ^ dKey[1];
+    dKey[3] = key[3] ^ dKey[2];
+    dKey[4] = key[4] ^ dKey[3];
+    dKey[5] = ~key[5] ^ dKey[4];
+    dKey[6] = ~key[6] ^ dKey[5];
+    /* write to HW */
+    /*P_HDCP_DPKLR*/
+    tmp = pnt | (dKey[0] << 8) | (dKey[1] << 16) | (dKey[2] << 24);
+	//HDCP_DEBUG("gl+++ km %x\n", tmp);
+    owl_hdmi_write(tmp, HDCP_DPKLR);
+    /*P_HDCP_DPKMR*/
+    tmp = dKey[3] | (dKey[4] << 8) | (dKey[5] << 16) | (dKey[6] << 24);
+	//HDCP_DEBUG("gl+++ km %x\n", tmp);
+    owl_hdmi_write(tmp, HDCP_DPKMR);
+
+    /* trigger accumulation */
+
+    while (!(owl_hdmi_read(HDCP_SR) & (1 << 3)))
+        ;
+    return 0;
+}
+
+int hdcp_ReadKsvList(unsigned char *Bstatus, unsigned char *ksvlist) {
+    int cnt;
+
+    /* get device count in Bstatus [6:0] */
+    if (i2c_hdcp_read(Bstatus, 0x41, 2) < 0) {
+        if (i2c_hdcp_read(Bstatus, 0x41, 2) < 0) {
+            return 0;
+        }
+    }
+
+    if (Bstatus[0] & 0x80) //if Max_devs_exceeded then quit
+        return 0;
+
+    if (Bstatus[1] & 0x8) //if Max_cascade_exceeded then quit
+        return 0;
+
+    cnt = Bstatus[0] & 0x7f;
+
+    if (!cnt) {
+        return 1;
+    }
+
+    if (i2c_hdcp_read(ksvlist, 0x43, 5 * cnt) < 0) {
+        if (i2c_hdcp_read(ksvlist, 0x43, 5 * cnt) < 0) {
+            return 0;
+        }
+    }
+
+    return 1;
+}
+
+/* convert INT8 number to little endien number */
+int c2ln14(unsigned char *num, char *a) {
+    int i;
+    int n = 14;
+    for (i = 0; i < 11; i++) {
+        num[i] = 0;
+    }
+
+    for (i = 0; i < n; i++) {
+        if (i % 2) {
+            if (a[n - i - 1] >= '0' && a[n - i - 1] <= '9') {
+                num[i / 2] |= (a[n - i - 1] - '0') << 4;
+            } else if (a[n - i - 1] >= 'a' && a[n - i - 1] <= 'f') {
+                num[i / 2] |= (a[n - i - 1] - 'a' + 10) << 4;
+            } else if (a[n - i - 1] >= 'A' && a[n - i - 1] <= 'F') {
+                num[i / 2] |= (a[n - i - 1] - 'A' + 10) << 4;
+            }
+        } else {
+            if (a[n - i - 1] >= '0' && a[n - i - 1] <= '9') {
+                num[i / 2] |= (a[n - i - 1] - '0');
+            } else if (a[n - i - 1] >= 'a' && a[n - i - 1] <= 'f') {
+                num[i / 2] |= (a[n - i - 1] - 'a' + 10);
+            } else if (a[n - i - 1] >= 'A' && a[n - i - 1] <= 'F') {
+                num[i / 2] |= (a[n - i - 1] - 'A' + 10);
+            }
+        }
+    }
+    return 0;
+}
+
+
+extern int read_mi_item(char *name, void *buf, unsigned int count);
+
+int hdcp_read_key(void)
+{
+    int array, col, index;
+    int num = 0;
+    int i = 0;
+	int ret;
+    unsigned char key[308];
+    unsigned char sha1_verify[20];
+    unsigned char sha1_result[20];
+	
+#ifdef READ_HDCP_KEY_FROM_NATIVE
+	return 0;
+#endif		
+
+    ret =  read_mi_item("HDCP", key, sizeof(key));
+    if (ret < 0) {
+        DEBUG_ERR("failed to read hdcp key from secure storage\n");
+		return ret;
+    }
+	printk("hdcp key cnt %d\n", ret);
+
+    for (i =1; i < sizeof(aksv); i++) {
+        aksv[i] = key[i -1];
+    }
+
+    for (i = 0; i < KSV_LENGTH; i++) {
+        num += check_one_number(key[i]);
+    }
+    
+    //key
+    if (num == 20) {
+    	HDCP_DEBUG("aksv is valid\n");
+		HDCP_DEBUG("hdcp key is as follows:\n");
+		for (array = 0; array < KEY_ARRAY_LENGTH; array++) {
+			 for (col = 0; col < KEY_COL_LENGTH; col++) {
+				index = (KSV_LENGTH + KSV_RESERVED + (array + 1) * KEY_COL_LENGTH) - col - 1;
+				sprintf(&test_keyr0[array][2 * col], "%x", ((key[index] & 0xf0) >> 4) & 0x0f);
+				sprintf(&test_keyr0[array][2 * col +1], "%x", key[index] & 0x0f);
+
+				HDCP_DEBUG("key_tmp[%d][%d]:%c\n", array, 2 * col, test_keyr0[array][2 * col]);
+				HDCP_DEBUG("key_tmp[%d][%d]:%c\n", array, 2 * col + 1, test_keyr0[array][2 * col + 1]);
+			}
+			HDCP_DEBUG("%s\n", test_keyr0[array]);
+		}
+        HDCP_DEBUG("\n\nhdcp key parse finished\n\n");
+        HDCP_DEBUG("verify code is as follows:\n");
+        for (i = 0; i < sizeof(sha1_verify); i++) {
+	        index = i + KSV_LENGTH + KSV_RESERVED + KEY_LENGTH;
+            sha1_verify[i] = key[index];
+	        HDCP_DEBUG("sha1_verify[%d]:%x\n", i, sha1_verify[i]);
+        }
+        HDCP_DEBUG("verify code parse finished\n\n");
+        if(sha_1(sha1_result, key, KSV_LENGTH + KSV_RESERVED + KEY_LENGTH))
+        {
+			HDCP_DEBUG("aksv kmalloc mem is failed\n");
+			return 1;
+	    }
+
+    } else {
+    	HDCP_DEBUG("aksv is invalid\n");
+        return 1;
+    }
+    
+    //verify
+    for(i = 0; i < VERIFY_LENGTH; i++) {
+		if (sha1_verify[i] != sha1_result[i]) {
+			DEBUG_ERR("sha1 verify error!\n");
+			return 1;
+		}
+    }
+    HDCP_DEBUG("[%s]sha1 verify success !\n", __func__);
+    return 0; 
+}
+
+int do_Vmatch(struct hdmi_ip_data *ip_data, unsigned char *v, unsigned char *ksvlist, unsigned char *bstatus,
+        unsigned char * m0) {
+    unsigned int tmp;
+    int data_counter;
+    unsigned char sha_1_input_data[MAX_SHA_1_INPUT_LENGTH];
+    int nblock, llen;
+    int cnt2 = ip_data->hdcp.Bstatus[0] & 0x7f;
+    int i, j;
+    volatile int hdcp_shacr = 0;
+
+    llen = 8 * M0_LENGTH + 8 * BSTATUS_LENGTH + cnt2 * 8 * KSV_LENGTH;
+
+    for (i = 0; i < MAX_SHA_1_INPUT_LENGTH; i++)
+        sha_1_input_data[i] = 0;
+
+    for (data_counter = 0;
+            data_counter < cnt2 * KSV_LENGTH + BSTATUS_LENGTH + M0_LENGTH;
+            data_counter++) {
+        if (data_counter < cnt2 * KSV_LENGTH) {
+            sha_1_input_data[data_counter] = ksvlist[data_counter];
+
+        } else if ((data_counter >= cnt2 * KSV_LENGTH)
+                && (data_counter < cnt2 * KSV_LENGTH + BSTATUS_LENGTH)) {
+            sha_1_input_data[data_counter] = bstatus[data_counter
+                    - (cnt2 * KSV_LENGTH)];
+        } else {
+            sha_1_input_data[data_counter] = m0[data_counter
+                    - (cnt2 * KSV_LENGTH + BSTATUS_LENGTH)];
+        }
+    }
+    sha_1_input_data[data_counter] = 0x80; //block ending signal       
+
+    nblock = (int) (data_counter / 64);
+    sha_1_input_data[nblock * 64 + 62] = (unsigned char) (((data_counter * 8)
+            >> 8) & 0xff); //total SHA counter high
+    sha_1_input_data[nblock * 64 + 63] = (unsigned char) ((data_counter * 8)
+            & 0xff); //total SHA counter low
+
+    //  P_HDCP_SHACR |= 0x1;    //reset SHA write pointer
+    tmp = owl_hdmi_read(HDCP_SHACR);
+    owl_hdmi_write(tmp | 0x1, HDCP_SHACR);
+
+    while (owl_hdmi_read(HDCP_SHACR) & 0x1); //wait completing reset operation
+    //  P_HDCP_SHACR |= 0x2;            //set new SHA-1 operation
+    tmp = owl_hdmi_read(HDCP_SHACR);
+    owl_hdmi_write(tmp | 0x2, HDCP_SHACR);
+
+    for (i = 0; i < nblock; i++) {
+        for (j = 0; j < 16; j++) {
+            //P_HDCP_SHADR 
+            tmp = (sha_1_input_data[i * 64 + (j * 4 + 0)] << 24)
+                    | (sha_1_input_data[i * 64 + (j * 4 + 1)] << 16)
+                    | (sha_1_input_data[i * 64 + (j * 4 + 2)] << 8)
+                    | (sha_1_input_data[i * 64 + (j * 4 + 3)]);
+            owl_hdmi_write(tmp, HDCP_SHADR);
+            owl_hdmi_read(HDCP_SHADR);
+        }
+        //      P_HDCP_SHACR |= 0x4;         //Start 512bit SHA operation           
+        tmp = owl_hdmi_read(HDCP_SHACR);
+        owl_hdmi_write(tmp | 0x4, HDCP_SHACR);
+        while (!(owl_hdmi_read(HDCP_SHACR) & 0x8))
+            ; //after 512bit SHA operation, this bit will be set to 1
+
+        //P_HDCP_SHACR &= 0xfd;                       //clear SHAfirst bit
+        tmp = owl_hdmi_read(HDCP_SHACR);
+        owl_hdmi_write(tmp & 0xfd, HDCP_SHACR);
+        owl_hdmi_read(HDCP_SHACR);
+    }
+    for (j = 0; j < 16; j++) {
+        // P_HDCP_SHADR 
+        tmp = (sha_1_input_data[nblock * 64 + (j * 4 + 0)] << 24)
+                | (sha_1_input_data[nblock * 64 + (j * 4 + 1)] << 16)
+                | (sha_1_input_data[nblock * 64 + (j * 4 + 2)] << 8)
+                | (sha_1_input_data[nblock * 64 + (j * 4 + 3)]);
+        owl_hdmi_write(tmp, HDCP_SHADR);
+        owl_hdmi_read(HDCP_SHADR);
+    }
+    //P_HDCP_SHACR |= 0x4;                        //Start 512bit SHA operation        
+    tmp = owl_hdmi_read(HDCP_SHACR);
+    owl_hdmi_write(tmp | 0x4, HDCP_SHACR);
+
+    while (!(owl_hdmi_read(HDCP_SHACR) & 0x8))
+        ; //after 512bit SHA operation, this bit will be set to 1
+    //write V
+    //P_HDCP_SHADR 
+    tmp = (v[3] << 24) | (v[2] << 16) | (v[1] << 8) | (v[0] << 0);
+    owl_hdmi_write(tmp, HDCP_SHADR);
+    owl_hdmi_read(HDCP_SHADR);
+
+    //P_HDCP_SHADR 
+    tmp = (v[7] << 24) | (v[6] << 16) | (v[5] << 8) | (v[4] << 0);
+    owl_hdmi_write(tmp, HDCP_SHADR);
+    owl_hdmi_read(HDCP_SHADR);
+
+    //P_HDCP_SHADR 
+    tmp = (v[11] << 24) | (v[10] << 16) | (v[9] << 8) | (v[8] << 0);
+    owl_hdmi_write(tmp, HDCP_SHADR);
+    owl_hdmi_read(HDCP_SHADR);
+
+    //P_HDCP_SHADR 
+    tmp = (v[15] << 24) | (v[14] << 16) | (v[13] << 8) | (v[12] << 0);
+    owl_hdmi_write(tmp, HDCP_SHADR);
+    owl_hdmi_read(HDCP_SHADR);
+
+    //P_HDCP_SHADR 
+    tmp = (v[19] << 24) | (v[18] << 16) | (v[17] << 8) | (v[16] << 0);
+    owl_hdmi_write(tmp, HDCP_SHADR);
+    owl_hdmi_read(HDCP_SHADR);
+
+    //wait Vmatch
+
+    for (i = 0; i < 3; i++) {
+        j = 0;
+        while ((j++) < 100)
+            ;
+        hdcp_shacr = owl_hdmi_read(HDCP_SHACR);
+        if (hdcp_shacr & 0x10) {
+            return 1; //Vmatch
+        }
+    }
+    return 0; //V unmatch
+
+}
+
+
+/*\B6\C1ȡM0\B5\C4ǰ4\D7ֽ\DA*/
+void hdcp_read_hdcp_MILR(unsigned char *M0) {
+    unsigned int tmp = 0;
+    tmp = owl_hdmi_read(HDCP_MILR);
+    M0[0] = (unsigned char) (tmp & 0xff);
+    M0[1] = (unsigned char) ((tmp >> 8) & 0xff);
+    M0[2] = (unsigned char) ((tmp >> 16) & 0xff);
+    M0[3] = (unsigned char) ((tmp >> 24) & 0xff);
+}
+/*\B6\C1ȡM0\B5ĺ\F34\D7ֽ\DA*/
+void hdcp_read_hdcp_MIMR(unsigned char *M0) {
+    unsigned int tmp = 0;
+    tmp = owl_hdmi_read(HDCP_MIMR);
+    M0[0] = (unsigned char) (tmp & 0xff);
+    M0[1] = (unsigned char) ((tmp >> 8) & 0xff);
+    M0[2] = (unsigned char) ((tmp >> 16) & 0xff);
+    M0[3] = (unsigned char) ((tmp >> 24) & 0xff);
+}
+
+void hdcp_set_out_opportunity_window(void)
+{
+	/*42,end 651,star 505 */
+	owl_hdmi_write(HDCP_KOWR_HDCPREKEYKEEPOUTWIN(0x2a) |
+		   HDCP_KOWR_HDCPVERKEEPOUTWINEND(0x28b) |
+		   HDCP_KOWR_HDCPVERTKEEPOUTWINSTART(0x1f9), HDCP_KOWR);
+	/*HDCP1.1 Mode: start 510,end 526 */
+	owl_hdmi_write(HDCP_OWR_HDCPOPPWINEND(0x20e) |
+		   HDCP_OWR_HDCPOPPWINSTART(0x1fe), HDCP_OWR);
+
+}
+
+static void hdcp_launch_authen_seq(void)
+{
+	int i = 6;
+	
+	hdcp_set_out_opportunity_window();
+	while ((owl_hdmi_read(HDMI_LPCR) & HDMI_LPCR_CURLINECNTR) == 0 && i < 65) {
+		udelay(1);
+		i++;
+	}
+	if( i > 64) {
+		DEBUG_ERR( "hdcp:HDMI_LPCR_CURLINECNTR timeout!\n");
+	}
+	i=6;
+	while ((owl_hdmi_read(HDMI_LPCR) & HDMI_LPCR_CURLINECNTR) != 0 && i < 65) {
+		udelay(1);
+		i++;
+	}
+	/*set Ri/Pj udpdate:128,16 */
+	owl_hdmi_write(HDCP_ICR_RIRATE(0x7f) | HDCP_ICR_PJRATE(0x0f), HDCP_ICR);
+		
+}
+
+void set_hdcp_ri_pj(void) {
+	int tmp;
+	HDCP_DEBUG("set_hdcp_ri_pj   ~~\n");
+	owl_hdmi_write(0x7f0f, HDCP_ICR);
+	
+	tmp = owl_hdmi_read(HDCP_CR);
+    tmp &=  (~HDCP_CR_ENRIUPDINT);
+	tmp &=  (~HDCP_CR_ENPJUPDINT);
+	tmp &=  (~HDCP_CR_HDCP_ENCRYPTENABLE);
+	tmp |=  HDCP_CR_FORCETOUNAUTHENTICATED;
+    owl_hdmi_write(tmp, HDCP_CR);
+	
+	tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_EN1DOT1_FEATURE;
+    owl_hdmi_write(tmp, HDCP_CR);
+	
+
+	HDCP_DEBUG("end set_hdcp_ri_pj  temp %x ~~\n", tmp);
+}
+
+int hdcp_get_ri(struct hdmi_ip_data *ip_data)
+{
+	ip_data->hdcp.Ri = (owl_hdmi_read(HDCP_LIR) >> 16) & 0xffff;
+	HDCP_DEBUG("[%s Ri(master):0x%x]\n", __func__, ip_data->hdcp.Ri);
+
+	return ip_data->hdcp.Ri;
+}
+
+int hdcp_check_ri(void) {
+    int Ri, Ri_Read;
+    unsigned char Ri_temp[8] = {0};
+	HDCP_DEBUG("start hdcp_check_ri\n");
+    Ri = (owl_hdmi_read(HDCP_LIR) >> 16) & 0xffff;
+    if (i2c_hdcp_read(Ri_temp, 0x08, 2) == 0) {
+        memset(Ri_temp, 0, sizeof(Ri_temp)); 
+    }
+    Ri_Read = (Ri_temp[1] << 8) | Ri_temp[0];
+	HDCP_DEBUG("start hdcp_check_ri ri%x  riread%x\n", Ri, Ri_Read);
+    if (Ri != Ri_Read) {
+		set_hdcp_ri_pj();
+		hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+		queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi.ip_data.hdcp.hdcp_work,
+                msecs_to_jiffies(3000));
+        return -1;
+    }
+    return 0;
+}
+
+
+int hdcp_GenKm(struct hdmi_ip_data *ip_data) 
+{
+    unsigned char key[11];
+    int i, j;
+	//test_hdcp_key();
+	for(i=0;i<30;i++)
+	HDCP_DEBUG("test_keyr0  %d %d\n", i, test_keyr0[0][i]);
+
+ for (i = 0; i < 5; i++) {
+        for (j = 0; j < 8; j++) {
+            if (ip_data->hdcp.Bksv[i] & (1 << j)) {
+                c2ln14(key, test_keyr0[i * 8 + j]);
+                hdcp_SetKm(&key[0], 0x55);
+            }
+        }
+    }
+    return 0;
+}
+
+
+
+int hdcp_ReadVprime(unsigned char *Vp) {
+    /* read Vp */
+    if (i2c_hdcp_read(Vp, 0x20, 20) != 0) {
+        if (i2c_hdcp_read(Vp, 0x20, 20) != 0) {
+            return 0;
+        }
+    }
+    return 1;
+}
+
+
+
+int hdcp_AuthenticationSequence(struct hdmi_ip_data *ip_data) {
+    /* force Encryption disable */
+    //  P_HDCP_CR &= ~HDCP_CR_ENC_ENABLE; //6 bit
+    /* reset Km accumulation */
+    //  P_HDCP_CR |= HDCP_CR_RESET_KM_ACC; //4 bit
+	int i;
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp = (tmp & (~HDCP_CR_HDCP_ENCRYPTENABLE)) | HDCP_CR_RESETKMACC;
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    /* set Bksv to accumulate Km */
+    hdcp_GenKm(ip_data);
+
+    /* disable Ri update interrupt */
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp &= (~HDCP_CR_ENRIUPDINT);
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    /* clear Ri updated pending bit */
+    tmp = owl_hdmi_read(HDCP_SR);
+    tmp |= HDCP_SR_RIUPDATED;
+    owl_hdmi_write(tmp, HDCP_SR);
+	
+	tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_AUTHCOMPUTE;
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    /* trigger hdcpBlockCipher at authentication */
+    //  P_HDCP_CR |= HDCP_CR_AUTH_COMP; //1 bit
+    /* wait 48+56 pixel clock to get R0 */
+    //  while(!(P_HDCP_SR & HDCP_SR_RI_UPDATE));
+	HDCP_DEBUG("  while (!(owl_hdmi_read(HDCP_SR) & HDCP_SR_RIUPDATED)\n");
+	i = 100;
+    while ((!(owl_hdmi_read(HDCP_SR) & HDCP_SR_RIUPDATED))&&(i--)){
+		mdelay(1);
+    }
+		HDCP_DEBUG("  while (!(owl_hdmi_read(HDCP_SR) & HDCP_SR_RIUPDATED)  end  %d\n", i);
+    //HDCP_DEBUG("wait Ri\n");
+    /* get Ri */
+    ip_data->hdcp.Ri = (owl_hdmi_read(HDCP_LIR) >> 16) & 0xffff;
+    HDCP_DEBUG("Ri:0x%x\n", ip_data->hdcp.Ri);
+
+    return 0;
+}
+
+//
+int hdcp_FreeRunGetAn(unsigned char *an) {
+    /* Get An */
+    /* get An influence from CRC64 */
+    unsigned int tmp;
+    int i;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_ANINFREQ ;
+    owl_hdmi_write(tmp, HDCP_CR);
+	
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_ANINFLUENCEMODE;
+    owl_hdmi_write(tmp, HDCP_CR);	
+	
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_AUTHREQUEST;
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    //P_HDCP_CR |= HDCP_CR_AN_INF_REQ; //25 bit
+
+    /* set An Influence Mode, influence will be load from AnIR0, AnIR1 */
+    //P_HDCP_CR |= HDCP_CR_LOAD_AN;  //7 bit
+    /* trigger to get An */
+    //P_HDCP_CR |= HDCP_CR_AUTH_REQ;  //0 bit  --д1\A3\AC\C9\FA\B3\C9an
+    HDCP_DEBUG("[hdcp_FreeRunGetAn]:wait An\n");
+	i=100;
+    while (!(owl_hdmi_read(HDCP_SR) & (HDCP_SR_ANREADY))&&(i--)){
+		udelay(1);
+	} //\B5ȴ\FDAn ready
+
+    HDCP_DEBUG("[hdcp_FreeRunGetAn]:wait An ok\n");
+    /* leave An influence mode */
+    tmp = owl_hdmi_read(HDCP_CR);
+
+    tmp &= (~HDCP_CR_ANINFLUENCEMODE);
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    /* 
+     * Convert HDCP An from bit endien to little endien 
+     * HDCP An should stored in little endien, 
+     * but HDCP HW store in bit endien. 
+     */
+    an[0] = 0x18;
+    tmp = owl_hdmi_read(HDCP_ANLR);
+    an[1] = tmp & 0xff;
+    an[2] = (tmp >> 8) & 0xff;
+    an[3] = (tmp >> 16) & 0xff;
+    an[4] = (tmp >> 24) & 0xff;
+
+    tmp = owl_hdmi_read(HDCP_ANMR);
+
+    an[5] = tmp & 0xff;
+    an[6] = (tmp >> 8) & 0xff;
+    an[7] = (tmp >> 16) & 0xff;
+    an[8] = (tmp >> 24) & 0xff;
+
+    for (i = 0; i < 9; i++)
+        HDCP_DEBUG("an[%d]:0x%x\n", i, an[i]);
+    
+    return 0;
+}
+
+
+void hdcp_ForceUnauthentication(void)
+{
+    /* disable link integry check */
+    /* force Encryption disable */
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp = (tmp & (~HDCP_CR_ENRIUPDINT) & (~HDCP_CR_ENPJUPDINT) & (~HDCP_CR_HDCP_ENCRYPTENABLE))
+            | HDCP_CR_FORCETOUNAUTHENTICATED;
+    owl_hdmi_write(tmp, HDCP_CR);
+    owl_hdmi_read(HDCP_CR);
+    /* force HDCP module to unauthenticated state */
+    //P_HDCP_CR |= HDCP_CR_FORCE_UNAUTH;
+}
+
+void enable_hdcp_repeater(void)
+{
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_DOWNSTRISREPEATER;
+    owl_hdmi_write(tmp, HDCP_CR);
+    tmp = owl_hdmi_read(HDCP_CR);
+}
+
+int check_ri_irq(void)
+{
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_SR);
+	HDCP_DEBUG("HDCP_SR 0x%x\n", tmp);
+	if(tmp&HDCP_SR_RIUPDATED)
+	{
+		tmp |= HDCP_SR_RIUPDATED;
+		tmp |= HDCP_SR_PJUPDATED;
+		owl_hdmi_write(tmp, HDCP_SR);	
+		return 1;
+	}
+	return 0;
+}
+
+void disable_hdcp_repeater(void)
+{
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp &= (~HDCP_CR_DOWNSTRISREPEATER);
+    owl_hdmi_write(tmp, HDCP_CR);
+    tmp = owl_hdmi_read(HDCP_CR);
+}
+
+void enable_ri_update_check(void)
+{
+    unsigned int tmp;
+	
+    tmp = owl_hdmi_read(HDCP_SR);
+    tmp |= HDCP_SR_RIUPDATED;
+    owl_hdmi_write(tmp, HDCP_SR);
+
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_ENRIUPDINT;
+    owl_hdmi_write(tmp, HDCP_CR);
+    owl_hdmi_read(HDCP_CR);
+}
+
+void set_hdcp_to_Authenticated_state(void)
+{
+    // Authenticated 
+    // set HDCP module to authenticated state 
+    unsigned int tmp;
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_DEVICEAUTHENTICATED;
+    owl_hdmi_write(tmp, HDCP_CR);
+    // start encryption    
+    tmp = owl_hdmi_read(HDCP_CR);
+    tmp |= HDCP_CR_HDCP_ENCRYPTENABLE;
+    owl_hdmi_write(tmp, HDCP_CR);
+
+    tmp = owl_hdmi_read(HDCP_CR);
+}
+
+void hdcp_check_handle(struct work_struct *work) {
+    unsigned char An[9] = {0};
+    unsigned char Bcaps = 0, Ri_temp[8] = {0};
+
+	//hdcp_launch_authen_seq();
+	
+	if((owl_hdmi_read(HDMI_CR)&0x01)&&(owl_hdmi_read(HDMI_CR)&(0x01<<29))){
+	
+	}else{
+		HDCP_CASE("hdmi plug out in hdcp\n");	
+		set_hdcp_ri_pj();
+		hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+		return ;		
+	}
+	
+	if(owl_hdmi_read(HDMI_GCPCR)&0x01){
+		HDCP_CASE("owl_hdmi_read(HDCP_GCPCR)&0x01 is true 0x%x\n", owl_hdmi_read(HDMI_GCPCR));	
+		set_hdcp_ri_pj();
+		hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+		return ;
+	}
+	
+	if(aksv[0] == 0x00 && aksv[1] == 0x00 && aksv[2] ==	0x00 &&	aksv[3]	== 0x00	&& aksv[4] == 0x00)
+	{
+		HDCP_CASE("aksv == 0\n");	
+		set_hdcp_ri_pj();
+		hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+		return ;
+	}
+	
+    HDCP_CASE("\n**********hdcp start guolong************ \n");
+    if(hdmi.ip_data.hdcp.hdcp_fail_times > HDCP_FAIL_TIMES) {//stop play
+        hdmi.ip_data.hdcp.hdcp_authentication_success = false;
+        HDCP_CASE("\n**********hdcp fail many times************ \n");
+        goto end;
+    }   
+
+    if((hdmi.ip_data.hdcp.need_to_delay -= 50) > 0) {
+        goto restart;
+    }
+
+    //state machine
+    switch (hdmi.ip_data.hdcp.hdcpOper_state) {
+    case HDCP_XMT_LINK_H0:
+        HDCP_CASE("************HDCP_XMT_LINK_H0*************\n");
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H1;
+
+    case HDCP_XMT_LINK_H1:
+        HDCP_CASE("************HDCP_XMT_LINK_H1*************\n");
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A0;
+	
+    /*
+     * Authentication phase 1: A0,A1,A2,A3
+     * A0.generate An, get Aksv;
+     * A1.write An and Aksv, read Bksv; 
+     * A2.get R0;
+     * A3.computes Km, Ks, M0 and R0;
+     *
+     * Authentication phase 2:  A6  or  A6,A8,A9,A91
+     * A6.check if sink support repeater, if not support repeater then authentication finish; 
+     * A8. check if  KSV is ready;
+     * A9:get KSV list;
+     * A91:compare V value;
+     *
+     * Authentication phase 3: A4,A5
+     * A4.set hdcp to Authenticated state;
+     * A5.authentication successful
+     */
+    case HDCP_XMT_AUTH_A0: //Authentication phase 1
+        HDCP_CASE("************HDCP_XMT_AUTH_A0*************\n");
+        /* genrate An, get Aksv */
+        hdmi.ip_data.hdcp.hdcpOper_retry = 0;
+        //get An value
+        hdcp_FreeRunGetAn(An);
+		msleep(10);
+       //send An
+        HDCP_CASE("************send An*************\n");
+
+        if (i2c_hdcp_write(&An[0], 0x18, 9) < 0) {
+            HDCP_DEBUG("\n Write An error \n"); 
+        }
+        //send aksv
+        HDCP_CASE("************send aksv*************\n");  
+
+        if (i2c_hdcp_write(aksv, 0x10, 6) < 0) {
+            HDCP_DEBUG("\n Write aksv error \n"); 
+        }
+
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A1;
+		//msleep(100);
+        hdmi.ip_data.hdcp.need_to_delay = 100;
+        break;
+
+    case HDCP_XMT_AUTH_A1://Authentication phase 1
+        HDCP_CASE("************HDCP_XMT_AUTH_A1*************\n");
+        /* 
+         * write An and Aksv, read Bksv 
+         * if get Bksv successful mean receiver/repeater support HDCP 
+         * check valid Bksv 20 ones and 20 zero 
+         */
+        HDCP_CASE("************read Bksv*************\n");
+        while (i2c_hdcp_read(hdmi.ip_data.hdcp.Bksv, 0x00, 5) < 0) {//if read successful, means support HDCP
+            hdmi.ip_data.hdcp.i2c_error++;
+            if (hdmi.ip_data.hdcp.i2c_error > 3) {
+                hdmi.ip_data.hdcp.i2c_error = 0;
+                HDCP_DEBUG("[631]Do not support HDCP \n");
+                break;
+            }
+        }
+		msleep(110);
+        HDCP_CASE("************Check_Bksv*************\n");
+        if (Check_Bksv_Invalid() == 0) {
+            hdmi.ip_data.hdcp.hdcp_fail_times++;
+            hdcp_ForceUnauthentication();
+            hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+            HDCP_DEBUG("\n Check_Bksv_Invalid \n");
+            hdmi.ip_data.hdcp.need_to_delay = 100;
+            break;
+        }
+
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A2;
+        hdmi.ip_data.hdcp.need_to_delay = 100;
+		//msleep(100);
+        break;
+   
+    case HDCP_XMT_AUTH_A2://Authentication phase 1
+        HDCP_CASE("************HDCP_XMT_AUTH_A2*************\n");
+        // Computations
+        // computes Km, Ks, M0 and R0   
+        HDCP_CASE("************read Bcaps*************\n");
+        if (i2c_hdcp_read(&Bcaps, 0x40, 1) < 0) {
+            HDCP_DEBUG("Read Bcaps error \n"); //error_handle();
+        }
+
+        if ((Bcaps & (1 << 6)) != 0) {
+            // set to support repeater 
+            HDCP_CASE("************support repeater*************\n");
+            hdmi.ip_data.hdcp.repeater = 1;
+            enable_hdcp_repeater();
+        } else {
+            // set to support NO repeater
+            HDCP_CASE("************dont  support repeater*************\n");
+            hdmi.ip_data.hdcp.repeater = 0;
+            disable_hdcp_repeater();
+        }
+        HDCP_CASE("************generate Ri*************\n");
+        hdcp_AuthenticationSequence(&hdmi.ip_data);
+        hdmi.ip_data.hdcp.hdcpOper_retry = 3; //add by keith
+
+        /* if computed results are available */
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A3;
+        //wait for 100 msec to read R0p.        
+        mdelay(130); // \BD\A8\D2鲻\B8\C4Ϊ\BFɵ\F7\B6\C8
+
+        break; //add by keith
+
+    case HDCP_XMT_AUTH_A3://Authentication phase 1
+        HDCP_CASE("************HDCP_XMT_AUTH_A3*************\n");
+        // Validate Receiver
+        // computes Km, Ks, M0 and R0
+        // if computed results are available
+         HDCP_DEBUG("************read R0*************\n");
+        if (i2c_hdcp_read(Ri_temp, 0x08, 2) < 0) {
+            memset(Ri_temp, 0, sizeof(Ri_temp)); 
+        }
+        hdmi.ip_data.hdcp.Ri_Read = (int) ((unsigned int) Ri_temp[1] << 8)
+                | Ri_temp[0];
+        HDCP_CASE("****Ri_Read:0x%x\n****", hdmi.ip_data.hdcp.Ri_Read);
+        if (hdmi.ip_data.hdcp.Ri != hdmi.ip_data.hdcp.Ri_Read) {
+            HDCP_DEBUG("\n R0 != Ri_Read \n");
+            if (hdmi.ip_data.hdcp.hdcpOper_retry != 0) {
+                hdmi.ip_data.hdcp.hdcpOper_retry--;
+                hdmi.ip_data.hdcp.need_to_delay = 100;
+            } else {
+                /* authentication part I failed */
+                hdmi.ip_data.hdcp.hdcp_fail_times++;
+                hdcp_ForceUnauthentication();
+                // restart
+                hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A0;
+                hdmi.ip_data.hdcp.need_to_delay = 200;
+            }
+            break;
+        }
+        //hdmi.ip_data.hdcp.hdcp_fail_times = 0;
+        hdmi.ip_data.hdcp.hdcpOper_retry = 0;
+        hdcp_read_hdcp_MILR(&hdmi.ip_data.hdcp.hdcpOper_M0[0]);
+        hdcp_read_hdcp_MIMR(&hdmi.ip_data.hdcp.hdcpOper_M0[4]);
+        // authentication part I successful 
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A6;
+
+    case HDCP_XMT_AUTH_A6://Authentication phase 2
+        HDCP_CASE("************HDCP_XMT_AUTH_A6*************\n");
+        // Test for Repeater
+        // get REPEATER
+        if (hdmi.ip_data.hdcp.repeater != 0) {
+            // change to Authentication part II 
+            hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A8;
+            /* wait 100msec */
+            hdmi.ip_data.hdcp.need_to_delay = 100;
+            hdmi.ip_data.hdcp.retry_times_for_set_up_5_second = 0;
+            break;
+        }
+
+        // NO repeater 
+        // change to Authentication part III
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A4;
+
+    case HDCP_XMT_AUTH_A4: ////Authentication phase 3
+        HDCP_CASE("************HDCP_XMT_AUTH_A4*************\n");
+        // Authenticated 
+        // set HDCP module to authenticated state      
+        // start encryption
+        set_hdcp_to_Authenticated_state();
+
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A5;
+        hdmi.ip_data.hdcp.hdcpOper_retry = 0;
+        // enable Ri update check
+
+        break;
+
+    case HDCP_XMT_AUTH_A5://Authentication phase 3
+        HDCP_CASE("************HDCP_XMT_AUTH_A5*************\n");
+        /* Link Integrity Check */
+        /* Interrupt and BH will do this job */
+        //hdmi.ip_data.hdcp.hdcp_fail_times = 0;
+        HDCP_CASE("********hdcp Authentication suceesful******** \n");
+        enable_ri_update_check();
+        hdmi.ip_data.hdcp.hdcp_authentication_success = true;
+        return;
+
+    case HDCP_XMT_AUTH_A8: ////Authentication phase 2
+        HDCP_CASE("************HDCP_XMT_AUTH_A8*************\n");
+        /* 2nd part authentication */
+        /* Wait for Ready */
+        /* set up 5 second timer poll for KSV list ready */
+        if ((hdmi.ip_data.hdcp.retry_times_for_set_up_5_second % 5) == 0) {
+            if (i2c_hdcp_read(&Bcaps, 0x40, 1) < 0) {
+                HDCP_DEBUG("\n Read Bcaps err \n"); 
+            }
+        }
+        if (!((Bcaps >> 5) & 0x1)) { //if KSVlist not ready!   
+            if (hdmi.ip_data.hdcp.retry_times_for_set_up_5_second <= 50) { //100 msec * 50 = 5 sec
+                hdmi.ip_data.hdcp.retry_times_for_set_up_5_second++;
+                hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A8;
+                /* wait 100msec */
+                hdmi.ip_data.hdcp.need_to_delay = 100;
+                break;
+            } else {
+                /* restart */
+                hdmi.ip_data.hdcp.hdcp_fail_times++;
+                hdmi.ip_data.hdcp.retry_times_for_set_up_5_second = 0;
+                hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A0;
+                hdcp_ForceUnauthentication();
+                /* wait 100msec */
+                hdmi.ip_data.hdcp.need_to_delay = 100;
+                HDCP_DEBUG("\n retry_times_for_set_up_5_second > 50 \n");
+                break;
+            }
+
+        }
+        //hdmi.ip_data.hdcp.hdcp_fail_times = 0;
+        hdmi.ip_data.hdcp.retry_times_for_set_up_5_second = 0;
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A9;
+
+    case HDCP_XMT_AUTH_A9://Authentication phase 2
+         HDCP_CASE("************HDCP_XMT_AUTH_A9*************\n");
+        /* Read KSV List and Bstatus */
+        //hdcp_ReadKsvList(&hdcpOper.Bstatus, hdcpOper.ksvList);//mark by keith
+        if (!hdcp_ReadKsvList(hdmi.ip_data.hdcp.Bstatus,
+                hdmi.ip_data.hdcp.ksvList)) { //add by keith
+            hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A0;
+            hdcp_ForceUnauthentication();
+            hdmi.ip_data.hdcp.hdcp_fail_times++;
+            HDCP_DEBUG("\n hdcp_ReadKsvList \n");
+            hdmi.ip_data.hdcp.need_to_delay = 100;
+
+            break;
+        }
+
+        hdmi.ip_data.hdcp.need_to_delay = 100;
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A9_1;
+        break;
+
+    case HDCP_XMT_AUTH_A9_1://Authentication phase 2
+        HDCP_CASE("************HDCP_XMT_AUTH_A9_1*************\n");
+        hdcp_ReadVprime(hdmi.ip_data.hdcp.Vp); //add by ciwu     
+        if (!do_Vmatch(&hdmi.ip_data, hdmi.ip_data.hdcp.Vp, hdmi.ip_data.hdcp.ksvList,
+                hdmi.ip_data.hdcp.Bstatus, hdmi.ip_data.hdcp.hdcpOper_M0)) {
+            /* compare with V' */
+            /* authentication part II failed */
+            hdmi.ip_data.hdcp.hdcp_fail_times++;
+            hdcp_ForceUnauthentication();
+            hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A0;
+
+            hdmi.ip_data.hdcp.need_to_delay = 100;
+            HDCP_DEBUG("\n do_Vmatch \n");
+            break;
+        }
+
+        /* KSV list correct , transit to Authentication Part III */
+        hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_AUTH_A4;
+        hdmi.ip_data.hdcp.need_to_delay = 100;
+        break;
+
+    default:
+        break;
+    }
+
+restart: 
+    queue_delayed_work(hdmi.ip_data.hdcp.wq,
+            &hdmi.ip_data.hdcp.hdcp_work, msecs_to_jiffies(hdcp_timer_interval));
+    return;
+    
+end: 
+    hdcp_ForceUnauthentication();
+    return;
+}
+
+void hdcp_init(void)
+{
+	hdmi.ip_data.hdcp.hdcpOper_state = HDCP_XMT_LINK_H0;
+	hdmi.ip_data.hdcp.hdcp_fail_times = 0;
+		
+	set_hdcp_ri_pj();
+	hdcp_launch_authen_seq();
+	hdcp_ForceUnauthentication();
+}
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi.c
new file mode 100755
index 0000000..2573849
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi.c
@@ -0,0 +1,1289 @@
+/*
+ * hdmi.c
+ *
+ * HDMI interface DSS driver setting for TI's OWL4 family of processor.
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors: Yong Zhi
+ *	Mythri pk <mythripk at ti.com>
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "HDMI"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+#include <linux/interrupt.h>
+#include <mach/switch.h>
+#include <mach/irqs.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/earlysuspend.h>
+#include <video/owldisplay.h>
+#include <asm/atomic.h>
+#include <linux/sched.h>    
+#include <linux/kthread.h> 
+#include <linux/timer.h>
+#include <linux/jiffies.h>
+
+#include <mach/clkname.h>
+#include <mach/module-owl.h>
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+
+#define SUSPEND_IN_DSS
+
+struct hdmi_core hdmi;
+
+struct timer_list hdmi_timer;
+
+struct switch_dev hdev = {
+	.name = "hdmi",
+};
+struct switch_dev hdev_audio = {
+	.name = "audio_hdmi",
+};
+struct hdmi_property
+{
+	int hdcp_onoff;
+	int channel_invert;
+	int bit_invert;
+	int hotplugable;
+	
+	u16 overscan_width;
+	u16 overscan_height;
+	
+	int lightness;
+	int saturation;
+	int contrast;
+} ;
+
+struct hdmi_property hdmi_data;
+static struct work_struct irq_work;
+static struct delayed_work hdmi_cable_check_work;
+
+static int boot_hdmi_vid = -1;
+static int user_config_vid = -1;
+
+module_param(boot_hdmi_vid, int, 0644);
+
+atomic_t hdmi_status = ATOMIC_INIT(0);
+
+static bool is_probe_called = false;
+
+struct ic_info {
+	int ic_type;
+};
+
+static struct ic_info  atm7039c_data = {
+   .ic_type = IC_TYPE_ATM7039C,
+};
+
+static  struct ic_info atm7059tc_data = {
+   .ic_type = IC_TYPE_ATM7059TC,
+};
+ 
+static  struct ic_info atm7059a_data = {
+   .ic_type = IC_TYPE_ATM7059A,
+};
+
+static const struct of_device_id atm70xx_hdmi_of_match[] = {
+
+	{.compatible = "actions,atm7039c-hdmi", .data = &atm7039c_data},
+	
+	{.compatible = "actions,atm7059tc-hdmi", .data = &atm7059tc_data},
+
+	{.compatible = "actions,atm7059a-hdmi", .data = &atm7059a_data},
+
+	{}
+};
+
+static struct hw_diff hdmi_atm7039c = {
+	.ic_type = IC_TYPE_ATM7039C,
+	.hp_start = 5,
+	.hp_end = 5,
+};
+
+static struct hw_diff hdmi_atm7059tc = {
+	.ic_type = IC_TYPE_ATM7059TC,
+	.hp_start 	= 16,
+	.hp_end	 	= 28,
+	.vp_start 	= 4,
+	.vp_end 	= 15,
+	.mode_start = 0,
+	.mode_end 	= 0,
+};
+
+static struct hw_diff hdmi_atm7059a = {
+	.ic_type = IC_TYPE_ATM7059A,
+	.hp_start 	= 16,
+	.hp_end	 	= 28,
+	.vp_start 	= 4,
+	.vp_end 	= 15,
+	.mode_start = 0,
+	.mode_end 	= 0,
+};
+
+MODULE_DEVICE_TABLE(of, atm70xx_hdmi_of_match);
+
+/*
+ * Logic for the below structure :
+ * user enters the CEA or VESA timings by specifying the HDMI code.
+ * There is a correspondence between CEA/VESA timing and code, please
+ * refer to section 6.3 in HDMI 1.3 specification for timing code.
+ */
+struct data_fmt_param {
+    const char *name;
+    s32 data_fmt;
+};
+
+static struct data_fmt_param date_fmts[] = {
+	{"1280x720p-50", OWL_TV_MOD_720P_50HZ},
+	{"1280x720p-60", OWL_TV_MOD_720P_60HZ},
+	{"1920x1080p-50", OWL_TV_MOD_1080P_50HZ},
+	{"1920x1080p-60", OWL_TV_MOD_1080P_60HZ},
+	{"720x576p-60", OWL_TV_MOD_576P},
+	{"720x480p-60", OWL_TV_MOD_480P},
+	{"DVI", OWL_TV_MOD_DVI},
+	{"PAL", OWL_TV_MOD_PAL},
+	{"NTSC", OWL_TV_MOD_NTSC},
+	{"4K30HZ", OWL_TV_MOD_4K_30HZ},
+};
+
+static struct hdmi_config cea_timings[] = {
+	{
+		{ 1920, 1080, 148500, 44, 88, 148, 5, 4, 36,
+			OWLDSS_SIG_ACTIVE_HIGH, OWLDSS_SIG_ACTIVE_HIGH,
+			false, 1, 0, },
+		{ 16, HDMI_HDMI,OWL_TV_MOD_1080P_60HZ},
+	},
+	{
+		{ 1920, 1080, 74250, 44, 528, 148, 5, 4, 36,
+			OWLDSS_SIG_ACTIVE_HIGH, OWLDSS_SIG_ACTIVE_HIGH,
+			false, 1, 0, },
+		{ 31, HDMI_HDMI,OWL_TV_MOD_1080P_50HZ },
+	},
+	{
+		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
+			OWLDSS_SIG_ACTIVE_HIGH, OWLDSS_SIG_ACTIVE_HIGH,
+			false, 1, 0, },
+		{ 4, HDMI_HDMI,OWL_TV_MOD_720P_60HZ},
+	},
+	{
+		{ 1280, 720, 74250, 40, 440, 220, 5, 5, 20,
+			OWLDSS_SIG_ACTIVE_HIGH, OWLDSS_SIG_ACTIVE_HIGH,
+			false, 1, 0, },
+		{ 19, HDMI_HDMI,OWL_TV_MOD_720P_50HZ},
+	},
+	{
+		{ 720, 576, 27000, 64, 12, 68, 5, 5, 39,
+			OWLDSS_SIG_ACTIVE_LOW, OWLDSS_SIG_ACTIVE_LOW,
+			false, 1, 0, },
+		{ 17, HDMI_HDMI,OWL_TV_MOD_576P},
+	},	
+	{
+		{ 720, 480, 27000, 62, 16, 60, 6, 9, 30,
+			OWLDSS_SIG_ACTIVE_LOW, OWLDSS_SIG_ACTIVE_LOW,
+			false, 7, 0, },
+		{ 2, HDMI_HDMI,OWL_TV_MOD_480P},
+	},		
+	{
+		{ 1280, 720, 74250, 40, 110, 220, 5, 5, 20,
+			OWLDSS_SIG_ACTIVE_HIGH, OWLDSS_SIG_ACTIVE_HIGH,
+			false, 1, 0, },
+		{ 126, HDMI_DVI,OWL_TV_MOD_DVI},
+	},
+};
+
+#if 0
+static void hdmi_print_info(struct owl_dss_device *dssdev)
+{
+	HDMI_DEBUG("~~~~~~~~~hdmi_print_info\n");
+
+	HDMI_DEBUG("x_res		= %d  \n",dssdev->timings.x_res);
+	HDMI_DEBUG("y_res		= %d  \n",dssdev->timings.y_res);
+	HDMI_DEBUG("pixel_clock	= %d  \n",dssdev->timings.pixel_clock);
+	HDMI_DEBUG("hsw			= %d  \n",dssdev->timings.hsw);
+	HDMI_DEBUG("hfp			= %d  \n",dssdev->timings.hfp);
+	HDMI_DEBUG("hbp			= %d  \n",dssdev->timings.hbp);
+	HDMI_DEBUG("vsw			= %d  \n",dssdev->timings.vsw);
+	HDMI_DEBUG("vfp			= %d  \n",dssdev->timings.vfp);
+	HDMI_DEBUG("vbp         = %d  \n",dssdev->timings.vbp);	
+	HDMI_DEBUG("vsync_level = %d  \n",dssdev->timings.vsync_level);
+	HDMI_DEBUG("hsync_level = %d  \n",dssdev->timings.hsync_level);
+	HDMI_DEBUG("interlace	= %d  \n",dssdev->timings.interlace);
+	HDMI_DEBUG("code		= %d  \n",hdmi.ip_data.cfg.cm.code);
+	HDMI_DEBUG("mode		= %d  \n",hdmi.ip_data.cfg.cm.mode);
+	HDMI_DEBUG("hdmi_src	= %d  \n",hdmi.ip_data.settings.hdmi_src);
+}
+#endif
+
+static int hdmi_init_display(struct owl_dss_device *dssdev)
+{
+
+	HDMI_DEBUG("init_display\n");
+
+	dss_init_hdmi_ip_ops(&hdmi.ip_data);
+
+	return 0;
+}
+
+static struct owl_video_timings *hdmi_get_timings_by_vid(int vid)
+{
+     int i = 0;
+     for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+		if (cea_timings[i].cm.vid == vid){
+			return &cea_timings[i].timings;
+		}
+	 }
+	 return NULL;
+}
+
+int owl_times_is_equal(const struct owl_video_timings *timings1,
+		     const struct owl_video_timings *timings2)
+{
+	return (timings1->x_res         == timings2->x_res &&
+		timings1->y_res         ==timings2->y_res &&
+		timings1->pixel_clock     == timings2->pixel_clock &&
+		timings1->hsw    == timings2->hsw &&
+		timings1->hfp    == timings2->hfp &&
+		timings1->hbp  == timings2->hbp &&
+		timings1->vsw == timings2->vsw &&
+		timings1->vfp == timings2->vfp &&
+		timings1->vbp == timings2->vbp);
+}
+
+static int hdmi_get_vid_by_times(struct owl_video_timings * times)
+{
+     int i ;
+     for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {     	
+		if (owl_times_is_equal(&cea_timings[i].timings,times)){
+			return cea_timings[i].cm.vid ;
+		}
+	 }
+	 return -1;
+}
+
+static bool hdmi_check_vid_available(int vid)
+{
+	return (((hdmi.edid.video_formats[0] >> vid) & 0x01)==1);
+}
+static int hdmi_get_code_by_vid(int vid)
+{
+     int i = 0;
+     for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+		if (cea_timings[i].cm.vid == vid){
+			return cea_timings[i].cm.code;
+		}
+	 }
+	 return -1;
+}
+static bool  is_hdmi_power_on(void)
+{
+	return ((hdmihw_read_reg(HDMI_CR) & 0x01) != 0);
+}
+
+#define DECLK2_MIN		150000000
+static unsigned long de_clk2_rate = 0;
+void  save_declk_and_switch_for_hdmi(void)
+{
+	struct clk      *de2_clk;
+	unsigned long  de2_new_clk = 0;
+	
+	de2_clk     = clk_get(NULL, CLKNAME_DE2_CLK);
+	
+	//save clk 
+	de_clk2_rate = clk_get_rate(de2_clk);
+	
+	if(de_clk2_rate < DECLK2_MIN)
+	{
+		//set new clk 	
+		de2_new_clk = clk_round_rate(de2_clk, DECLK2_MIN);
+		
+		clk_set_rate(de2_clk,de2_new_clk);
+		
+		clk_prepare(de2_clk);
+		
+	    clk_enable(de2_clk);
+	    printk("save_declk_and_switch_for_hdmi de2_new_clk %ld MHZ\n " ,de2_new_clk);
+	}	
+}
+void  restore_declk_for_hdmi(void)
+{
+	struct clk      *de2_clk;
+	unsigned long  de2_new_clk = 0;
+	
+	de2_clk     = clk_get(NULL, CLKNAME_DE2_CLK);
+	printk("restore_declk_for_hdmi de_clk2_rate %ld MHZ\n " ,de_clk2_rate);
+	if(de_clk2_rate != 0 && clk_get_rate(de2_clk) != de_clk2_rate)
+	{
+	
+		de2_new_clk = clk_round_rate(de2_clk, de_clk2_rate);
+		
+		clk_set_rate(de2_clk,de2_new_clk);
+		
+		clk_prepare(de2_clk);
+		
+	    clk_enable(de2_clk);	
+	}	
+}
+static int hdmi_power_on_full(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct owl_overlay_manager *mgr = dssdev->manager;
+			
+	if(hdmi.ip_data.cfg.cm.code == VID1280x720P_60_DVI){
+		hdmi.ip_data.settings.hdmi_mode = HDMI_DVI;
+	}else{
+		hdmi.ip_data.settings.hdmi_mode = hdmi.edid.isHDMI;
+	}
+	
+	if(is_hdmi_power_on())
+	{
+		dss_mgr_enable(mgr);
+		return 0;
+	}
+
+	hdmi.ip_data.ops->hdmi_clk24Men(&hdmi.ip_data, 1);	
+	
+	hdmi.ip_data.ops->pll_enable(&hdmi.ip_data);
+	
+	hdmi.ip_data.ops->hdmi_reset(&hdmi.ip_data);
+	
+	hdmi.ip_data.ops->hpd_clear_plug(&hdmi.ip_data);	
+	
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 1);
+	
+	r = dss_mgr_enable(mgr);
+	if (r)
+		goto err_mgr_enable;
+	DEBUG_ON("dss_mgr_enable end\n");	
+		
+	hdmi.ip_data.ops->video_configure(&hdmi.ip_data);
+
+	hdmi.ip_data.ops->video_enable(&hdmi.ip_data);
+	
+	hdmi.ip_data.ops->phy_enable(&hdmi.ip_data);		
+	DEBUG_ON("hdmi_power_on_full end\n");	
+
+	return 0;
+
+err_mgr_enable:
+	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
+	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);
+	return -EIO;
+}
+
+static void hdmi_power_off_full(struct owl_dss_device *dssdev)
+{
+	struct owl_overlay_manager *mgr = dssdev->manager;
+	
+	hdmi.ip_data.ops->phy_disable(&hdmi.ip_data);	
+	hdmi.ip_data.ops->video_disable(&hdmi.ip_data);
+		
+	dss_mgr_disable(mgr);
+	
+	hdmi.ip_data.ops->pll_disable(&hdmi.ip_data);
+	hdmi.ip_data.ops->hdmi_clk24Men(&hdmi.ip_data, 0);	
+	
+	restore_declk_for_hdmi();	
+}
+
+static int hdmi_set_settings(struct hdmi_ip_data *ip_data)
+{
+	ip_data->settings.hdmi_src = DE;
+	ip_data->settings.vitd_color = 0xff0000;
+	ip_data->settings.enable_3d = NOT_3D;
+	ip_data->settings.present_3d = NOT_3D;
+	ip_data->settings.pixel_encoding = RGB444;
+	ip_data->settings.color_xvycc = 0;
+	ip_data->settings.deep_color = color_mode_24bit;
+	ip_data->settings.hdmi_mode = HDMI_HDMI;
+	
+	ip_data->settings.channel_invert = hdmi_data.channel_invert;
+	ip_data->settings.bit_invert = hdmi_data.bit_invert;
+	return 0;	
+}
+
+static void hdmi_display_set_dssdev(struct owl_dss_device *dssdev)
+{
+	hdmi.dssdev = dssdev;
+}
+
+static int hdmi_probe_pdata(struct platform_device *pdev)
+{
+	struct owl_dss_device *dssdev = NULL;
+	int r;
+	
+	r = hdmi_init_display(dssdev);
+	if (r) {
+		DEBUG_ERR("device %s init failed: %d\n", dssdev->name, r);
+		return r;
+	}
+
+	return 0;
+}
+
+static int check_best_vid_from_edid(struct hdmi_edid *edid)
+{
+	int best_vid;
+	int i = 0;	
+	
+	if(boot_hdmi_vid != -1)	{
+		
+		best_vid =  boot_hdmi_vid;
+		boot_hdmi_vid = -1;
+		
+	}else if(hdmi.edid.read_ok){
+		
+		if(user_config_vid != -1
+			&& hdmi_check_vid_available(user_config_vid)){
+			best_vid = user_config_vid;
+		}else{
+			for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {	
+				if(hdmi_check_vid_available(cea_timings[i].cm.vid)){			
+					best_vid = cea_timings[i].cm.vid;
+					break;
+				}
+			}
+		}		
+	}else{
+		if(user_config_vid != -1){
+			best_vid = user_config_vid;
+		}else{
+			best_vid = OWL_TV_MOD_DVI;
+		}
+	}
+		
+	hdmi.ip_data.cfg.cm.vid = best_vid;
+	
+	return best_vid;
+}
+void hdmi_send_uevent(bool data)
+{
+	mutex_lock(&hdmi.ip_data.lock);
+	/*HDMI_DEBUG("~~~hdmi_send_uevent %d  %d\n", data, atomic_read(&hdmi_status));*/
+	if(data){
+		if(atomic_read(&hdmi_status)==0){
+			HDMI_DEBUG("parse_edid start\n");
+			parse_edid(&hdmi.edid);
+			check_best_vid_from_edid(&hdmi.edid);
+			HDMI_DEBUG("parse_edid end\n");		
+			if(hdmi.data.hpd_en){	
+				switch_set_state(&hdev, 1);	
+			}
+			if(hdmi.dssdev != NULL 
+				&& hdmi.dssdev->driver != NULL 
+				&& hdmi.dssdev->driver->hot_plug_nodify){
+				hdmi.dssdev->driver->hot_plug_nodify(hdmi.dssdev,data);	
+			}
+			atomic_set(&hdmi_status, 1);
+		}
+	}else{
+		if((atomic_read(&hdmi_status)==1)&&hdmi.data.send_uevent){
+			if(hdmi.data.hpd_en){
+				switch_set_state(&hdev, 0);	
+			}
+			if(hdmi.dssdev != NULL 
+				&& hdmi.dssdev->driver != NULL 
+				&& hdmi.dssdev->driver->hot_plug_nodify){
+				hdmi.dssdev->driver->hot_plug_nodify(hdmi.dssdev,data);	
+			}
+			atomic_set(&hdmi_status, 0);
+		}	
+	}		
+	mutex_unlock(&hdmi.ip_data.lock);
+
+}
+
+void hdmi_cable_check(struct work_struct *work)
+{
+	/*HDMI_DEBUG("hdmi_cable_check  ~~~~~~~~\n");*/	
+	if(hdmi.data.cable_check_onoff){
+		if(hdmi.ip_data.ops->cable_check(&hdmi.ip_data)){		
+			hdmi_send_uevent(1);
+		}else{
+			hdmi_send_uevent(0);
+		}
+	}
+	queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi_cable_check_work,
+				msecs_to_jiffies(2000));
+}
+
+int hdmi_cable_check_init(void)
+{
+	queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi_cable_check_work,
+				msecs_to_jiffies(2000));
+	return 0;
+}
+
+extern void hdmi_cec_irq_handler(void);
+
+static irqreturn_t hdmi_irq_handle(int irq, void *data)
+{
+	//DEBUG_ON("[%s start]\n", __func__);
+	u32 status = hdmi.ip_data.ops->get_irq_state(&hdmi.ip_data);
+	if(status & HDMI_HPD_IRQ)
+	{
+		hdmi.data.hpd_pending  = hdmi.ip_data.ops->detect(&hdmi.ip_data);
+		hdmi.data.cable_status = hdmi.ip_data.ops->cable_check(&hdmi.ip_data);
+		hdmi.data.hdcp_ri      = check_ri_irq();	
+		hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 0);		
+		schedule_work(&irq_work);
+	}else{
+		hdmi_cec_irq_handler();
+	}	
+	//DEBUG_ON("[%s end]\n", __func__);	
+	return IRQ_HANDLED;
+}
+
+static void do_hpd_irq(struct work_struct *work) 
+{
+	bool sta_new;	
+	DEBUG_ON("~~~~~~~~~~~~~irq_handler  %d\n", hdmi.data.hdmi_sta);
+	if(hdmi.data.hpd_pending){
+		if(hdmi_data.hdcp_onoff){
+			msleep(10);
+		}else{
+			msleep(50);
+		}
+		sta_new = hdmi.ip_data.ops->cable_check(&hdmi.ip_data);
+		DEBUG_ON("sta_new %d old %d\n", sta_new, hdmi.data.cable_status);
+		if(sta_new==hdmi.data.cable_status){
+			if(sta_new){
+				DEBUG_ON("~~~~~~~~~~~~~hdmi plug in\n");					
+				hdmi_send_uevent(1);
+			}else{
+				DEBUG_ON("~~~~~~~~~~~~~hdmi plug out\n");
+				hdmi_send_uevent(0);
+			}
+		}
+		hdmi.data.hpd_pending = false;
+	}
+	
+	mutex_lock(&hdmi.lock);	
+	hdmi.ip_data.ops->hpd_clear_plug(&hdmi.ip_data);	
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 1);
+	mutex_unlock(&hdmi.lock);	
+	
+	if((hdmi_data.hdcp_onoff) && (hdmi.data.hdcp_ri)){
+        hdcp_check_ri();
+	}
+	
+}
+
+int owldss_hdmi_display_check_timing(struct owl_dss_device *dssdev,
+					struct owl_video_timings *timings)
+{
+	
+	int i = 0;
+	for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+		if (owl_times_is_equal(&cea_timings[i].timings,timings)){
+			return 0;
+		}
+	}
+	return -1;
+}
+void owldss_hdmi_display_set_timing(struct owl_dss_device *dssdev,struct owl_video_timings *timings)
+{
+	struct owl_video_timings *dss_timings = &dssdev->timings;
+	int vid = hdmi_get_vid_by_times(timings);
+	
+	timings = hdmi_get_timings_by_vid(vid);
+	
+	mutex_lock(&hdmi.lock);
+	
+	if (timings != NULL){
+			memcpy(dss_timings,timings,sizeof(struct owl_video_timings));
+			memcpy(&hdmi.ip_data.cfg.timings,timings,sizeof(struct owl_video_timings));			
+	}else{
+		printk("owldss_hdmi_display_set_timing NULL  \n");
+	}	
+	hdmi.ip_data.cfg.cm.vid = vid;
+	hdmi.ip_data.cfg.cm.code = hdmi_get_code_by_vid(vid);
+	hdmi.ip_data.cfg.cm.mode = hdmi.edid.isHDMI;	
+	
+	mutex_unlock(&hdmi.lock);
+}
+
+void owldss_hdmi_display_set_vid(struct owl_dss_device *dssdev,int vid)
+{
+	struct owl_video_timings *timings;
+	struct owl_video_timings *dss_timings = &dssdev->timings;
+
+	mutex_lock(&hdmi.lock);
+	
+	timings = hdmi_get_timings_by_vid(vid);
+	printk("timings : xres %d yres %d size of %d %d \n",timings->x_res,timings->y_res,sizeof(struct owl_video_timings),sizeof(struct owl_video_timings*));
+	if (timings != NULL){
+			memcpy(dss_timings,timings,sizeof(struct owl_video_timings));
+			memcpy(&hdmi.ip_data.cfg.timings,timings,sizeof(struct owl_video_timings));			
+	}else{
+		printk("hdmi_get_timings NULL  \n");
+	}	
+	hdmi.ip_data.cfg.cm.vid = vid;
+	hdmi.ip_data.cfg.cm.code = hdmi_get_code_by_vid(vid);
+	hdmi.ip_data.cfg.cm.mode = hdmi.edid.isHDMI;	
+	DEBUG_ON("owldss_hdmi_display_set_vid vid %d ,code %d mode %d  \n",hdmi.ip_data.cfg.cm.vid,hdmi.ip_data.cfg.cm.code,hdmi.ip_data.cfg.cm.mode);
+	mutex_unlock(&hdmi.lock);
+}
+
+void owldss_hdmi_display_get_vid(struct owl_dss_device *dssdev, int *vid)
+{    
+	mutex_lock(&hdmi.lock);
+	*vid = hdmi.ip_data.cfg.cm.vid;
+	DEBUG_ON("owldss_hdmi_display_get_vid %d \n",*vid);
+	mutex_unlock(&hdmi.lock);
+}
+
+void owldss_hdmi_display_enable_hotplug(struct owl_dss_device *dssdev, bool enable)
+{
+	if(!hdmi_data.hotplugable)
+	{
+		 return;
+	}
+	mutex_lock(&hdmi.lock);	
+	HDMI_DEBUG("owldss_hdmi_display_enable_hotplug  enable %d\n", enable);
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, enable);
+	if(enable){
+		if(hdmi.ip_data.ops->cable_check(&hdmi.ip_data)){
+			HDMI_DEBUG("owldss_hdmi_display_enable_hotplug  switch_set_state 1\n");
+			hdmi_send_uevent(1);
+		}
+		hdmi.data.hpd_en = 1;
+	}else{
+		if(hdmi.ip_data.ops->cable_check(&hdmi.ip_data)){
+			HDMI_DEBUG("owldss_hdmi_display_enable_hotplug  switch_set_state 0\n");
+			hdmi_send_uevent(0);
+		}
+		hdmi.data.hpd_en = 0;
+	}
+	mutex_unlock(&hdmi.lock);
+}
+
+void owldss_hdmi_display_enable_hdcp(struct owl_dss_device *dssdev, bool enable)
+{
+	mutex_lock(&hdmi.lock);	
+	
+	if(enable){
+		hdmi_data.hdcp_onoff = 1;
+	}else{
+		hdmi_data.hdcp_onoff = 0;
+	}
+	mutex_unlock(&hdmi.lock);
+}
+
+int owldss_hdmi_display_get_vid_cap(struct owl_dss_device *dssdev, int *vid_cap)
+{
+	int i=0;
+	int vid = 0;
+	mutex_lock(&hdmi.lock);
+	if(hdmi.edid.video_formats[0]==0){
+		if(hdmi.ip_data.ops->cable_check(&hdmi.ip_data)){
+			HDMI_DEBUG("parse_edid start\n");
+			parse_edid(&hdmi.edid);
+			HDMI_DEBUG("parse_edid end\n");	
+		}else{
+			hdmi.edid.video_formats[0]=0x80090014;
+			DEBUG_ERR("NO HDMI CABLE\n");
+		}	
+	}
+	for (i = 0; i < ARRAY_SIZE(cea_timings); i++) {
+		vid =  cea_timings[i].cm.vid;			
+		if(hdmi_check_vid_available(vid)){			
+			*vid_cap = i;		
+			vid_cap++;	
+		}
+	}
+	
+	if(hdmi.edid.read_ok==0){
+		*vid_cap = OWL_TV_MOD_DVI;		
+		vid_cap++;				
+	}
+	
+	mutex_unlock(&hdmi.lock);
+	return 8;
+}
+
+void owldss_hdmi_display_set_overscan(struct owl_dss_device *dssdev,u16 over_scan_width,u16 over_scan_height)
+{	
+	mutex_lock(&hdmi.lock);
+	hdmi_data.overscan_width = over_scan_width;
+	hdmi_data.overscan_height = over_scan_height;
+	mutex_unlock(&hdmi.lock);
+	
+}
+void owldss_hdmi_display_get_overscan(struct owl_dss_device *dssdev, u16 * over_scan_width,u16 * over_scan_height)
+{
+	mutex_lock(&hdmi.lock);
+	*over_scan_width = hdmi_data.overscan_width;
+	*over_scan_height = hdmi_data.overscan_height;
+	mutex_unlock(&hdmi.lock);
+}
+
+int owldss_hdmi_read_edid(struct owl_dss_device *dssdev, u8 * buffer , int len)
+{
+	int r = read_edid(buffer,len);
+	if(r <= 0){
+		printk("owldss_hdmi_read_edid ~~~ error\n");
+	}
+	return r;
+}
+int owldss_hdmi_display_get_cable_status(struct owl_dss_device *dssdev)
+{
+	int r;
+	mutex_lock(&hdmi.lock);
+	r = hdmi.ip_data.ops->cable_check(&hdmi.ip_data);
+	HDMI_DEBUG("ENTER owldss_hdmi_display_get_cable_status %d\n",r);
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+int owldss_hdmi_display_enable(struct owl_dss_device *dssdev)
+{
+
+	struct owl_overlay_manager *mgr = dssdev->manager;
+	int r = 0;
+
+	DEBUG_ON("ENTER hdmi_display_enable\n");
+
+	mutex_lock(&hdmi.lock);
+
+    if (mgr == NULL) {
+		DEBUG_ERR("failed to enable display: no manager\n");
+		r = -ENODEV;
+		goto err0;
+	}
+	   
+    save_declk_and_switch_for_hdmi();
+    
+	r = owl_dss_start_device(dssdev);
+	
+	if (r) {
+		DEBUG_ERR("failed to start device\n");
+		goto err0;
+	}
+	HDMI_DEBUG("owl_dss_start_device end\n");	
+	
+	r = hdmi_power_on_full(dssdev);
+	if (r) {
+		DEBUG_ERR("failed to power on device\n");
+		goto err1;
+	}	
+
+	if(hdmi_data.hdcp_onoff){
+		hdcp_init();
+
+		queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi.ip_data.hdcp.hdcp_work,
+					msecs_to_jiffies(50));
+	}			
+	if(hdmi.ip_data.settings.hdmi_mode == HDMI_HDMI){
+		switch_set_state(&hdev_audio, 1);
+	}
+	/*hdmi_dump_regs();*/
+	
+	mutex_unlock(&hdmi.lock);
+	return 0;
+
+err1:
+	owl_dss_stop_device(dssdev);
+err0:
+	restore_declk_for_hdmi();
+	mutex_unlock(&hdmi.lock);
+	return r;
+}
+
+int owldss_hdmi_hotplug_debug(struct owl_dss_device *dssdev,int enable)
+{
+	if(enable){
+		DEBUG_ON("~~~~~~~~~~~~~hdmi plug in\n");					
+		hdmi_send_uevent(1);
+	}else{
+		DEBUG_ON("~~~~~~~~~~~~~hdmi plug out\n");
+		hdmi_send_uevent(0);
+	}
+	return 0;
+}
+
+int owldss_hdmi_cable_debug(struct owl_dss_device *dssdev,int enable)
+{
+	if(enable){
+		hdmi.data.cable_check_onoff = 1;
+	}else{
+		hdmi.data.cable_check_onoff = 0;
+	}
+	DEBUG_ON("~~~~~~~~~~~~~owldss_hdmi_cable_debug %d\n", hdmi.data.cable_check_onoff );
+	return 0;
+}
+
+int owldss_hdmi_uevent_debug(struct owl_dss_device *dssdev,int enable)
+{
+	if(enable){
+		hdmi.data.send_uevent = 1;
+	}else{
+		hdmi.data.send_uevent = 0;
+	}	
+	DEBUG_ON("~~~~~~~~~~~~~owldss_hdmi_uevent_debug %d\n", hdmi.data.send_uevent );
+	return 0;
+}
+
+void owldss_hdmi_display_disable(struct owl_dss_device *dssdev)
+{
+	DEBUG_ON("Enter hdmi_display_disable\n");
+
+	mutex_lock(&hdmi.lock);
+
+	hdmi_power_off_full(dssdev);
+
+	owl_dss_stop_device(dssdev);
+	
+	if(hdmi.ip_data.settings.hdmi_mode == HDMI_HDMI){
+		switch_set_state(&hdev_audio, 2);
+	}
+
+	mutex_unlock(&hdmi.lock);
+}
+
+int owl_hdmi_get_effect_parameter(struct owl_dss_device *dssdev, enum owl_plane_effect_parameter parameter_id)
+{
+
+    switch(parameter_id){
+    	case OWL_DSS_VIDEO_LIGHTNESS:
+    		return hdmi_data.lightness;
+    	case OWL_DSS_VIDEO_SATURATION:
+    		return hdmi_data.saturation;
+    	case OWL_DSS_VIDEO_CONSTRAST:
+    		return hdmi_data.contrast;
+    	default:
+    		printk("invalid plane effect parameter \n");
+    		return -1;
+    }
+}
+
+void owl_hdmi_set_effect_parameter(struct owl_dss_device *dssdev,enum owl_plane_effect_parameter parameter_id ,int value)
+{
+     switch(parameter_id){
+    	case OWL_DSS_VIDEO_LIGHTNESS:
+    		hdmi_data.lightness = value;
+    		break;
+    	case OWL_DSS_VIDEO_SATURATION:
+    		hdmi_data.saturation = value;
+    		break;
+    	case OWL_DSS_VIDEO_CONSTRAST:
+    		hdmi_data.contrast = value;
+    		break;
+    	default:
+    		printk("invalid plane effect parameter parameter_id %d value %d\n",parameter_id,value);
+    		break;
+    }
+
+}
+
+int owldss_hdmi_panel_init(struct owl_dss_device *dssdev)
+{	
+	int r;
+	HDMI_DEBUG("owl_dss_device  hdmi  p->0x%p\n", dssdev);
+	hdmi_display_set_dssdev(dssdev);
+	hdmi_set_settings(&hdmi.ip_data);	
+	HDMI_DEBUG("hpd_enable start\n");
+	
+	if(hdmi.hdmihw_diff->ic_type == IC_TYPE_ATM7059TC){		
+		hdmi.ip_data.ops->hdmi_devclken(&hdmi.ip_data, 1);
+		hdmi.ip_data.ops->hdmi_reset(&hdmi.ip_data);
+	}
+	
+	owldss_hdmi_display_set_vid(dssdev,hdmi.ip_data.cfg.cm.vid);	
+	
+	
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 0);
+	
+	r = request_irq(OWL_IRQ_HDMI, hdmi_irq_handle, 0, "hdmidev", NULL);	
+	
+	if (r) {
+		DEBUG_ERR(" register irq failed!\n");
+		return r;
+	} else {
+		DEBUG_ON(" register irq ON!\n");
+	}		
+	hdmi_cable_check_init();
+	return 0;
+}
+
+int owldss_hdmi_panel_suspend(struct owl_dss_device *dssdev)
+{
+	DEBUG_ON("owldss_hdmi_panel_suspend \n");
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 0);
+	cancel_delayed_work_sync(&hdmi_cable_check_work);
+	cancel_delayed_work_sync(&hdmi.ip_data.hdcp.hdcp_work);
+	cancel_work_sync(&irq_work);
+	//flush_workqueue(hdmi.ip_data.hdcp.wq);
+	//flush_scheduled_work();
+	return 0;
+}
+
+int owldss_hdmi_panel_resume(struct owl_dss_device *dssdev)
+{
+	DEBUG_ON("owldss_hdmi_panel_resume \n");
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, hdmi.data.hpd_en);
+
+	queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi_cable_check_work,
+				msecs_to_jiffies(2000));
+	return 0;
+}
+static u32 string_to_data_fmt(const char *name)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(date_fmts); i++) {
+		if (!strcmp(date_fmts[i].name, name))
+			return date_fmts[i].data_fmt;
+	}
+
+	return -1;
+}
+static int of_get_hdmi_data(struct platform_device *pdev, struct hdmi_property *hdmi_data)
+{
+	struct device_node *of_node;
+	char const *default_resulation;
+	char const *over_scan;
+	
+
+	HDMI_DEBUG("%s\n", __func__);
+
+	of_node = pdev->dev.of_node;
+
+	if (of_property_read_u32_array(of_node, "hdcp_onoff", &hdmi_data->hdcp_onoff , 1)) {
+		hdmi_data->hdcp_onoff = 0;
+	}
+	if (of_property_read_u32_array(of_node, "channel_invert", &hdmi_data->channel_invert , 1)) {
+		hdmi_data->channel_invert = 0;
+	}
+	if (of_property_read_u32_array(of_node, "bit_invert", &hdmi_data->bit_invert , 1)) {
+		hdmi_data->bit_invert = 0;
+	}
+	
+	if (of_property_read_u32_array(of_node, "hotplugable", &hdmi_data->hotplugable , 1)) {
+		hdmi_data->hotplugable = 1;		
+	}
+	hdmi.data.hpd_en = hdmi_data->hotplugable;			
+	
+	if (!of_property_read_string(of_node, "over_scan", &over_scan)) {		
+		if(over_scan != NULL)
+		{
+			printk("over_scan \n %s",over_scan);
+			sscanf(over_scan,"%d,%d",(int *)(&hdmi_data->overscan_width),(int *)(&hdmi_data->overscan_height));
+			printk("hdmi_data->overscan_width %d  ,hdmi_data->overscan_height %d \n",hdmi_data->overscan_width,hdmi_data->overscan_height);
+		}
+		
+	}
+	
+	if (of_property_read_string(of_node, "default_resolution", &default_resulation)) {
+		default_resulation = NULL;
+	}
+	
+	user_config_vid = string_to_data_fmt(default_resulation);
+	
+	if(boot_hdmi_vid == -1)
+	{
+		boot_hdmi_vid = user_config_vid;
+	}
+		
+	hdmi.ip_data.cfg.cm.vid = boot_hdmi_vid;
+	
+	if(hdmi.ip_data.cfg.cm.vid == -1){
+		
+		hdmi.ip_data.cfg.cm.vid = OWL_TV_MOD_720P_60HZ;
+		
+	}
+	
+	DEBUG_ON("of_get_hdmi_data ~~~~~~~~~~~~~ hdmi.ip_data.cfg.cm.code %d \n",hdmi.ip_data.cfg.cm.code);
+
+	if (of_property_read_u32_array(of_node, "lightness", &hdmi_data->lightness , 1)) {
+		hdmi_data->lightness = DEF_LIGHTNESS;
+		//DEBUG_ON("cat not get lightness  %d\n", hdmi_data->lightness);
+	}
+	if (of_property_read_u32_array(of_node, "saturation", &hdmi_data->saturation , 1)) {
+		hdmi_data->saturation = DEF_SATURATION;
+		//DEBUG_ON("cat not get saturation  %d\n", hdmi_data->saturation);
+	}
+	if (of_property_read_u32_array(of_node, "contrast", &hdmi_data->contrast , 1)) {
+		hdmi_data->contrast = DEF_CONTRAST;
+		//DEBUG_ON("cat not get contrast  %d\n", hdmi_data->contrast);
+	}
+	
+	hdmi.ip_data.txrx_cfg.drv_from_dts = 0;
+	
+	if (of_property_read_u32_array(of_node, "vid480p_tx1", &hdmi.ip_data.txrx_cfg.vid480p_tx1, 1)) {
+		//DEBUG_ERR("cat not get vid480p_tx1 \n");
+		goto read_err;
+	}
+	if (of_property_read_u32_array(of_node, "vid480p_tx2", &hdmi.ip_data.txrx_cfg.vid480p_tx2, 1)) {
+		DEBUG_ERR("cat not get vid480p_tx2 \n");
+		goto read_err;
+	}
+	if (of_property_read_u32_array(of_node, "vid576p_tx1", &hdmi.ip_data.txrx_cfg.vid576p_tx1, 1)) {
+		DEBUG_ERR("cat not get vid576p_tx1 \n");
+		goto read_err;
+	}	
+	if (of_property_read_u32_array(of_node, "vid576p_tx2", &hdmi.ip_data.txrx_cfg.vid576p_tx2, 1)) {
+		DEBUG_ERR("cat not get vid576p_tx2 \n");
+		goto read_err;
+	}	
+	if (of_property_read_u32_array(of_node, "vid720p_tx1", &hdmi.ip_data.txrx_cfg.vid720p_tx1, 1)) {
+		DEBUG_ERR("cat not get vid720p_tx1 \n");
+		goto read_err;
+	}	
+	if (of_property_read_u32_array(of_node, "vid720p_tx2", &hdmi.ip_data.txrx_cfg.vid720p_tx2, 1)) {
+		DEBUG_ERR("cat not get vid720p_tx2 \n");
+		goto read_err;
+	}		
+	if (of_property_read_u32_array(of_node, "vid1080p_tx1", &hdmi.ip_data.txrx_cfg.vid1080p_tx1, 1)) {
+		DEBUG_ERR("cat not get vid1080p_tx1 \n");
+		goto read_err;
+	}	
+	if (of_property_read_u32_array(of_node, "vid1080p_tx2", &hdmi.ip_data.txrx_cfg.vid1080p_tx2, 1)) {
+		DEBUG_ERR("cat not get vid1080p_tx2 \n");
+		goto read_err;
+	}	
+
+	hdmi.ip_data.txrx_cfg.drv_from_dts = 1;
+read_err:
+	
+	return 0;
+}
+
+void hdcp_read_key_handle(struct work_struct *work)
+{	
+	if(hdcp_read_key()==-EAGAIN){
+		queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi.ip_data.hdcp.hdcp_read_key_work,
+			msecs_to_jiffies(2000));			
+	}
+}
+
+/* HDMI HW IP initialisation */
+static int platform_hdmihw_probe(struct platform_device *pdev)
+{
+	int r;
+	struct resource * hdmihw_mem;
+	const struct of_device_id *id = of_match_device(atm70xx_hdmi_of_match, &pdev->dev);	
+	DEBUG_ON("Enter owldss_hdmihw_probe\n");
+	if(id != NULL){
+		struct ic_info * info = (struct ic_info *)id->data;	
+		if(info != NULL){
+			HDMI_DEBUG("hdmi info ic_type 0x%x \n",info->ic_type);
+			if(info->ic_type == IC_TYPE_ATM7039C){
+				hdmi.hdmihw_diff = &hdmi_atm7039c;
+			}else if(info->ic_type == IC_TYPE_ATM7059TC){	
+				hdmi.hdmihw_diff = &hdmi_atm7059tc;
+			}
+			else if(info->ic_type == IC_TYPE_ATM7059A){	
+				hdmi.hdmihw_diff = &hdmi_atm7059a;
+			}
+		}else{
+			HDMI_DEBUG("hdmi info is null\n");
+		}
+	}
+	
+	if(of_get_hdmi_data(pdev, &hdmi_data)){
+		DEBUG_ERR("of_get_hdmi_data error\n");
+		return -1;
+	}
+
+	hdmi.pdev = pdev;
+
+	mutex_init(&hdmi.lock);
+	mutex_init(&hdmi.ip_data.lock);
+
+	/* Base address taken from platform */
+	hdmihw_mem = platform_get_resource(hdmi.pdev, IORESOURCE_MEM, 0);
+	if (!hdmihw_mem) {
+		DEBUG_ERR("hdmihw_mem platform_get_resource ERROR\n");
+		r = -EINVAL;
+		goto err1;
+	}
+	
+	hdmi.ip_data.base = devm_ioremap_resource(&pdev->dev, hdmihw_mem);
+	if (IS_ERR(hdmi.ip_data.base)){	
+		DEBUG_ERR("hdmi.ip_data.base error\n");
+		return PTR_ERR(hdmi.ip_data.base);
+	}	
+	HDMI_DEBUG("base=%p\n", hdmi.ip_data.base);		
+	r = hdmi_probe_pdata(pdev);
+	if (r) {
+		return r;
+	}
+		
+	owl_hdmi_create_sysfs(&pdev->dev);	
+	
+    hdmi.ip_data.hdcp.wq = create_workqueue("atm705a-hdmi-hdcp");
+	
+	INIT_DELAYED_WORK(&hdmi.ip_data.hdcp.hdcp_work, hdcp_check_handle);
+	
+	INIT_DELAYED_WORK(&hdmi.ip_data.hdcp.hdcp_read_key_work, hdcp_read_key_handle);
+	
+	INIT_DELAYED_WORK(&hdmi_cable_check_work, hdmi_cable_check);
+	
+	INIT_WORK(&irq_work, do_hpd_irq);
+
+	
+	
+	queue_delayed_work(hdmi.ip_data.hdcp.wq, &hdmi.ip_data.hdcp.hdcp_read_key_work,
+					msecs_to_jiffies(50));
+ 
+	r = switch_dev_register(&hdev);
+	if (r)
+		goto err1;
+	r = switch_dev_register(&hdev_audio);
+	if (r)
+		goto err2;	
+		
+	ddc_init();
+	
+	hdmi.data.cable_check_onoff = 1;
+	hdmi.data.send_uevent = 1;
+	hdmi.edid.isHDMI = HDMI_HDMI;
+	is_probe_called = true;
+	return 0;
+	
+err2:
+	switch_dev_unregister(&hdev);
+err1:
+	return r;	
+}
+
+static int platform_hdmihw_remove(struct platform_device *pdev)
+{
+	DEBUG_ON("platform_hdmihw_remove \n");
+	return 0;
+}
+
+#ifndef SUSPEND_IN_DSS
+static s32 hdmi_diver_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+#ifndef CONFIG_HAS_EARLYSUSPEND
+	DEBUG_ON("hdmi_diver_suspend \n");
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 0);
+#endif
+	return 0;
+}
+
+static s32 hdmi_diver_resume(struct platform_device *pdev)
+{
+#ifndef CONFIG_HAS_EARLYSUSPEND
+	DEBUG_ON("hdmi_diver_resume \n");
+
+	hdmi.ip_data.ops->hdmi_reset(&hdmi.ip_data);
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, hdmi.data.hpd_en);
+#endif
+	return 0;
+}
+#endif 
+
+#ifndef SUSPEND_IN_DSS
+static void hdmi_early_suspend(struct early_suspend *h)
+{
+	DEBUG_ON("hdmi_early_suspend \n");
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, 0);
+}
+static void hdmi_late_resume(struct early_suspend *h)
+{
+	DEBUG_ON("hdmi_late_resume \n");
+
+	hdmi.ip_data.ops->hdmi_reset(&hdmi.ip_data);
+	hdmi.ip_data.ops->hpd_enable(&hdmi.ip_data, hdmi.data.hpd_en);
+}
+
+static struct early_suspend hdmi_early_suspend_desc = {
+#ifndef SUSPEND_IN_DSS
+	.suspend = hdmi_early_suspend,
+	.resume  = hdmi_late_resume,
+#endif
+};
+#endif
+
+static struct platform_driver owldss_hdmihw_driver = {
+	.probe		= platform_hdmihw_probe,
+	.remove         = platform_hdmihw_remove,
+#ifndef SUSPEND_IN_DSS
+	.suspend = hdmi_diver_suspend,
+	.resume = hdmi_diver_resume,
+#endif
+	.driver         = {
+		.name   = "owl_hdmihw",
+		.owner  = THIS_MODULE,
+		.of_match_table = atm70xx_hdmi_of_match,
+	},
+};
+
+int owl_hdmi_init_platform(void)
+{
+	int r;
+	r = platform_driver_register(&owldss_hdmihw_driver);
+	
+#ifndef SUSPEND_IN_DSS
+	register_early_suspend(&hdmi_early_suspend_desc);
+#endif	
+
+	if (r) {
+		DEBUG_ERR("Failed to initialize hdmi platform driver\n");
+		goto err_driver;
+	}
+	if(!is_probe_called){
+		r = -1;
+	}
+err_driver:
+	return r;
+}
+
+int owl_hdmi_uninit_platform(void)
+{   
+	platform_driver_unregister(&owldss_hdmihw_driver);
+	
+    return 0;
+}
+
+static int __init boot_hdmi_vid_setup(char *str)
+{
+	
+	sscanf(str,"%d",&boot_hdmi_vid);
+	printk("-------- boot_hdmi_vid_setup %d --------\n",boot_hdmi_vid);
+	return 1;
+}
+__setup("hdmi_vid=", boot_hdmi_vid_setup);
+void hdmihw_write_reg(u32 val, const u16 idx)
+{
+	hdmi.ip_data.ops->write_reg(&hdmi.ip_data, idx, val);
+}
+EXPORT_SYMBOL(hdmihw_write_reg); 
+
+int hdmihw_read_reg(const u16 idx)
+{
+	return hdmi.ip_data.ops->read_reg(&hdmi.ip_data, idx);
+}
+EXPORT_SYMBOL(hdmihw_read_reg); 
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi.h b/drivers/video/fbdev/owl/displays/hdmi/hdmi.h
new file mode 100755
index 0000000..1d1e70b
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi.h
@@ -0,0 +1,421 @@
+/*
+ * hdmi.h
+ *
+ * HDMI header definition for OWL IP.
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _OWL_HDMI_H
+#define _OWL_HDMI_H
+#include <video/owldss.h>
+
+#define PRINGK_ON
+#ifdef PRINGK_ON
+#define DEBUG_ON(format, ...) \
+	do { \
+		printk(KERN_INFO "OWL_HDMI: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define DEBUG_ON(format, ...)
+#endif
+
+#define ERR_DEBUG
+#ifdef ERR_DEBUG
+#define DEBUG_ERR(format, ...) \
+	do { \
+		printk(KERN_ERR "OWL_HDMI_ERR: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define DEBUG_ERR(format, ...)
+#endif
+
+#define DEBUG
+#ifdef DEBUG
+#define HDMI_DEBUG(format, ...) \
+	do { \
+		printk(KERN_DEBUG "OWL_HDMI_DEBUG: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define HDMI_DEBUG(format, ...)
+#endif
+
+#define DEBUG_HDCPa
+#ifdef DEBUG_HDCP
+#define HDCP_DEBUG(format, ...) \
+	do { \
+		printk(KERN_INFO "OWL_HDCP: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define HDCP_DEBUG(format, ...)
+#endif
+
+#define DEBUG_EDIDa
+#ifdef DEBUG_EDID
+#define EDID_DEBUG(format, ...) \
+	do { \
+		printk(KERN_INFO "OWL_EDID: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define EDID_DEBUG(format, ...)
+#endif
+
+#define HDCP_CASE(format, ...) \
+	do { \
+		printk(KERN_INFO "HDCP_CASE: " format, ## __VA_ARGS__); \
+	} while (0)
+	
+/*add macro to diff IC*/
+#define IC_TYPE_ATM7039C	 0x01  
+#define IC_TYPE_ATM7059TC	 0x02
+#define IC_TYPE_ATM7059A	 0x03 
+
+struct hdmi_ip_data;
+
+enum VIDEO_ID_TABLE {
+	VID640x480P_60_4VS3 = 1,
+	VID720x480P_60_4VS3,
+	VID1280x720P_60_16VS9 = 4,
+	VID1920x1080I_60_16VS9,
+	VID720x480I_60_4VS3,
+	VID1920x1080P_60_16VS9 = 16,
+	VID720x576P_50_4VS3,
+	VID1280x720P_50_16VS9 = 19,
+	VID1920x1080I_50_16VS9,
+	VID720x576I_50_4VS3,
+	VID1440x576P_50_4VS3 = 29,
+	VID1920x1080P_50_16VS9 = 31,
+	VID1920x1080P_24_16VS9,
+	VID1280x720P_60_DVI = 126,
+	VID_MAX
+}; 
+
+enum hdmi_core_hdmi_dvi {
+	HDMI_DVI = 0,
+	HDMI_HDMI = 1
+};
+
+enum hdmi_core_irq_state {
+	HDMI_HPD_IRQ = 0x1,
+	HDMI_CEC_IRQ = 0x2,
+};
+enum hdmi_clk_refsel {
+	HDMI_REFSEL_PCLK = 0,
+	HDMI_REFSEL_REF1 = 1,
+	HDMI_REFSEL_REF2 = 2,
+	HDMI_REFSEL_SYSCLK = 3
+};
+
+enum SRC_SEL {
+	VITD = 0,
+	DE,
+	SRC_MAX
+};
+
+enum FORMAT_3D{
+	NOT_3D= 0,
+	IS_3D,
+	FORMAT_3D_MAX
+};
+
+enum hdmi_core_packet_mode {
+	HDMI_PACKETMODERESERVEDVALUE = 0,
+	HDMI_PACKETMODE24BITPERPIXEL = 4,
+	HDMI_PACKETMODE30BITPERPIXEL = 5,
+	HDMI_PACKETMODE36BITPERPIXEL = 6,
+	HDMI_PACKETMODE48BITPERPIXEL = 7
+};
+
+enum hdmi_packing_mode {
+	HDMI_PACK_10b_RGB_YUV444 = 0,
+	HDMI_PACK_24b_RGB_YUV444_YUV422 = 1,
+	HDMI_PACK_20b_YUV422 = 2,
+	HDMI_PACK_ALREADYPACKED = 7
+};
+
+enum hdmi_pixel_foemat{
+	RGB444 = 0,
+	YUV444 = 2
+};
+
+enum hdmi_deep_color{
+	color_mode_24bit = 0,
+	color_mode_30bit = 1,
+	color_mode_36bit = 2,
+	color_mode_48bit = 3
+};
+
+struct hw_diff {
+	int ic_type;
+	int hp_start;
+	int hp_end;
+	int vp_start;
+	int vp_end;
+	int mode_start;
+	int mode_end;
+};
+
+struct hdmi_hdcp {
+	int hdcpOper_state;
+	int hdcp_a2;
+	int hdcpOper_retry;
+	int repeater;
+	int Ri; 
+	int Ri_Read;
+	int retry_times_for_set_up_5_second;
+
+	int hdcp_check_status;
+	int need_to_delay;
+	int check_state;
+	int hot_plug_pin_status;
+	int hdcp_have_goin_authentication;
+	int hdcp_have_open_authentication;
+	int hdcp_have_authentication_finished;
+	int hdcp_error_timer_open;
+
+	unsigned char  Bksv[5];
+	unsigned char  Bstatus[2];
+	unsigned char  ksvList[128*5];
+	unsigned char  Vp[20];
+	unsigned char  hdcpOper_M0[8];
+
+	int ri_counter;
+	int Ri_Read_Error;
+	int i_error;
+	int i2c_error;
+	int hdcp_fail_times;
+
+	struct workqueue_struct *wq;
+	struct delayed_work hdcp_work;
+	struct delayed_work hdcp_err_work;
+	
+	struct delayed_work hdcp_read_key_work;
+	
+	bool read_hdcp_success;
+	bool hdcp_authentication_success;
+};
+
+struct hdmi_video_format {
+	enum hdmi_packing_mode	packing_mode;
+	u32			y_res;	/* Line per panel */
+	u32			x_res;	/* pixel per line */
+};
+
+struct hdmi_cm {
+	int	code;
+	int	mode;
+	int vid;
+};
+
+struct hdmi_settings {
+	int hdmi_src;
+	int vitd_color;
+	int enable_3d;
+	int present_3d;
+	int pixel_encoding;
+	int color_xvycc;
+	int deep_color;
+	int hdmi_mode;
+	int channel_invert;
+	int bit_invert;
+};
+
+struct hdmi_config {
+	struct owl_video_timings timings;
+	struct hdmi_cm cm;
+};
+
+struct data_flag {
+	bool hpd_en;
+	bool cable_status;
+	bool hpd_pending;
+	bool hdmi_sta;
+	bool hdcp_ri;
+	bool cable_check_onoff;
+	bool send_uevent;
+};
+
+struct drv_cfg{
+	int drv_from_dts;
+	
+	int vid480p_tx1;
+	int vid480p_tx2;
+	int vid576p_tx1;
+	int vid576p_tx2;
+	int vid720p_tx1;
+	int vid720p_tx2;
+	int vid1080p_tx1;
+	int vid1080p_tx2;
+	
+};
+
+struct hdmi_ip_data {
+	
+	void __iomem	*base;	/* HDMI*/
+	
+	const struct owl_hdmi_ip_ops *ops;
+	
+	struct hdmi_config cfg;
+
+	struct hdmi_settings settings;
+	
+	struct drv_cfg txrx_cfg;
+	
+	struct hdmi_hdcp hdcp;
+		
+	struct mutex lock;
+};
+
+struct hdmi_edid{
+
+	u8		EDID_Buf[1024];
+	u8 		Device_Support_VIC[512];
+	u8      isHDMI;
+	u8      YCbCr444_Support;
+	u32     video_formats[4];
+	bool    read_ok;
+};
+
+struct hdmi_core{
+	struct mutex lock;
+	
+	struct device *dev;
+	
+	struct platform_device *pdev;
+
+	struct hdmi_ip_data ip_data;
+	
+	struct hdmi_edid edid;
+	
+	struct data_flag data;
+	
+	struct hw_diff *hdmihw_diff;
+	
+	struct owl_dss_device *dssdev;
+
+};
+extern struct hdmi_core hdmi;
+
+struct owl_hdmi_ip_ops {
+
+	void (*hdmi_devclken)(struct hdmi_ip_data *ip_data, bool enable);
+	
+	void (*hdmi_clk24Men)(struct hdmi_ip_data *ip_data, bool enable);
+
+	void (*hdmi_reset)(struct hdmi_ip_data *ip_data);
+	
+	int (*pll_enable)(struct hdmi_ip_data *ip_data);
+
+	void (*pll_disable)(struct hdmi_ip_data *ip_data);
+	
+	int (*read_reg)(struct hdmi_ip_data *ip_data,	const u16 idx);
+	
+	void (*write_reg)(struct hdmi_ip_data *ip_data,	const u16 idx, u32 val);
+	
+	bool (*cable_check)(struct hdmi_ip_data *ip_data);
+	
+	bool (*detect)(struct hdmi_ip_data *ip_data);	
+	
+	void (*hpd_enable)(struct hdmi_ip_data *ip_data,bool enable);
+
+	void (*hpd_clear_plug)(struct hdmi_ip_data *ip_data);
+
+	void (*phy_enable)(struct hdmi_ip_data *ip_data);
+
+	void (*phy_disable)(struct hdmi_ip_data *ip_data);
+
+	void (*video_enable)(struct hdmi_ip_data *ip_data);
+
+	void (*video_disable)(struct hdmi_ip_data *ip_data);	
+
+	void (*dump_hdmi)(struct hdmi_ip_data *ip_data);	
+	
+	void (*video_configure)(struct hdmi_ip_data *ip_data);
+	
+	u32 (*get_irq_state)(struct hdmi_ip_data *ip_data);
+};
+
+/**************************
+hdmi_panel.c
+**************************/
+
+int hdmi_panel_init(void);
+void hdmi_panel_exit(void);
+
+/**************************
+hdmi.c
+**************************/
+void hdmi_send_uevent(bool data);
+
+int owldss_hdmi_display_enable(struct owl_dss_device *dssdev);
+void owldss_hdmi_display_disable(struct owl_dss_device *dssdev);
+void owldss_hdmi_display_set_timing(struct owl_dss_device *dssdev,	struct owl_video_timings *timings);
+void owldss_hdmi_display_set_vid(struct owl_dss_device *dssdev,	int vid);
+void owldss_hdmi_display_get_vid(struct owl_dss_device *dssdev, int *vid);
+void owldss_hdmi_display_set_overscan(struct owl_dss_device *dssdev,u16 over_scan_width,u16 over_scan_height);
+void owldss_hdmi_display_get_overscan(struct owl_dss_device *dssdev, u16 * over_scan_width,u16 * over_scan_height);
+void owldss_hdmi_display_enable_hotplug(struct owl_dss_device *dssdev, bool enable);
+void owldss_hdmi_display_enable_hdcp(struct owl_dss_device *dssdev, bool enable);
+int owldss_hdmi_display_get_vid_cap(struct owl_dss_device *dssdev, int *vid_cap);
+int owldss_hdmi_display_get_cable_status(struct owl_dss_device *dssdev);
+int owldss_hdmi_read_edid(struct owl_dss_device *dssdev, u8 * buffer , int len);
+int owldss_hdmi_display_check_timing(struct owl_dss_device *dssdev, struct owl_video_timings *timings);
+int owldss_hdmi_panel_init(struct owl_dss_device *dssdev);
+int owl_hdmi_init_platform(void);
+int owl_hdmi_uninit_platform(void);
+
+int owldss_hdmi_panel_suspend(struct owl_dss_device *dssdev);
+int owldss_hdmi_panel_resume(struct owl_dss_device *dssdev);
+
+int owldss_hdmi_hotplug_debug(struct owl_dss_device *dssdev,int enable);
+int owldss_hdmi_cable_debug(struct owl_dss_device *dssdev,int enable);
+int owldss_hdmi_uevent_debug(struct owl_dss_device *dssdev,int enable);
+
+void owl_hdmi_set_effect_parameter(struct owl_dss_device *dssdev,enum owl_plane_effect_parameter parameter_id ,int value);
+int owl_hdmi_get_effect_parameter(struct owl_dss_device *dssdev, enum owl_plane_effect_parameter parameter_id);
+void hdmihw_write_reg(u32 val, const u16 idx);
+int hdmihw_read_reg(const u16 idx);
+/**************************
+hdmi_ip.c
+**************************/
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+
+/**************************
+hdmi_sysfs.c
+**************************/
+int owl_hdmi_create_sysfs(struct device *dev);
+/**************************
+hdmi_edid.c
+**************************/
+int ddc_init(void);
+int parse_edid(struct hdmi_edid *edid);
+int read_edid(u8 * edid , int len);
+int i2c_hdcp_write(const char *buf, unsigned short offset, int count) ;
+int i2c_hdcp_read(char *buf, unsigned short offset, int count) ;
+/**************************
+hdcp.c
+**************************/
+void hdcp_check_handle(struct work_struct *work);
+int hdcp_read_key(void);
+void hdcp_init(void);
+int hdcp_check_ri(void);
+int check_ri_irq(void);
+/**************************
+hdmi_packet.c
+**************************/
+int  asoc_hdmi_gen_infoframe(struct hdmi_ip_data *ip_data);
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec.c
new file mode 100755
index 0000000..afd0236
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec.c
@@ -0,0 +1,404 @@
+/*
+ * hdmi_cecc
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: HaiYu Huang  <huanghaiyu at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/sched.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+
+#include "cec.h"
+#include "cec_reg.h"
+
+#define CEC_IOC_MAGIC        'c'
+#define CEC_IOC_SETLADDR     _IOW(CEC_IOC_MAGIC, 0, unsigned int)
+
+#define VERSION   "1.0" /* Driver version number */
+#define CEC_MINOR 243	/* Major 10, Minor 242, /dev/cec */
+
+
+#define CEC_STATUS_TX_BYTES         (1<<0)
+#define CEC_STATUS_TX_ERROR         (1<<5)
+#define CEC_STATUS_TX_DONE          (1<<6)
+#define CEC_STATUS_TX_TRANSFERRING  (1<<7)
+
+#define CEC_STATUS_RX_BYTES         (1<<8)
+#define CEC_STATUS_RX_ERROR         (1<<13)
+#define CEC_STATUS_RX_DONE          (1<<14)
+#define CEC_STATUS_RX_TRANSFERRING  (1<<15)
+
+
+
+/* CEC Rx buffer size */
+#define CEC_RX_BUFF_SIZE            16
+/* CEC Tx buffer size */
+#define CEC_TX_BUFF_SIZE            16
+
+static atomic_t hdmi_on = ATOMIC_INIT(0);
+static DEFINE_MUTEX(cec_lock);
+struct clk *hdmi_cec_clk;
+
+static int hdmi_cec_open(struct inode *inode, struct file *file)
+{
+	int ret = 0;
+
+	mutex_lock(&cec_lock);
+	clk_enable(hdmi_cec_clk);
+
+	if (atomic_read(&hdmi_on)) {
+		hdmi_cec_dbg("do not allow multiple open for tvout cec\n");
+		ret = -EBUSY;
+		goto err_multi_open;
+	} else
+		atomic_inc(&hdmi_on);
+	
+	hdmi_cec_hw_init();
+	
+	hdmi_cec_reset();
+	
+	hdmi_cec_set_rx_state(STATE_RX);
+	
+	hdmi_cec_unmask_rx_interrupts();
+	
+	hdmi_cec_enable_rx();
+
+err_multi_open:
+	mutex_unlock(&cec_lock);
+
+	return ret;
+}
+
+static int hdmi_cec_release(struct inode *inode, struct file *file)
+{
+	atomic_dec(&hdmi_on);
+
+	hdmi_cec_mask_tx_interrupts();
+	hdmi_cec_mask_rx_interrupts();
+
+	clk_disable(hdmi_cec_clk);
+	clk_put(hdmi_cec_clk);
+
+	return 0;
+}
+
+static ssize_t hdmi_cec_read(struct file *file, char __user *buffer,
+			size_t count, loff_t *ppos)
+{
+	ssize_t retval;
+	unsigned long spin_flags;
+	
+	if (wait_event_interruptible(cec_rx_struct.waitq,
+			atomic_read(&cec_rx_struct.state) == STATE_DONE)) {
+		return -ERESTARTSYS;
+	}
+	spin_lock_irqsave(&cec_rx_struct.lock, spin_flags);
+
+	if (cec_rx_struct.size > count) {
+		spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+		return -1;
+	}
+ 
+	if (copy_to_user(buffer, cec_rx_struct.buffer, cec_rx_struct.size)) {
+		spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+		printk(KERN_ERR " copy_to_user() failed!\n");
+		return -EFAULT;
+	}
+
+	retval = cec_rx_struct.size;
+
+	hdmi_cec_set_rx_state(STATE_RX);
+	
+	spin_unlock_irqrestore(&cec_rx_struct.lock, spin_flags);
+
+	return retval;
+}
+
+static ssize_t hdmi_cec_write(struct file *file, const char __user *buffer,
+			size_t count, loff_t *ppos)
+{
+	char *data;
+
+	/* check data size */
+	if (count > CEC_TX_BUFF_SIZE || count == 0){
+		printk(KERN_ERR" hdmi_cec_write count -- %d line %d error \n",count,__LINE__);
+		return -1;
+	}
+
+	data = kmalloc(count, GFP_KERNEL);
+
+	if (!data) {
+		printk(KERN_ERR " kmalloc() failed!\n");
+		return -1;
+	}
+
+	if (copy_from_user(data, buffer, count)) {
+		printk(KERN_ERR " copy_from_user() failed!\n");
+		kfree(data);
+		return -EFAULT;
+	}
+
+	/*disable rx  switch to tx mode*/
+	hdmi_cec_disable_rx();
+
+	hdmi_cec_copy_packet(data, count);
+	
+	kfree(data);
+
+	/* wait for interrupt */
+
+	if (wait_event_interruptible(cec_tx_struct.waitq,
+		atomic_read(&cec_tx_struct.state)
+		!= STATE_TX)) {
+
+		return -ERESTARTSYS;
+	}
+
+	hdmi_cec_disable_tx();
+	
+	/*cec_reset*/
+	hdmi_cec_reset();
+	
+	/*switch to rx mode*/	
+	hdmi_cec_unmask_rx_interrupts(); 	
+		
+	hdmi_cec_enable_rx();
+	
+	if (atomic_read(&cec_tx_struct.state) == STATE_ERROR){
+		return -1;
+	}
+
+	return count;
+}
+static long hdmi_cec_ioctl(struct file *file, unsigned int cmd,
+						unsigned long arg)
+
+{
+	u32 laddr;
+	hdmi_cec_dbg(" hdmi_cec_ioctl  cmd 0x%x \n",cmd);
+	switch (cmd) {
+	case CEC_IOC_SETLADDR:
+		
+		if (get_user(laddr, (u32 __user *) arg))
+			return -EFAULT;
+		hdmi_cec_dbg(" hdmi_cec_ioctl  CEC_IOC_SETLADDR 0x%x \n",
+					laddr);
+		hdmi_cec_set_addr(laddr);
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static u32 hdmi_cec_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &cec_rx_struct.waitq, wait);
+	if (atomic_read(&cec_rx_struct.state) == STATE_DONE)
+		{
+			hdmi_cec_dbg("owl_hdmi_cec_poll ok \n");
+		return POLLIN | POLLRDNORM;
+		}
+	return 0;
+}
+
+static const struct file_operations cec_fops = {
+	.owner   = THIS_MODULE,
+	.open    = hdmi_cec_open,
+	.release = hdmi_cec_release,
+	.read    = hdmi_cec_read,
+	.write   = hdmi_cec_write,
+	.unlocked_ioctl = hdmi_cec_ioctl,
+	.poll    = hdmi_cec_poll,
+};
+
+static struct miscdevice cec_misc_device = {
+	.minor = CEC_MINOR,
+	.name  = "CEC",
+	.fops  = &cec_fops,
+};
+
+void hdmi_cec_irq_handler(void)
+{
+
+	u32 status = 0;
+	status = hdmi_cec_get_status();
+	if (status & CEC_STATUS_TX_DONE) {
+		if (status & CEC_STATUS_TX_ERROR) {
+			hdmi_cec_dbg(" CEC_STATUS_TX_ERROR!\n");
+			hdmi_cec_set_tx_state(STATE_ERROR);
+		} else {
+			hdmi_cec_dbg(" CEC_STATUS_TX_DONE!\n");
+			hdmi_cec_set_tx_state(STATE_DONE);
+		}
+
+		hdmi_cec_clr_pending_tx();
+
+		wake_up_interruptible(&cec_tx_struct.waitq);
+	}
+
+	if (status & CEC_STATUS_RX_DONE) {
+		if (status & CEC_STATUS_RX_ERROR) {
+			hdmi_cec_dbg(" CEC_STATUS_RX_ERROR!\n");
+			hdmi_cec_rx_reset();
+			hdmi_cec_unmask_rx_interrupts();
+			hdmi_cec_enable_rx();
+		} else {
+			u32 size;
+			u8 header;
+
+			hdmi_cec_dbg(" CEC_STATUS_RX_DONE!\n");
+
+			/* copy data from internal buffer */
+			size = (status >> 8) & 0x0f;
+
+			header = hdmi_cec_get_rx_header();
+			cec_rx_struct.buffer[0] = header;
+
+			spin_lock(&cec_rx_struct.lock);
+			
+			hdmi_cec_get_rx_buf(size, cec_rx_struct.buffer);
+
+			cec_rx_struct.size = size + 1;/*includ 1 byte header*/
+
+			hdmi_cec_set_rx_state(STATE_DONE);
+
+			spin_unlock(&cec_rx_struct.lock);
+			
+			/*after receive data reset rx*/
+			hdmi_cec_rx_reset();
+			hdmi_cec_unmask_rx_interrupts(); 
+			hdmi_cec_enable_rx();
+		}
+
+		/* clear interrupt pending bit */
+		hdmi_cec_clr_pending_rx();
+
+		wake_up_interruptible(&cec_rx_struct.waitq);
+	}
+
+	return;
+}
+EXPORT_SYMBOL(hdmi_cec_irq_handler);
+static int hdmi_cec_probe(struct platform_device *pdev)
+{
+	u8 *buffer;
+
+	hdmi_cec_mem_probe(pdev);	
+	if (misc_register(&cec_misc_device)) {
+		printk(KERN_WARNING " Couldn't register device 10, %d.\n",
+				CEC_MINOR);
+		return -EBUSY;
+	}	
+
+	spin_lock_init(&cec_rx_struct.lock);
+	init_waitqueue_head(&cec_rx_struct.waitq);	
+	init_waitqueue_head(&cec_tx_struct.waitq);
+
+	buffer = kmalloc(CEC_TX_BUFF_SIZE, GFP_KERNEL);
+
+	if (!buffer) {
+		printk(KERN_ERR " kmalloc() failed!\n");
+		misc_deregister(&cec_misc_device);
+		return -EIO;
+	}
+
+	cec_rx_struct.buffer = buffer;
+
+	cec_rx_struct.size   = 0;
+
+	dev_info(&pdev->dev, "probe successful\n");
+
+	return 0;
+}
+
+static int hdmi_cec_remove(struct platform_device *pdev)
+{
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int hdmi_cec_suspend(struct platform_device *dev, pm_message_t state)
+{
+	return 0;
+}
+
+static int hdmi_cec_resume(struct platform_device *dev)
+{
+	return 0;
+}
+#else
+#define hdmi_cec_suspend NULL
+#define hdmi_cec_resume NULL
+#endif
+
+static struct of_device_id owl_hdmi_cec_of_match[] = {
+	{
+		.compatible = "actions,atm7059a-hdmi-cec",
+	},
+	{},
+};
+
+static struct platform_driver hdmi_cec_driver = {
+	.probe		= hdmi_cec_probe,
+	.remove		= hdmi_cec_remove,
+	.suspend	= hdmi_cec_suspend,
+	.resume		= hdmi_cec_resume,
+	.driver		= {
+		.name	= "atm7059a-hdmi-cec",
+		.owner	= THIS_MODULE,
+		.of_match_table = owl_hdmi_cec_of_match,
+	},
+};
+
+static char banner[] __initdata =
+	"Actions CEC for OWL Driver, (c) 2009 ACTIONS Electronics\n";
+
+static int __init hdmi_cec_init(void)
+{
+	int ret;
+
+	printk(banner);
+	ret = platform_driver_register(&hdmi_cec_driver);
+	if (ret) {
+		printk(KERN_ERR "Platform Device Register Failed %d\n", ret);
+
+		return -1;
+	}
+	hdmi_cec_dbg("platform_driver_register hdmi-cec \n");
+	return 0;
+}
+
+static void __exit hdmi_cec_exit(void)
+{
+	kfree(cec_rx_struct.buffer);
+
+	platform_driver_unregister(&hdmi_cec_driver);
+}
+
+module_init(hdmi_cec_init);
+module_exit(hdmi_cec_exit);
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec_ctrl.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec_ctrl.c
new file mode 100755
index 0000000..f40829c
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_cec_ctrl.c
@@ -0,0 +1,406 @@
+/*
+ * hdmi_cec_ctrl.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: HaiYu Huang  <huanghaiyu at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/irqreturn.h>
+#include <linux/stddef.h>
+
+#include "cec_reg.h"
+#include "cec.h"
+
+#define CEC_MESSAGE_BROADCAST_MASK	0x0F
+#define CEC_MESSAGE_BROADCAST		0x0F
+
+
+static struct resource	*cec_mem;
+void __iomem		*cec_base;
+
+struct cec_rx_struct cec_rx_struct;
+struct cec_tx_struct cec_tx_struct;
+
+void hdmi_cec_hw_init(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECCR);
+	reg &= 0xffffff;	        //clear bit31:24
+    reg |= (1<<28);	//PreDiv = 33;timerdiv = 0.8MHz/0.04MHz;disable DAC test
+	writel(reg, cec_base + HDMI_CECCR);
+	
+	reg = readl(cec_base + HDMI_CECRTCR);
+    reg &= 0xfffffff0;
+    reg |= 5;
+    writel(reg,cec_base + HDMI_CECRTCR);    
+    
+    writel(0x8cbc2a51,cec_base + HDMI_CECRXTCR);
+    
+    
+    //CECTxTCR Register
+    writel(0x9420,cec_base + HDMI_CECTXTCR0); 
+    writel(0x182424,cec_base + HDMI_CECTXTCR1);
+    
+    //enable CEC mode
+    reg = readl(cec_base + HDMI_CECCR);
+    reg |= (1<<30);
+    reg |= (4<<24);
+    writel(reg,cec_base + HDMI_CECCR);
+
+    reg = readl(cec_base + CEC_DDC_HPD);
+    reg |= 0x10;
+    reg &= 0xfffffffe;
+    writel(reg,cec_base + CEC_DDC_HPD);			//enable cec internal pull up resistor   
+}
+
+void hdmi_cec_enable_rx(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECRXCR);
+	reg |= CES_RX_CTRL_ENABLE;
+	writel(reg, cec_base + HDMI_CECRXCR);
+}
+
+/*we can't disable rx ,used reset replace disable rx*/
+void hdmi_cec_disable_rx(void)
+{
+	u32 reg;	
+	reg = readl(cec_base + HDMI_CECRXCR);
+
+	reg |= CES_RX_CTRL_RESET;
+	
+	writel(reg, cec_base + HDMI_CECRXCR);
+	
+	while((readl(cec_base + HDMI_CECRXCR) & 0x4000) != 0);
+}
+
+void hdmi_cec_disable_tx(void)
+{
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECTXCR);
+	reg &= ~CES_TX_CTRL_ENABLE;
+	writel(reg, cec_base + HDMI_CECTXCR);
+}
+
+void hdmi_cec_enable_tx(void)
+{
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECTXCR);
+	reg |= CES_TX_CTRL_ENABLE;
+	writel(reg, cec_base + HDMI_CECTXCR);
+}
+
+void hdmi_cec_mask_rx_interrupts(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECRXCR);
+	reg &= ~CES_RX_IRQ_ENABLE;		/*close cec rx interrupt*/
+	reg &= ~CES_RX_IRQ_PENDDING;		
+	writel(reg, cec_base + HDMI_CECRXCR);
+}
+
+void hdmi_cec_unmask_rx_interrupts(void)
+{
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECRXCR);
+	reg |= CES_RX_IRQ_ENABLE;		/*enable cec rx interrupt*/
+	reg |= CES_RX_IRQ_PENDDING;		/*set 1 reset cec rx interrupt*/
+	writel(reg, cec_base + HDMI_CECRXCR);
+}
+
+void hdmi_cec_mask_tx_interrupts(void)
+{
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECTXCR);
+	reg &= ~CES_TX_IRQ_ENABLE;
+	reg &= ~CES_TX_IRQ_PENDDING;
+	writel(reg, cec_base + HDMI_CECTXCR);
+
+}
+
+void hdmi_cec_unmask_tx_interrupts(void)
+{
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECTXCR);
+	reg |= CES_TX_IRQ_ENABLE;
+	reg |= CES_TX_IRQ_PENDDING;
+	writel(reg, cec_base + HDMI_CECTXCR);
+}
+
+void hdmi_cec_reset(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECRXCR);
+	
+	reg |= CES_RX_CTRL_RESET;
+	
+	writel(reg, cec_base + HDMI_CECRXCR);
+	
+	while(readl(cec_base + HDMI_CECRXCR) & 0x4000);
+	
+	reg = readl(cec_base + HDMI_CECTXCR);
+	
+	reg |= CES_TX_CTRL_RESET;
+	
+	writel(reg, cec_base + HDMI_CECTXCR);
+	
+	while(readl(cec_base + HDMI_CECTXCR) & 0x4000);
+
+}
+
+void hdmi_cec_tx_reset(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECTXCR);
+	
+	reg |= CES_TX_CTRL_RESET;
+	
+	writel(reg, cec_base + HDMI_CECTXCR);
+	
+	while(readl(cec_base + HDMI_CECTXCR) & 0x4000);
+}
+
+void hdmi_cec_rx_reset(void)
+{
+	u32 reg;
+	
+	reg = readl(cec_base + HDMI_CECRXCR);
+	
+	reg |= CES_RX_CTRL_RESET;
+	
+	writel(reg, cec_base + HDMI_CECRXCR);
+	
+	while(readl(cec_base + HDMI_CECRXCR) & 0x4000);
+}
+
+void hdmi_cec_set_tx_state(enum cec_state state)
+{
+	atomic_set(&cec_tx_struct.state, state);
+}
+
+void hdmi_cec_set_rx_state(enum cec_state state)
+{
+	atomic_set(&cec_rx_struct.state, state);
+}
+
+void hdmi_cec_copy_packet(char *data, size_t count)
+{
+	int i = 1;
+	u8 initiator;
+	u8 destination;
+	u32 reg;	
+	
+	initiator = ((data[0] >> 4) & 0x0f);
+	destination = (data[0] & 0x0f);
+	
+	hdmi_cec_dbg(" %s count %d %d initiator %d destination %d \n",__FUNCTION__,count,__LINE__,initiator,destination);
+	
+	/*reset TX */
+	hdmi_cec_tx_reset();	
+	
+	/*write data */
+	while (i < count) {
+		writel(data[i], cec_base + HDMI_CECTXDR);
+		i++;
+	}
+
+    /*config destination*/
+	reg = readl(cec_base + HDMI_CECTXCR);	
+	
+	reg &= ~CES_TX_CTRL_BCAST;
+		
+	reg |= (destination << 8);
+		
+	writel(reg, cec_base + HDMI_CECTXCR);
+	
+	/*config initiator*/
+	reg = readl(cec_base + HDMI_CECCR);
+	
+	reg &= ~ (0x0f << 24);
+	reg |= ((initiator & 0x0F) << 24);	
+	
+	writel(reg, cec_base + HDMI_CECCR);
+	
+	/*set count*/
+	reg = readl(cec_base + HDMI_CECTXCR);
+	reg &= ~0x0f;
+	reg |= count;	
+	writel(reg, cec_base + HDMI_CECTXCR);
+	
+	/*set tx */
+	hdmi_cec_set_tx_state(STATE_TX);
+	
+	/*enable tx*/
+	hdmi_cec_enable_tx();
+	
+	/*enable tx interrupts*/	
+	hdmi_cec_unmask_tx_interrupts();	
+}
+
+void hdmi_cec_set_addr(u32 addr)
+{
+	u32 reg;
+	hdmi_cec_dbg("hdmi_cec_set_addr addr %d \n ",addr);
+	reg = readl(cec_base + HDMI_CECCR);
+	
+	reg &= ~ (0x0f << 24);
+	reg |= ((addr & 0x0F) << 24);
+	
+	writel(reg, cec_base + HDMI_CECCR);
+	
+}
+
+u32 hdmi_cec_get_status(void)
+{
+	u32 status = 0;
+
+	status = (readl(cec_base + HDMI_CECTXCR) & 0xff);
+	status |= (readl(cec_base + HDMI_CECRXCR) & 0xff) << 8;
+
+	if((status & CES_TX_IRQ_PENDDING) != 0){
+		status |= CES_TX_IRQ_PENDDING;
+		if(!((readl(cec_base + HDMI_CECCR) >> 29) & 0x1))
+		{
+			status |= CES_TX_FIFO_RRROR;
+		}
+	}
+	return status;
+}
+
+void hdmi_cec_clr_pending_tx(void)
+{
+	u32 reg;
+
+	reg = readl(cec_base + HDMI_CECTXCR);
+
+	reg |= CES_TX_IRQ_PENDDING;
+	
+	writel(reg,	cec_base + HDMI_CECTXCR);
+}
+
+void hdmi_cec_clr_pending_rx(void)
+{
+
+	u32 reg;
+	reg = readl(cec_base + HDMI_CECRXCR);
+
+	reg |= CES_RX_IRQ_PENDDING;
+	
+	writel(reg,	cec_base + HDMI_CECRXCR);
+}
+u8 hdmi_cec_get_rx_header(void)
+{
+	u8 initiator;
+	u8 destination;
+	u8 rx_header;
+
+	initiator = (readl(cec_base + HDMI_CECRXCR) >> 8) & 0xf;
+	
+	if((readl(cec_base + HDMI_CECRXCR) >> 16) & 0x1)
+		destination = 0xf;
+		else
+			destination = (readl(cec_base + HDMI_CECCR) >> 24) & 0xf;
+			
+			initiator = (readl(cec_base + HDMI_CECRXCR) >> 8) & 0xf;
+	rx_header = (initiator << 4) | destination;
+	hdmi_cec_dbg("rx_header: %x\n", rx_header);
+	return rx_header;
+}
+void hdmi_cec_get_rx_buf(u32 size, u8 *buffer)
+{
+	u32 i = 1;
+	u32 reg;
+	u8 count = size + 1;
+	while(readl(cec_base + HDMI_CECRXCR) & 0x1F)
+	{
+		if(i < count){
+			buffer[i] = readl(cec_base + HDMI_CECRXDR);
+			i++;
+		}
+	}
+	
+#if 0
+	hdmi_cec_dbg("hdmi_cec_get_rx_buf size 0x%x: ",size);
+	for(i = 0 ; i < size ; i++)
+	{
+		hdmi_cec_dbg(" 0x%x ",buffer[i]);
+	}
+#endif
+	
+	if ((readl(cec_base + HDMI_CECRXCR)>>7) & 0x1)                  //Rx EOM 
+	{   
+		reg = readl(cec_base + HDMI_CECRXCR);
+	
+		reg |= 1<<14;
+		
+		writel(reg, cec_base + HDMI_CECRXCR);
+
+		while((readl(cec_base + HDMI_CECRXCR) & 0x4000) != 0);
+	}	   
+}
+
+int hdmi_cec_mem_probe(struct platform_device *pdev)
+{
+	struct resource *cec_mem;
+	int	ret = 0;
+	hdmi_cec_dbg("%s %d \n",__FUNCTION__,__LINE__);
+	dev_dbg(&pdev->dev, "%s\n", __func__);
+
+	cec_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (cec_mem == NULL) {
+		dev_err(&pdev->dev,
+			"failed to get memory region resource for cec\n");
+		return -ENOENT;
+	}	
+
+	cec_base = ioremap(cec_mem->start, resource_size(cec_mem));
+
+	if (cec_base == NULL) {
+		dev_err(&pdev->dev,
+			"failed to ioremap address region for cec\n");
+		return -ENOENT;
+	}
+
+	return ret;
+}
+
+int __init hdmi_cec_mem_release(struct platform_device *pdev)
+{
+	iounmap(cec_base);
+
+	if (cec_mem != NULL) {
+		if (release_resource(cec_mem))
+			dev_err(&pdev->dev,
+				"Can't remove tvout drv !!\n");
+
+		kfree(cec_mem);
+
+		cec_mem = NULL;
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_edid.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_edid.c
new file mode 100755
index 0000000..a714942
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_edid.c
@@ -0,0 +1,745 @@
+/*
+ * hdmi_edid.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+
+
+#define VID1920x1080P_24_16VS9_3D_FP  (VID1920x1080P_24_16VS9 +0x80)
+#define VID1280x720P_50_16VS9_3D_FP   (VID1280x720P_50_16VS9  +0x80)
+#define VID1280x720P_60_16VS9_3D_FP   (VID1280x720P_60_16VS9  +0x80)
+
+#define HDMI_EDID_ADDR		(0x60 >> 1)
+#define HDMI_EDID_DDC_ADDR	(0xa0 >> 1)
+
+#define IIC_FROM_DTS
+
+extern void set_hdmi_i2c_flag(int flag);
+
+struct edid_dev {
+	struct i2c_client *client;
+	
+};
+
+#ifndef IIC_FROM_DTS
+static struct i2c_board_info i2c_hdmi_devices ={	
+	I2C_BOARD_INFO("hdmi_read_edid", 0x60),	
+};
+#endif
+
+static const struct i2c_device_id hdmi_edid_id[] = {
+	{ "hdmi_read_edid", 0 },
+	{ }
+};
+
+static const struct of_device_id hdmi_edid_of_match[] = {
+	{ "actions,hdmi_read_edid" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c,hdmi_edid_id);
+MODULE_DEVICE_TABLE(of, hdmi_edid_of_match);
+
+struct edid_dev *edid_devp;
+
+static int hdmi_iic_probe(struct i2c_client *client,
+        const struct i2c_device_id *id)
+{
+    int err = 0;
+	
+	EDID_DEBUG("ok iic~~~~~~~\n");
+	edid_devp->client = client;
+	return err;
+}
+
+static int hdmi_iic_remove(struct i2c_client *i2c)
+{
+	return 0;
+}
+
+static struct i2c_driver hdmi_iic_driver = {
+    .driver = {
+        .owner    = THIS_MODULE,
+        .name    = "hdmi_iic",
+		.of_match_table = of_match_ptr(hdmi_edid_of_match),
+    },
+	.id_table	  = hdmi_edid_id,
+    .probe        = hdmi_iic_probe,
+	.remove		  = hdmi_iic_remove,
+};
+
+static int i2c_check_adapter(void)
+{
+	EDID_DEBUG("i2c_check_adapter iic~~~~~~~\n");
+	if((edid_devp)&&(edid_devp->client)){
+		EDID_DEBUG("i2c_check_adapter OK!\n");
+		return 0;	
+	}else{
+		DEBUG_ERR("i2c_check_adapter edid_devp->client = NULL!\n");
+		return -EFAULT;
+	}
+}
+
+int ddc_init(void)
+{	
+	EDID_DEBUG("[%s start]  \n", __func__);
+	EDID_DEBUG("gll i2c_add_driver~~~\n");
+#ifdef IIC_FROM_DTS
+	edid_devp = kzalloc(sizeof(struct edid_dev),GFP_KERNEL);  
+	if(i2c_add_driver(&hdmi_iic_driver))
+	{
+		DEBUG_ERR("i2c_add_driver hdmi_iic_driver error!!!\n");
+		goto err;
+	}
+#else	
+		struct i2c_adapter *i2c_adap;  
+		edid_devp = kzalloc(sizeof(struct edid_dev),GFP_KERNEL);         	        
+		i2c_adap = i2c_get_adapter(3);  
+		if (!i2c_adap) {
+			DEBUG_ERR("hdmi  adapter error!\n");
+			goto err;
+		}
+	 
+		edid_devp->client = i2c_new_device(i2c_adap, &i2c_hdmi_devices);  
+		i2c_put_adapter(i2c_adap); 
+#endif 
+	return 0;
+err:
+	kfree(edid_devp);
+	return -EFAULT;
+
+}
+
+static int ddc_read(char segment_index, char segment_offset, char * pbuf)
+{
+	int ret;
+	int retry_num = 0;
+	char segment_pointer;
+	struct i2c_msg msg[3];
+	struct i2c_adapter *adap;
+	struct i2c_client *client;
+	
+	EDID_DEBUG("[%s start]\n",__func__);
+	
+	set_hdmi_i2c_flag(1);
+
+RETRY:
+	retry_num++;
+
+	/*add i2c driver*/
+	adap = edid_devp->client->adapter;
+	client = edid_devp->client;
+	segment_pointer = (char)segment_index;
+	
+	/* set segment pointer */
+	msg[0].addr = HDMI_EDID_ADDR;
+	msg[0].flags = client->flags | I2C_M_IGNORE_NAK;
+	msg[0].buf = &segment_pointer;
+	msg[0].len = 1;
+	msg[1].addr = HDMI_EDID_DDC_ADDR;
+	msg[1].flags = client->flags;
+	msg[1].buf = &segment_offset;
+	msg[1].len = 1;
+	msg[2].addr = HDMI_EDID_DDC_ADDR;
+	msg[2].flags = client->flags  | I2C_M_RD;
+	msg[2].buf = pbuf;
+	msg[2].len = 128;
+
+	ret = i2c_transfer(adap, msg, 3);
+
+	if (ret != 3) {
+		
+		DEBUG_ERR("[in %s]fail to read EDID ret %d \n",__func__,ret);
+		ret = -1;
+		goto RETURN1;
+		
+	} 
+	EDID_DEBUG("[%s finished]\n",__func__);
+
+RETURN1:
+	if ((ret < 0) && (retry_num < 3)) {
+		
+		EDID_DEBUG("ret_val1 is %d,retry_num is %d\n",ret,retry_num);
+		EDID_DEBUG("[in %s]the %dth read EDID error,try again\n", __func__,retry_num);
+
+		goto RETRY;
+		
+	} else {
+	
+		set_hdmi_i2c_flag(0);
+	
+		return ret;
+	}    	
+}
+
+static int get_edid_data(u8 block,u8 *buf)
+{
+	u8 i;
+    u8 * pbuf = buf + 128*block;
+    u8 offset = (block&0x01)? 128:0;
+  
+	if(ddc_read(block>>1,offset,pbuf)<0)
+	{
+		DEBUG_ERR("read edid error!!!\n");
+		return -1;
+	}
+//	edid_test(offset, pbuf);
+	////////////////////////////////////////////////////////////////////////////
+    EDID_DEBUG("Sink : EDID bank %d:\n",block);
+
+	EDID_DEBUG(" 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\n");
+	EDID_DEBUG(" ===============================================================================================\n");
+
+	for (i = 0; i < 8; i++) 
+	{
+		EDID_DEBUG(" %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x\n",
+				pbuf[i*16 + 0 ],pbuf[i*16 + 1 ],pbuf[i*16 + 2 ],pbuf[i*16 + 3 ],
+				pbuf[i*16 + 4 ],pbuf[i*16 + 5 ],pbuf[i*16 + 6 ],pbuf[i*16 + 7 ],
+				pbuf[i*16 + 8 ],pbuf[i*16 + 9 ],pbuf[i*16 + 10],pbuf[i*16 + 11],
+				pbuf[i*16 + 12],pbuf[i*16 + 13],pbuf[i*16 + 14],pbuf[i*16 + 15]
+				);
+	}
+    EDID_DEBUG(" ===============================================================================================\n");
+
+    return 0;
+	
+}
+
+/////////////////////////////////////////////////////////////////////
+// parse_edid()
+// Check EDID check sum and EDID 1.3 extended segment.
+/////////////////////////////////////////////////////////////////////
+int edid_checksum(u8 block,u8 *buf)
+{
+    int i = 0, CheckSum = 0;
+	u8 *pbuf = buf + 128*block;
+	
+    for( i = 0, CheckSum = 0 ; i < 128 ; i++ )
+	{
+        CheckSum += pbuf[i] ; 
+        CheckSum &= 0xFF ;
+    }
+
+	if( CheckSum != 0 )
+	{
+		DEBUG_ERR("EDID block %d checksum error\n",block);
+		return -1 ;
+	}
+	return 0;
+}
+
+int edid_header_check(u8 *pbuf)
+{
+	if( pbuf[0] != 0x00 ||
+	    pbuf[1] != 0xFF ||
+	    pbuf[2] != 0xFF ||
+	    pbuf[3] != 0xFF ||
+	    pbuf[4] != 0xFF ||
+	    pbuf[5] != 0xFF ||
+	    pbuf[6] != 0xFF ||
+	    pbuf[7] != 0x00)
+	{
+    	DEBUG_ERR("EDID block0 header error\n");
+        return -1 ;
+    }
+	return 0;
+}
+
+int edid_version_check(u8 *pbuf)
+{
+    EDID_DEBUG("EDID version: %d.%d ",pbuf[0x12],pbuf[0x13]) ;
+    if( (pbuf[0x12]!= 0x01) || (pbuf[0x13]!=0x03))
+	{
+		DEBUG_ERR("Unsupport EDID format,EDID parsing exit\n");
+		return -1;
+    }
+	return 0;
+}
+
+int parse_dtd_block(struct hdmi_edid *edid, u8 *pbuf)
+{
+	u32 	pclk,sizex,Hblanking,sizey,Vblanking,Hsync_offset,Hsync_plus,
+			Vsync_offset,Vsync_plus,H_image_size,V_image_size,H_Border,
+			V_Border,pixels_total,frame_rate;
+    pclk 		= ( (u32)pbuf[1]	<< 8) + pbuf[0];
+    sizex 		= (((u32)pbuf[4] 	<< 4) & 0x0f00) + pbuf[2];
+    Hblanking 	= (((u32)pbuf[4] 	<< 8) & 0x0f00) + pbuf[3];
+    sizey 		= (((u32)pbuf[7] 	<< 4) & 0x0f00) + pbuf[5];
+    Vblanking 	= (((u32)pbuf[7] 	<< 8) & 0x0f00) + pbuf[6];
+    Hsync_offset= (((u32)pbuf[11] << 2) & 0x0300) + pbuf[8];
+    Hsync_plus 	= (((u32)pbuf[11] << 4) & 0x0300) + pbuf[9];
+    Vsync_offset= (((u32)pbuf[11] << 2) & 0x0030) + (pbuf[10] >> 4);
+    Vsync_plus 	= (((u32)pbuf[11] << 4) & 0x0030) + (pbuf[8] & 0x0f);
+    H_image_size= (((u32)pbuf[14] << 4) & 0x0f00) + pbuf[12];
+    V_image_size= (((u32)pbuf[14] << 8) & 0x0f00) + pbuf[13];
+    H_Border 	=  pbuf[15];
+	V_Border 	=  pbuf[16];
+
+	pixels_total = (sizex + Hblanking) * (sizey + Vblanking);
+
+	if( (pbuf[0] == 0) && (pbuf[1] == 0) && (pbuf[2] == 0))
+	{
+		return 0;
+	}
+	
+	if(pixels_total == 0){
+		return 0;
+	}
+	else
+	{
+		frame_rate = (pclk * 10000) /pixels_total;
+	}
+
+    if ((frame_rate == 59) || (frame_rate == 60))
+	{
+        if ((sizex== 720) && (sizey == 240))
+        {
+        	edid->Device_Support_VIC[VID720x480I_60_4VS3] = 1;
+        }
+        if ((sizex== 720) && (sizey == 480))
+        {
+        	edid->Device_Support_VIC[VID720x480P_60_4VS3] = 1;
+        }
+        if ((sizex== 1280) && (sizey == 720))
+        {
+            edid->Device_Support_VIC[VID1280x720P_60_16VS9] = 1;
+        }
+        if ((sizex== 1920) && (sizey == 540))
+        {
+            edid->Device_Support_VIC[VID1920x1080I_60_16VS9] = 1;
+        }
+        if ((sizex== 1920) && (sizey == 1080))
+        {
+            edid->Device_Support_VIC[VID1920x1080P_60_16VS9] = 1;
+        }
+    }
+	else if ((frame_rate == 49) || (frame_rate == 50))
+	{
+        if ((sizex== 720) && (sizey == 288))
+        {
+        	edid->Device_Support_VIC[VID720x576I_50_4VS3] = 1;
+        }
+        if ((sizex== 720) && (sizey == 576))
+        {
+        	edid->Device_Support_VIC[VID720x576P_50_4VS3] = 1;
+        }
+        if ((sizex== 1280) && (sizey == 720))
+        {
+            edid->Device_Support_VIC[VID1280x720P_50_16VS9] = 1;
+        }          
+        if ((sizex== 1920) && (sizey == 540))
+        {
+            edid->Device_Support_VIC[VID1920x1080I_50_16VS9] = 1;
+        }
+        if ((sizex== 1920) && (sizey == 1080))
+        {
+            edid->Device_Support_VIC[VID1920x1080P_50_16VS9] = 1;
+        }
+    }
+	else if ((frame_rate == 23) || (frame_rate == 24))
+	{
+        if ((sizex== 1920) && (sizey == 1080))
+        {
+            edid->Device_Support_VIC[VID1920x1080P_24_16VS9] = 1;
+        }
+    }
+	EDID_DEBUG("PCLK=%d\tXsize=%d\tYsize=%d\tFrame_rate=%d\n",
+		  pclk*10000,sizex,sizey,frame_rate);
+		  
+    return 0;
+}
+
+int parse_videodata_block(struct hdmi_edid *edid, u8 *pbuf,u8 size)
+{
+	int i=0;
+	while(i<size)
+	{
+		edid->Device_Support_VIC[pbuf[i] &0x7f] = 1;
+		if(pbuf[i] &0x80)
+		{
+		   EDID_DEBUG("parse_videodata_block: VIC %d(native) support\n", pbuf[i]&0x7f);
+		}
+		else
+		{
+		   EDID_DEBUG("parse_videodata_block: VIC %d support\n", pbuf[i]);
+		}
+		i++;
+	}
+	
+	////////////////////////////////////////////////////////////////////////////
+    EDID_DEBUG("parse_videodata_block : Device_Support_VIC :\n");
+
+	EDID_DEBUG(" 0   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F\n");
+	EDID_DEBUG(" ===============================================================================================\n");
+
+	for (i = 0; i < 8; i++) 
+	{
+		EDID_DEBUG(" %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x  %2.2x\n",
+				edid->Device_Support_VIC[i*16 + 0 ],edid->Device_Support_VIC[i*16 + 1 ],edid->Device_Support_VIC[i*16 + 2 ],edid->Device_Support_VIC[i*16 + 3 ],
+				edid->Device_Support_VIC[i*16 + 4 ],edid->Device_Support_VIC[i*16 + 5 ],edid->Device_Support_VIC[i*16 + 6 ],pbuf[i*16 + 7 ],
+				edid->Device_Support_VIC[i*16 + 8 ],edid->Device_Support_VIC[i*16 + 9 ],edid->Device_Support_VIC[i*16 + 10],pbuf[i*16 + 11],
+				edid->Device_Support_VIC[i*16 + 12],edid->Device_Support_VIC[i*16 + 13],edid->Device_Support_VIC[i*16 + 14],pbuf[i*16 + 15]
+				);
+	}
+    EDID_DEBUG(" ===============================================================================================\n");
+   
+	return 0;
+}
+
+int parse_audiodata_block(u8 *pbuf,u8 size)
+{
+	u8 sum = 0;
+	
+	while(sum < size)
+	{
+    	if( (pbuf[sum]&0xf8) == 0x08)
+    	{
+			EDID_DEBUG("parse_audiodata_block: max channel=%d\n",(pbuf[sum]&0x7)+1);
+			EDID_DEBUG("parse_audiodata_block: SampleRate code=%x\n",pbuf[sum+1]);
+			EDID_DEBUG("parse_audiodata_block: WordLen code=%x\n",pbuf[sum+2]);
+    	}
+    	sum += 3;
+	}
+	return 0;
+}
+
+int parse_hdmi_vsdb(struct hdmi_edid *edid, u8 * pbuf,u8 size)
+{
+	u8 index = 8;
+
+	if( (pbuf[0] ==0x03) &&	(pbuf[1] ==0x0c) &&	(pbuf[2] ==0x00) )	//check if it's HDMI VSDB
+	{
+		edid->isHDMI = HDMI_HDMI;
+		EDID_DEBUG("Find HDMI Vendor Specific DataBlock\n");
+	}
+	else
+	{
+		edid->isHDMI = HDMI_DVI;
+		return 0;
+	}
+	
+	if(size <=8)
+		return 0;
+
+	if((pbuf[7]&0x20) == 0 )
+		return 0;
+	if((pbuf[7]&0x40) == 1 )
+		index = index +2;
+	if((pbuf[7]&0x80) == 1 )
+		index = index +2;
+
+	if(pbuf[index]&0x80)		//mandatary format support
+	{
+		edid->Device_Support_VIC[VID1920x1080P_24_16VS9_3D_FP] = 1;
+		edid->Device_Support_VIC[VID1280x720P_50_16VS9_3D_FP] = 1;
+		edid->Device_Support_VIC[VID1280x720P_60_16VS9_3D_FP] = 1;
+		EDID_DEBUG("3D_present\n");
+	}
+	else
+	{
+		return 0;
+	}
+	
+	if( ((pbuf[index]&0x60) ==1) || ((pbuf[index]&0x60) ==2) )
+	{
+		EDID_DEBUG("3D_multi_present\n");
+	}
+	
+	index += (pbuf[index+1]&0xe0) + 2;
+	if(index > (size+1) )
+	   	return 0;
+	   	
+	EDID_DEBUG("3D_multi_present byte(%2.2x,%2.2x)\n",pbuf[index],pbuf[index+1]);
+
+	return 0;
+}
+
+int read_edid(u8 * edid , int len)
+{
+	int r, l;
+
+	if (len < 128)
+		return -EINVAL;
+		
+	if(i2c_check_adapter())
+	{
+		DEBUG_ERR("iic adapter error!!!\n");
+		return -1;		
+	}
+	
+	if(ddc_read(0,0,edid)<0)
+	{
+		DEBUG_ERR("read edid error!!!\n");
+		return -1;
+	}
+	
+	l = 128;
+
+	if (len >= 128 * 2 && edid[0x7e] > 0) {
+		r = ddc_read(1,0x80,edid + 0x80);
+		if (r)
+			return r;
+		l += 128;
+	}
+	return l;
+	
+}
+int parse_edid(struct hdmi_edid *edid)
+{
+    //collect the EDID ucdata of segment 0
+    u8 BlockCount ;
+    u32 i,offset ;
+
+    EDID_DEBUG("parse_edid\n");
+
+    memset(edid->Device_Support_VIC,0,sizeof(edid->Device_Support_VIC));
+    memset(edid->EDID_Buf,0,sizeof(edid->EDID_Buf));
+	memset(edid->video_formats,0,sizeof(edid->video_formats));
+	
+    edid->isHDMI = HDMI_HDMI;
+    edid->YCbCr444_Support = 0;
+	edid->read_ok = 0;
+
+	if(i2c_check_adapter())
+	{
+		DEBUG_ERR("iic adapter error!!!\n");
+		goto err0;		
+	}
+	
+    if( get_edid_data(0, edid->EDID_Buf) != 0)
+	{
+		DEBUG_ERR("get_edid_data error!!!\n");
+		goto err0;
+	}
+
+	if( edid_checksum(0, edid->EDID_Buf) != 0)
+	{
+		DEBUG_ERR("edid_checksum error!!!\n");
+		goto err0;
+	}
+
+	if( edid_header_check(edid->EDID_Buf)!= 0)
+	{
+		DEBUG_ERR("edid_header_check error!!!\n");
+		goto err0;
+	}
+
+	if( edid_version_check(edid->EDID_Buf)!= 0)
+	{
+		DEBUG_ERR("edid_version_check error!!!\n");
+		goto err0;
+	}
+	
+	parse_dtd_block(edid, edid->EDID_Buf + 0x36);	
+
+	parse_dtd_block(edid, edid->EDID_Buf + 0x48);
+
+    BlockCount = edid->EDID_Buf[0x7E];
+
+    if( BlockCount > 0 )
+    {
+	    if ( BlockCount > 4 )
+	    {
+	        BlockCount = 4 ;
+	    }
+	    for( i = 1 ; i <= BlockCount ; i++ )
+	    {
+	        get_edid_data(i, edid->EDID_Buf) ;  
+	        if( edid_checksum(i, edid->EDID_Buf)!= 0)
+	        {
+	        	return 0;
+	        }
+
+			if((edid->EDID_Buf[0x80*i+0]==2)/*&&(edid->EDID_Buf[0x80*i+1]==1)*/)
+			{
+				//add by matthew 20120809 to add rgb/yuv detect
+				if( (edid->EDID_Buf[0x80*i+1]>=1))
+				{
+						if(edid->EDID_Buf[0x80*i+3]&0x20)
+						{
+							edid->YCbCr444_Support = 1;
+							EDID_DEBUG("device support YCbCr44 output\n");
+						}
+				}
+				//end by matthew 20120809
+				
+				offset = edid->EDID_Buf[0x80*i+2];
+				if(offset > 4)		//deal with reserved data block
+				{
+					u8 bsum = 4;
+					while(bsum < offset)
+					{
+						u8 tag = edid->EDID_Buf[0x80*i+bsum]>>5;
+						u8 len = edid->EDID_Buf[0x80*i+bsum]&0x1f;
+						if( (len >0) && ((bsum + len + 1) > offset) )
+						{
+						    EDID_DEBUG("len or bsum size error\n");
+							return 0;
+						}else
+						{
+							if( tag == 1)		//ADB
+							{
+								parse_audiodata_block(edid->EDID_Buf+0x80*i+bsum+1,len);
+							}
+							else if( tag == 2)	//VDB
+							{
+								parse_videodata_block(edid, edid->EDID_Buf+0x80*i+bsum+1,len);
+							}
+							else if( tag == 3)	//vendor specific 
+							{
+								parse_hdmi_vsdb(edid, edid->EDID_Buf+0x80*i+bsum+1,len);
+							}
+						}
+
+						bsum += (len +1);
+					}
+					
+				}else
+				{
+					EDID_DEBUG("no data in reserved block%d\n",i);
+				}
+				
+				if(offset >= 4)		//deal with 18-byte timing block
+				{
+					if(offset == 4)
+					{
+						edid->isHDMI = HDMI_DVI;
+						EDID_DEBUG("dvi mode\n");
+					}				
+					while(offset < (0x80-18))
+					{
+						parse_dtd_block(edid, edid->EDID_Buf + 0x80*i + offset);	
+						offset += 18;
+					}
+					EDID_DEBUG("deal with 18-byte timing block\n");
+
+				}else
+				{
+					EDID_DEBUG("no datail timing in block%d\n",i);
+				}
+			}
+
+	    }
+    }
+	
+	for(i=0;i<128;i++)
+	{
+		if(edid->Device_Support_VIC[i]==1)
+		{
+			edid->video_formats[i/32] |= (1<<(i%32));
+		}
+	}
+	edid->video_formats[0] |= 0x04;
+	edid->read_ok = 1;
+	EDID_DEBUG("edid->video_formats[0] = 0x%x\n", edid->video_formats[0]);
+	EDID_DEBUG("edid->video_formats[1] = 0x%x\n", edid->video_formats[1]);	
+	EDID_DEBUG("edid->video_formats[2] = 0x%x\n", edid->video_formats[2]);	
+	EDID_DEBUG("edid->video_formats[3] = 0x%x\n", edid->video_formats[3]);	
+    return 0 ;
+
+err0:
+	edid->video_formats[0] = 0x80090014;
+	edid->video_formats[1] = 0;
+	edid->video_formats[2] = 0;
+	edid->video_formats[3] = 0;
+	DEBUG_ERR("read edid err0\n");
+	return -1 ;
+}
+
+#define HDCP_ADDR	(0x74 >> 1)
+int i2c_hdcp_write(const char *buf, unsigned short offset, int count) 
+{
+    int ret;
+    struct i2c_client *client = edid_devp->client;
+    struct i2c_adapter *adap = client->adapter;
+
+    struct i2c_msg msg;
+	
+	set_hdmi_i2c_flag(1);
+
+    msg.addr = HDCP_ADDR;
+    msg.flags = client->flags | I2C_M_IGNORE_NAK;
+    msg.len = count;
+    msg.buf = (char *)buf;
+
+    ret = i2c_transfer(adap, &msg, 1);
+
+    /*
+     * If everything went ok (i.e. 1 msg transmitted), return #bytes
+     * transmitted, else error code.
+     */
+	 
+	set_hdmi_i2c_flag(0);
+    return (ret == 2) ? count : ret;
+
+}
+
+int i2c_hdcp_read(char *buf, unsigned short offset, int count) 
+{
+
+    struct i2c_client *client = edid_devp->client;
+    struct i2c_adapter *adap = client->adapter;
+    struct i2c_msg msg[2];
+    int ret;
+    int i;
+	set_hdmi_i2c_flag(1);
+    msg[0].addr = HDCP_ADDR;
+    msg[0].flags = client->flags | I2C_M_IGNORE_NAK;
+    msg[0].buf = (unsigned char *)&offset;
+    msg[0].len = 1;
+    msg[1].addr = HDCP_ADDR;
+    msg[1].flags = client->flags | I2C_M_RD;
+    msg[1].buf = buf;
+    msg[1].len = count;
+    ret = i2c_transfer(adap, msg, 2);
+    for (i = 0; i < count; i++)
+    	HDCP_DEBUG("i2c hdcp read :buf[%d]   %d\n", i, msg[1].buf[i]);
+
+    /*
+     * If everything went ok (i.e. 1 msg received), return #bytes received,
+     * else error code.
+     */
+	set_hdmi_i2c_flag(0);
+    return (ret == 2) ? count : ret;
+
+}
+
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.c
new file mode 100755
index 0000000..4181d55
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.c
@@ -0,0 +1,906 @@
+/*
+ * hdmi_ip.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+#include <linux/clk.h>
+#include <mach/clkname.h>
+#include <mach/module-owl.h>
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+
+static inline void hdmi_write_reg(struct hdmi_ip_data *ip_data,	const u16 idx, u32 val)
+{
+	//HDMI_DEBUG("write base=%x  offset=%x  val=%x\n", ip_data->base, idx, val);
+	writel(val, ip_data->base + idx);
+}
+
+static inline u32 hdmi_read_reg(struct hdmi_ip_data *ip_data,const u16 idx)
+{
+	//HDMI_DEBUG("read base=%x  offset=%x \n", ip_data->base, idx);
+	return readl(ip_data->base + idx);
+}
+
+/* HDMI_CORE_VIDEO_CONFIG */
+static void hdmi_core_config_deepcolor_mode(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);	
+	val = REG_SET_VAL(val,ip_data->settings.deep_color, 17, 16);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+	return;
+}
+
+static void hdmi_core_config_pixel_fomat(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);	
+	val = REG_SET_VAL(val,ip_data->settings.pixel_encoding, 5, 4);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+	return;
+}
+
+static void hdmi_core_config_3d_mode(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);	
+	val = REG_SET_VAL(val,ip_data->settings.enable_3d, 8, 8);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+	return;
+
+}
+
+static void hdmi_core_config_mode(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);	
+	val = REG_SET_VAL(val,ip_data->settings.hdmi_mode, hdmi.hdmihw_diff->mode_end, hdmi.hdmihw_diff->mode_start);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+	return;		
+}
+
+static void hdmi_core_config_invert(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);	
+	val = REG_SET_VAL(val,ip_data->settings.bit_invert, 28, 28);
+	val = REG_SET_VAL(val,ip_data->settings.channel_invert, 29, 29);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+	return;		
+}
+
+static void hdmi_core_config_colordepth_value(struct hdmi_ip_data *ip_data)
+{
+	u32 val = 0;
+	
+	u32 mode = ip_data->settings.deep_color;	
+	
+	val = hdmi_read_reg(ip_data, HDMI_GCPCR);	
+	
+	val = REG_SET_VAL(val,mode, 7, 4);
+	
+	val = REG_SET_VAL(val,1, 31, 31);
+	
+	if(mode > HDMI_PACKETMODE24BITPERPIXEL){
+
+		val = REG_SET_VAL(val,1, 30, 30);
+
+	}else{
+
+		val = REG_SET_VAL(val,0, 30, 30);
+
+	}
+	// clear specify avmute flag in gcp packet 
+	val = REG_SET_VAL(val,1, 1, 1);	
+	
+	hdmi_write_reg(ip_data, HDMI_GCPCR, val);
+	
+	return;
+
+}
+
+static void hdmi_core_config_input_src(struct hdmi_ip_data *ip_data)
+{
+	u32 val;
+		
+	val = hdmi_read_reg(ip_data, HDMI_ICR);
+	
+	if(ip_data->settings.hdmi_src==VITD){
+		
+		val = REG_SET_VAL(val,0x01, 24, 24);
+		
+		val = REG_SET_VAL(val,hdmi.ip_data.settings.vitd_color, 23, 0);
+		
+	}else{
+		
+		val = REG_SET_VAL(val,0x00, 24, 24);
+		
+	}
+		
+	hdmi_write_reg(ip_data, HDMI_ICR, val);
+	
+	return;
+}
+
+static void hdmi_video_init_format(struct hdmi_video_format *video_fmt,
+	struct owl_video_timings *timings, struct hdmi_config *param)
+{
+	HDMI_DEBUG("Enter hdmi_video_init_format\n");
+	video_fmt->packing_mode = HDMI_PACK_24b_RGB_YUV444_YUV422;
+	video_fmt->y_res = param->timings.y_res;
+	video_fmt->x_res = param->timings.x_res;
+
+    timings->x_res = param->timings.x_res;
+    timings->y_res = param->timings.y_res;
+	timings->hbp = param->timings.hbp;
+	timings->hfp = param->timings.hfp;
+	timings->hsw = param->timings.hsw;
+	timings->vbp = param->timings.vbp;
+	timings->vfp = param->timings.vfp;
+	timings->vsw = param->timings.vsw;
+	timings->vstart = param->timings.vstart;
+	timings->repeat = param->timings.repeat;
+	
+	timings->vsync_level = param->timings.vsync_level;
+	timings->hsync_level = param->timings.hsync_level;
+	timings->interlace = param->timings.interlace;
+	timings->repeat = param->timings.repeat;
+}
+
+static void hdmi_video_config_format(struct hdmi_ip_data *ip_data,
+		struct owl_video_timings *timings)
+{
+	u32 val = 0;
+	u32 val_hp = timings->x_res + timings->hbp + timings->hfp + timings->hsw;
+	u32 val_vp = timings->y_res + timings->vbp + timings->vfp + timings->vsw;
+	HDMI_DEBUG("x %d %d %d %d\n", timings->x_res, timings->hbp, timings->hfp, timings->hsw);
+	HDMI_DEBUG("x %d %d %d %d\n", timings->y_res, timings->vbp, timings->vfp, timings->vsw);
+
+	val = hdmi_read_reg(ip_data, HDMI_VICTL);
+	val = REG_SET_VAL(val ,val_hp-1, hdmi.hdmihw_diff->hp_end, hdmi.hdmihw_diff->hp_start);
+	if(timings->interlace == 0){
+		val = REG_SET_VAL(val ,val_vp- 1, hdmi.hdmihw_diff->vp_end, hdmi.hdmihw_diff->vp_start);
+	}else{
+		val = REG_SET_VAL(val ,val_vp * 2, hdmi.hdmihw_diff->vp_end, hdmi.hdmihw_diff->vp_start);
+	}
+
+	HDMI_DEBUG("hdmi_video_config_format val = %x hp = %x vp=%x\n", val, val_hp, val_vp);	
+	hdmi_write_reg(ip_data, HDMI_VICTL, val);
+}
+
+static void hdmi_video_config_interface(struct hdmi_ip_data *ip_data, struct owl_video_timings *timings)
+{
+
+	u32 val;
+	HDMI_DEBUG("hdmi_video_config_interface timings->interlace %x\n", timings->interlace);
+	if(timings->interlace == 0){	
+		val = 0;
+		hdmi_write_reg(ip_data, HDMI_VIVSYNC, val);
+		
+	    val = hdmi_read_reg(ip_data, HDMI_VIVHSYNC);
+		if(timings->vstart!=1){
+			val = REG_SET_VAL(val ,timings->hsw - 1, 8, 0);
+			val = REG_SET_VAL(val ,timings->vstart - 2, 23, 12);
+			val = REG_SET_VAL(val ,timings->vstart + timings->vsw - 2, 27, 24);		
+		}else{
+			val = REG_SET_VAL(val ,timings->hsw - 1, 8, 0);
+			val = REG_SET_VAL(val ,timings->y_res + timings->vbp + timings->vfp + timings->vsw - 1, 23, 12);
+			val = REG_SET_VAL(val ,timings->vsw - 1, 27, 24);		
+		}
+		hdmi_write_reg(ip_data, HDMI_VIVHSYNC, val);
+		
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIVHSYNC %x\n", val);
+		
+		//VIALSEOF = (y_res + vbp + vsp - 1)  |  ((vbp + vfp - 1) << 12)
+		val = hdmi_read_reg(ip_data, HDMI_VIALSEOF);
+		val = REG_SET_VAL(val ,timings->vstart -1 + timings->vsw + timings->vbp + timings->y_res - 1, 23, 12);
+		val = REG_SET_VAL(val ,timings->vstart -1 + timings->vsw + timings->vbp - 1, 10, 0);
+		hdmi_write_reg(ip_data, HDMI_VIALSEOF, val);
+		
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIALSEOF %x\n", val);
+		
+	    val = 0;
+		hdmi_write_reg(ip_data, HDMI_VIALSEEF, val);
+	
+		//VIADLSE =  (x_res + hbp + hsp - 1)  |  ((hbp + hsw - 1) << 12)
+		val = hdmi_read_reg(ip_data, HDMI_VIADLSE);
+		val = REG_SET_VAL(val ,timings->hbp +  timings->hsw - 1, 11, 0);
+		val = REG_SET_VAL(val ,timings->x_res + timings->hbp + timings->hsw - 1, 28, 16);
+		hdmi_write_reg(ip_data, HDMI_VIADLSE, val);
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIADLSE %x\n", val);
+	}else{
+		val = 0;
+		hdmi_write_reg(ip_data, HDMI_VIVSYNC, val);
+		
+		//VIVHSYNC  = (hsw -1 ) | ((y_res + vsw + vfp + vbp - 1 ) << 12) | (vfp -1 << 24)
+	    val = hdmi_read_reg(ip_data, HDMI_VIVHSYNC);
+		val = REG_SET_VAL(val ,timings->hsw - 1, 8, 0);
+		val = REG_SET_VAL(val ,(timings->y_res + timings->vbp + timings->vfp + timings->vsw) * 2, 22, 12);
+		val = REG_SET_VAL(val ,timings->vfp * 2, 22, 12);
+		hdmi_write_reg(ip_data, HDMI_VIVHSYNC, val);
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIVHSYNC %x\n", val);
+		
+		//VIALSEOF = (y_res + vbp + vfp - 1)  |  ((vbp + vfp - 1) << 12)
+		val = hdmi_read_reg(ip_data, HDMI_VIALSEOF);
+		val = REG_SET_VAL(val ,timings->vbp + timings->vfp  - 1, 22, 12);
+		val = REG_SET_VAL(val ,(timings->y_res + timings->vbp + timings->vfp)*2, 10, 0);
+		hdmi_write_reg(ip_data, HDMI_VIALSEOF, val);
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIALSEOF %x\n", val);
+		
+	    val = 0;
+		hdmi_write_reg(ip_data, HDMI_VIALSEEF, val);
+		
+		//VIADLSE =  (x_res + hbp + hsp - 1)  |  ((hbp + hsw - 1) << 12)
+		val = hdmi_read_reg(ip_data, HDMI_VIADLSE);
+		val = REG_SET_VAL(val ,timings->hbp +  timings->hsw - 1, 27, 16);
+		val = REG_SET_VAL(val ,timings->x_res + timings->hbp + timings->hsw - 1, 11, 0);
+		hdmi_write_reg(ip_data, HDMI_VIADLSE, val);
+		HDMI_DEBUG("hdmi_video_config_interface HDMI_VIADLSE %x\n", val);
+	}
+
+}
+
+static void hdmi_video_interval_packet(struct hdmi_ip_data *ip_data, struct owl_video_timings *timings)
+{
+	u32 val;
+	HDMI_DEBUG("hdmi_video_interval_packet\n");
+	switch (ip_data->cfg.cm.code)
+	{
+		case VID640x480P_60_4VS3:
+		case VID720x480P_60_4VS3:
+		case VID720x576P_50_4VS3:
+			val = 0x701;
+			break;		
+		case VID1280x720P_60_16VS9:
+		case VID1280x720P_50_16VS9:
+		case VID1920x1080P_50_16VS9:
+		case VID1280x720P_60_DVI:
+			val = 0x1107;
+			break;
+		case VID1920x1080P_60_16VS9:
+			val = 0x1105;
+			break;
+		default:
+			val = 0x1107;
+			break;
+	}
+	hdmi_write_reg(ip_data, HDMI_DIPCCR, val);	
+}
+
+static void hdmi_video_config_timing(struct hdmi_ip_data *ip_data, struct owl_video_timings *timings)
+{
+
+	bool vsync_pol, hsync_pol ,interlace, repeat;
+	u32 val;
+	vsync_pol = timings->vsync_level == OWLDSS_SIG_ACTIVE_LOW ;
+	hsync_pol = timings->hsync_level == OWLDSS_SIG_ACTIVE_LOW ;
+	
+	interlace = timings->interlace;
+	repeat    = timings->repeat; 
+	
+	val = hdmi_read_reg(ip_data, HDMI_SCHCR);
+	val = REG_SET_VAL(val , hsync_pol, 1, 1);
+	val = REG_SET_VAL(val , vsync_pol, 2, 2);
+	hdmi_write_reg(ip_data, HDMI_SCHCR, val);
+
+	val = hdmi_read_reg(ip_data, HDMI_VICTL);
+	val = REG_SET_VAL(val ,interlace, 28, 28);
+	val = REG_SET_VAL(val ,repeat, 29, 29);
+	hdmi_write_reg(ip_data, HDMI_VICTL, val);	
+}
+
+static void ip_hdmi_devclken(struct hdmi_ip_data *ip_data, bool enable)
+{
+	if(enable){
+		module_clk_enable(MOD_ID_HDMI);	
+	}else{
+		module_clk_disable(MOD_ID_HDMI);
+	}
+}
+
+static void ip_hdmi_clk24Men(struct hdmi_ip_data *ip_data, bool enable)
+{
+	if(enable){
+		module_clk_enable(MOD_ID_TV24M);	
+	}else{
+		module_clk_disable(MOD_ID_TV24M);	
+	}	
+}
+
+static void ip_hdmi_reset(struct hdmi_ip_data *ip_data)
+{
+	HDMI_DEBUG("[%s start]\n", __func__);
+
+	HDMI_DEBUG("~~~~~module_reset \n");
+	module_reset(MOD_ID_HDMI);
+/*	
+	val = hdmi_read_reg(ip_data, HDMI_TX_1);
+	val = REG_SET_VAL(val ,1, 23, 23);
+	hdmi_write_reg(ip_data, HDMI_TX_1, val);
+	HDMI_DEBUG("[%s finished]\n", __func__);
+*/
+}
+
+static void ip_hdmi_pllpu(struct hdmi_ip_data *ip_data)
+{
+	/*u32 val;	
+	val = hdmi_read_reg(ip_data, HDMI_TX_2);
+	val = REG_SET_VAL(val ,1, 27, 27);
+	hdmi_write_reg(ip_data, HDMI_TX_2, val);
+	HDMI_DEBUG("[%s finished]\n", __func__);
+
+	val = hdmi_read_reg(ip_data, HDMI_TX_1);
+	val = REG_SET_VAL(val ,1, 23, 23);
+	hdmi_write_reg(ip_data, HDMI_TX_1, val);
+	HDMI_DEBUG("[%s finished]\n", __func__);*/
+	
+	if(hdmi.ip_data.txrx_cfg.drv_from_dts)
+	{
+		switch (ip_data->cfg.cm.code)
+		{
+			case VID640x480P_60_4VS3:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid480p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid480p_tx2&(0xfffff0ff));	
+				break;	
+			case VID720x576P_50_4VS3:
+			case VID720x480P_60_4VS3:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid576p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid576p_tx2&(0xfffff0ff));	
+				break;		
+			case VID1280x720P_60_16VS9:
+			case VID1280x720P_50_16VS9:
+			case VID1280x720P_60_DVI:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid720p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid720p_tx2&(0xfffff0ff));	
+				break;
+			case VID1920x1080P_60_16VS9:
+			case VID1920x1080P_50_16VS9:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid1080p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid1080p_tx2&(0xfffff0ff));	
+				break;
+			default:
+				DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+		}		
+	}else{
+		if(hdmi.hdmihw_diff->ic_type == IC_TYPE_ATM7059A){	
+			switch (ip_data->cfg.cm.code)
+			{
+				case VID640x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c2983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;	
+				case VID720x576P_50_4VS3:
+				case VID720x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c2983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;		
+				case VID1280x720P_60_16VS9:
+				case VID1280x720P_50_16VS9:
+				case VID1280x720P_60_DVI:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81942983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;
+				case VID1920x1080P_60_16VS9:
+				case VID1920x1080P_50_16VS9:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81902983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;
+				default:
+					DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+			}
+		}else{
+			switch (ip_data->cfg.cm.code)
+			{
+				case VID640x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c0986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;	
+				case VID720x576P_50_4VS3:
+				case VID720x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c0986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;		
+				case VID1280x720P_60_16VS9:
+				case VID1280x720P_50_16VS9:
+				case VID1280x720P_60_DVI:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81982986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);
+					break;
+				case VID1920x1080P_60_16VS9:
+				case VID1920x1080P_50_16VS9:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81940986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87&0xfffff0ff);	
+					break;
+				default:
+					DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+			}	
+		}
+	}
+}
+
+static int ip_hdmi_pll_enable(struct hdmi_ip_data *ip_data)
+{
+	u32 pix_rate = 0;
+	int ret;
+	struct clk *tvout_clk = NULL;
+	HDMI_DEBUG("PLL locked!\n");
+	switch (ip_data->cfg.cm.code)
+	{
+		case VID640x480P_60_4VS3:
+			pix_rate = 25200000;
+			break;	
+		case VID720x576P_50_4VS3:
+		case VID720x480P_60_4VS3:
+			pix_rate = 27000000;
+			break;		
+		case VID1280x720P_60_16VS9:
+		case VID1280x720P_50_16VS9:
+		case VID1280x720P_60_DVI:
+			pix_rate = 74250000;
+			break;
+		case VID1920x1080P_60_16VS9:
+		case VID1920x1080P_50_16VS9:
+			pix_rate = 148500000;
+			break;
+		default:
+			return -EINVAL;
+	}
+	
+	tvout_clk = clk_get(NULL, CLKNAME_TVOUTPLL);
+	ret = clk_set_rate(tvout_clk, pix_rate);
+	if (ret < 0) {
+		DEBUG_ERR("pixel rate set error!\n");
+		return ret;
+	}		
+	msleep(5);
+	clk_prepare(tvout_clk);
+	clk_enable(tvout_clk);
+	msleep(10);
+	return 0;
+}
+
+/* hdmi pll dsiable */
+
+static void ip_hdmi_pll_disable(struct hdmi_ip_data *ip_data)
+{
+	struct clk *tvout_clk = NULL;
+	HDMI_DEBUG("PLL Disable!\n");
+	tvout_clk = clk_get(NULL, CLKNAME_TVOUTPLL);
+    clk_disable(tvout_clk);	
+	clk_unprepare(tvout_clk);
+
+}
+
+static void ip_hdmi_write_reg(struct hdmi_ip_data *ip_data,	const u16 idx, u32 val)
+{
+	hdmi_write_reg(ip_data, idx, val);
+}
+
+static int ip_hdmi_read_reg(struct hdmi_ip_data *ip_data, const u16 idx)
+{
+	return hdmi_read_reg(ip_data, idx);
+}
+
+static bool ip_hdmi_cable_check_state(struct hdmi_ip_data *ip_data)
+{
+	bool hpd;
+	
+	/*HDMI_DEBUG("hdmi_read_reg(ip_data, HDMI_CR)=%x\n",hdmi_read_reg(ip_data, HDMI_CR));*/
+	
+	/*hpd = (hdmi_read_reg(ip_data, HDMI_CR)&(1<<29)?1:0);*/
+	
+	if((hdmi_read_reg(ip_data, HDMI_CR)&(1<<29))&&(hdmi_read_reg(ip_data, CEC_DDC_HPD)&(3<<12))){
+		if((hdmi_read_reg(ip_data, CEC_DDC_HPD)&(3<<8))||
+			(hdmi_read_reg(ip_data, CEC_DDC_HPD)&(3<<10))||
+			(hdmi_read_reg(ip_data, CEC_DDC_HPD)&(3<<12))||
+			(hdmi_read_reg(ip_data, CEC_DDC_HPD)&(3<<14))
+			){
+			hpd = 1;
+		}else{
+			hpd = 0;
+		}	
+	}else{
+		hpd = 0;
+	}
+
+	return hpd;
+}
+
+static bool ip_hdmi_detect(struct hdmi_ip_data *ip_data)
+{
+	u32 val;
+		
+	val = hdmi_read_reg(ip_data, HDMI_CR);
+
+	return (REG_GET_VAL(val,30,30) == 1);
+}
+
+static u32 ip_hdmi_get_irq_state(struct hdmi_ip_data *ip_data)
+{
+	u32 val;
+	u32 irq_state = 0;
+
+	val = hdmi_read_reg(ip_data, HDMI_CR);
+
+	if(REG_GET_VAL(val,30,30) == 1)
+	{
+		irq_state |= HDMI_HPD_IRQ;
+	}
+	
+	val = hdmi_read_reg(ip_data, HDMI_CECTXCR);
+
+	if(REG_GET_VAL(val,6,6) == 1)
+	{
+		irq_state |= HDMI_CEC_IRQ;
+	}
+
+	val = hdmi_read_reg(ip_data, HDMI_CECRXCR);
+
+	if(REG_GET_VAL(val,6,6) == 1)
+	{
+		irq_state |= HDMI_CEC_IRQ;
+	}
+	
+	return irq_state;
+}
+
+static void ip_hdmi_hpd_enable(struct hdmi_ip_data *ip_data,bool enable)
+{
+
+	u32 val;
+	
+	val = hdmi_read_reg(ip_data, HDMI_CR);
+	
+	if(enable){	
+		//set hotplug debounce ,default used 0x0f	
+		val = REG_SET_VAL(val, 0x0f, 27, 24);
+		
+		//enable hotplug interrupt 	
+		val = REG_SET_VAL(val ,0x01, 31, 31);
+		
+		//enable hotplug function 	
+		val = REG_SET_VAL(val ,0x01, 28, 28);	
+		
+		//no clear hotplug panding bit 	
+		val = REG_SET_VAL(val ,0x00, 30, 30);
+	}else{
+		//enable hotplug interrupt 	
+		val = REG_SET_VAL(val ,0x00, 31, 31);
+		
+		//enable hotplug function 	
+		val = REG_SET_VAL(val ,0x00, 28, 28);
+		
+		//clear hotplug panding bit 	
+		val = REG_SET_VAL(val ,0x01, 30, 30);
+	}
+	
+	hdmi_write_reg(ip_data, HDMI_CR, val);
+
+}
+
+static void ip_hdmi_clear_plugstatus(struct hdmi_ip_data *ip_data)
+{
+
+	u32 val;
+	
+	val = hdmi_read_reg(ip_data, HDMI_CR);
+
+	//clear hotplug panding bit 	
+	val = REG_SET_VAL(val ,0x01, 30, 30);
+
+	hdmi_write_reg(ip_data, HDMI_CR, val);
+	
+}
+
+static void ip_hdmi_phy_enable(struct hdmi_ip_data *ip_data)
+{
+
+/*	u32 val;
+	// tdms enable
+	val = hdmi_read_reg(ip_data, TMDS_EODR0);
+	val = REG_SET_VAL(val ,1, 31, 31);
+	hdmi_write_reg(ip_data, TMDS_EODR0, val);	
+*/	
+	if(hdmi.ip_data.txrx_cfg.drv_from_dts)
+	{
+		switch (ip_data->cfg.cm.code)
+		{
+			case VID640x480P_60_4VS3:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid480p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid480p_tx2);	
+				break;	
+			case VID720x576P_50_4VS3:
+			case VID720x480P_60_4VS3:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid576p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid576p_tx2);	
+				break;		
+			case VID1280x720P_60_16VS9:
+			case VID1280x720P_50_16VS9:
+			case VID1280x720P_60_DVI:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid720p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid720p_tx2);	
+				break;
+			case VID1920x1080P_60_16VS9:
+			case VID1920x1080P_50_16VS9:
+				hdmi_write_reg(ip_data, HDMI_TX_1, hdmi.ip_data.txrx_cfg.vid1080p_tx1);	
+				hdmi_write_reg(ip_data, HDMI_TX_2, hdmi.ip_data.txrx_cfg.vid1080p_tx2);	
+				break;
+			default:
+				DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+		}		
+	}else{
+		if(hdmi.hdmihw_diff->ic_type == IC_TYPE_ATM7059A){	
+			switch (ip_data->cfg.cm.code)
+			{
+				case VID640x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c2983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;	
+				case VID720x576P_50_4VS3:
+				case VID720x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c2983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;		
+				case VID1280x720P_60_16VS9:
+				case VID1280x720P_50_16VS9:
+				case VID1280x720P_60_DVI:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81942983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;
+				case VID1920x1080P_60_16VS9:
+				case VID1920x1080P_50_16VS9:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81902983);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;
+				default:
+					DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+			}
+		}else{
+			switch (ip_data->cfg.cm.code)
+			{
+				case VID640x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c0986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;	
+				case VID720x576P_50_4VS3:
+				case VID720x480P_60_4VS3:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x819c0986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;		
+				case VID1280x720P_60_16VS9:
+				case VID1280x720P_50_16VS9:
+				case VID1280x720P_60_DVI:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81982986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);
+					break;
+				case VID1920x1080P_60_16VS9:
+				case VID1920x1080P_50_16VS9:
+					hdmi_write_reg(ip_data, HDMI_TX_1, 0x81940986);	
+					hdmi_write_reg(ip_data, HDMI_TX_2, 0x18f80f87);	
+					break;
+				default:
+					DEBUG_ERR("!!!no surpport this vid %d\n", ip_data->cfg.cm.code);
+			}	
+		}
+	}
+}
+
+static void ip_hdmi_phy_disable(struct hdmi_ip_data *ip_data)
+{
+	u32 val;
+
+	// LDO_TMDS power off
+    val = hdmi_read_reg(ip_data, HDMI_TX_2);
+	val = REG_SET_VAL(val ,0, 27, 27);
+	val = REG_SET_VAL(val ,0, 17, 17);
+	val = REG_SET_VAL(val ,0x0, 11, 8);
+	hdmi_write_reg(ip_data, HDMI_TX_2, val);	
+    // tx pll power off
+    val = hdmi_read_reg(ip_data, HDMI_TX_1);
+	val = REG_SET_VAL(val ,0, 23, 23);
+	hdmi_write_reg(ip_data, HDMI_TX_1, val);
+	
+}
+
+static void ip_hdmi_video_start(struct hdmi_ip_data *ip_data)
+{
+	u32 val;
+	
+	val = hdmi_read_reg(ip_data, TMDS_EODR0);
+	val = REG_SET_VAL(val ,1, 31, 31);
+	hdmi_write_reg(ip_data, TMDS_EODR0, val);	
+	
+	val = hdmi_read_reg(ip_data, HDMI_CR);
+	val = REG_SET_VAL(val ,1, 0, 0);
+	hdmi_write_reg(ip_data, HDMI_CR, val);
+
+ /*        val = hdmi_read_reg(ip_data, HDMI_ICR);
+         val = REG_SET_VAL(val ,1, 25, 25);
+         hdmi_write_reg(ip_data, HDMI_ICR, val);
+*/
+	
+}
+
+static void ip_hdmi_video_stop(struct hdmi_ip_data *ip_data)
+{
+         u32 val;
+
+         val = hdmi_read_reg(ip_data, HDMI_ICR);
+         val = REG_SET_VAL(val ,0, 25, 25);
+         hdmi_write_reg(ip_data, HDMI_ICR, val);
+
+         val = hdmi_read_reg(ip_data, HDMI_CR);
+         val = REG_SET_VAL(val ,0, 0, 0);
+         hdmi_write_reg(ip_data, HDMI_CR, val);
+         
+}
+
+
+static void ip_hdmi_dump(struct hdmi_ip_data *ip_data)
+{
+#define DUMPREG(name,r) DEBUG_ON("%s %08x\n",name,hdmi_read_reg(ip_data, r))
+	
+    DUMPREG("HDMI_VICTL  value is ", HDMI_VICTL);
+    DUMPREG("HDMI_VIVSYNC  value is ", HDMI_VIVSYNC);
+    DUMPREG("HDMI_VIVHSYNC  value is ", HDMI_VIVHSYNC);
+    DUMPREG("HDMI_VIALSEOF  value is ", HDMI_VIALSEOF);
+    DUMPREG("HDMI_VIALSEEF  value is ", HDMI_VIALSEEF);
+    DUMPREG("HDMI_VIADLSE  value is ", HDMI_VIADLSE);
+    DUMPREG("HDMI_VR  value is ", HDMI_VR);
+    DUMPREG("HDMI_CR  value is ", HDMI_CR);
+    DUMPREG("HDMI_SCHCR  value is ", HDMI_SCHCR);
+    DUMPREG("HDMI_ICR  value is ", HDMI_ICR);
+    DUMPREG("HDMI_SCR  value is ", HDMI_SCR);
+    DUMPREG("HDMI_LPCR  value is ", HDMI_LPCR);
+    DUMPREG("HDCP_CR  value is ", HDCP_CR);
+    DUMPREG("HDCP_SR  value is ", HDCP_SR);
+    DUMPREG("HDCP_ANLR  value is ", HDCP_ANLR);
+    DUMPREG("HDCP_ANMR  value is ", HDCP_ANMR);
+    DUMPREG("HDCP_ANILR  value is ", HDCP_ANILR);
+    DUMPREG("HDCP_ANIMR  value is ", HDCP_ANIMR);
+    DUMPREG("HDCP_DPKLR  value is ", HDCP_DPKLR);
+    DUMPREG("HDCP_DPKMR  value is ", HDCP_DPKMR);
+    DUMPREG("HDCP_LIR  value is ", HDCP_LIR);
+    DUMPREG("HDCP_SHACR  value is ", HDCP_SHACR);
+    DUMPREG("HDCP_SHADR  value is ", HDCP_SHADR);
+    DUMPREG("HDCP_ICR  value is ", HDCP_ICR);
+    DUMPREG("HDCP_KMMR  value is ", HDCP_KMMR);
+    DUMPREG("HDCP_KMLR  value is ", HDCP_KMLR);
+    DUMPREG("HDCP_MILR  value is ", HDCP_MILR);
+    DUMPREG("HDCP_MIMR  value is ", HDCP_MIMR);
+    DUMPREG("HDCP_KOWR  value is ", HDCP_KOWR);
+    DUMPREG("HDCP_OWR  value is ", HDCP_OWR);
+
+    DUMPREG("TMDS_STR0  value is ", TMDS_STR0);
+    DUMPREG("TMDS_STR1  value is ", TMDS_STR1);
+    DUMPREG("TMDS_EODR0  value is ", TMDS_EODR0);
+    DUMPREG("TMDS_EODR1  value is ", TMDS_EODR1);
+    DUMPREG("HDMI_ASPCR  value is ", HDMI_ASPCR);
+    DUMPREG("HDMI_ACACR  value is ", HDMI_ACACR);
+    DUMPREG("HDMI_ACRPCR  value is ", HDMI_ACRPCR);
+    DUMPREG("HDMI_ACRPCTSR  value is ", HDMI_ACRPCTSR);
+    DUMPREG("HDMI_ACRPPR value is ", HDMI_ACRPPR);
+    DUMPREG("HDMI_GCPCR  value is ", HDMI_GCPCR);
+    DUMPREG("HDMI_RPCR  value is ", HDMI_RPCR);
+    DUMPREG("HDMI_RPRBDR  value is ", HDMI_RPRBDR);
+    DUMPREG("HDMI_OPCR  value is ", HDMI_OPCR);
+    DUMPREG("HDMI_DIPCCR  value is ", HDMI_DIPCCR);
+    DUMPREG("HDMI_ORP6PH  value is ", HDMI_ORP6PH);
+    DUMPREG("HDMI_ORSP6W0  value is ", HDMI_ORSP6W0);
+    DUMPREG("HDMI_ORSP6W1  value is ", HDMI_ORSP6W1);
+    DUMPREG("HDMI_ORSP6W2  value is ", HDMI_ORSP6W2);
+    DUMPREG("HDMI_ORSP6W3  value is ", HDMI_ORSP6W3);
+    DUMPREG("HDMI_ORSP6W4  value is ", HDMI_ORSP6W4);
+    DUMPREG("HDMI_ORSP6W5  value is ", HDMI_ORSP6W5);
+    DUMPREG("HDMI_ORSP6W6v  value is ", HDMI_ORSP6W6);
+    DUMPREG("HDMI_ORSP6W7  value is ", HDMI_ORSP6W7);
+    DUMPREG("HDMI_CECCR  value is ", HDMI_CECCR);
+    DUMPREG("HDMI_CECRTCR  value is ", HDMI_CECRTCR);
+    DUMPREG("HDMI_CRCCR  value is ", HDMI_CRCCR);
+    DUMPREG("HDMI_CRCDOR  value is ", HDMI_CRCDOR);
+    DUMPREG("HDMI_TX_1  value is ", HDMI_TX_1);
+    DUMPREG("HDMI_TX_2  value is ", HDMI_TX_2);
+    DUMPREG("CEC_DDC_HPD  value is ", CEC_DDC_HPD);
+
+}
+
+static void ip_hdmi_basic_configure(struct hdmi_ip_data *ip_data)
+{
+
+	/* HDMI */
+	struct owl_video_timings video_timing;
+	struct hdmi_video_format video_format;
+
+	/* HDMI core */
+	struct hdmi_config *cfg = &ip_data->cfg;
+	/**/
+	ip_hdmi_pllpu(ip_data);
+	/* video config */
+	hdmi_video_init_format(&video_format, &video_timing, cfg);	
+
+	/*HDMI_SCHCR vinster hinster bit 2:1
+	HDMI_VICTL POR*/
+	hdmi_video_config_timing(ip_data, &video_timing);
+	/*HDMI_VICTL*/
+	hdmi_video_config_format(ip_data, &video_timing);
+	/*HDMI_VIVSYNC
+	HDMI_VIVHSYNC
+	HDMI_VIALSEOF
+	HDMI_VIALSEEF
+	HDMI_VIADLSE*/
+	hdmi_video_config_interface(ip_data,&video_timing);	
+	/*DIPCCR*/
+	hdmi_video_interval_packet(ip_data,&video_timing);	
+	/*HDMI_ICR*/	
+	hdmi_core_config_input_src(ip_data);
+	/*HDMI_SCHCR*/	
+	hdmi_core_config_pixel_fomat(ip_data);
+	/*HDMI_SCHCR*/	
+	hdmi_core_config_deepcolor_mode(ip_data);
+	/*HDMI_SCHCR*/	
+	hdmi_core_config_mode(ip_data);
+	/*HDMI_SCHCR*/	
+	hdmi_core_config_invert(ip_data);
+	/*HDMI_GCPCR*/	
+	hdmi_core_config_colordepth_value(ip_data);
+	/*HDMI_SCHCR*/	
+	hdmi_core_config_3d_mode(ip_data);	
+	
+	asoc_hdmi_gen_infoframe(ip_data);
+	/*ip_hdmi_dump(ip_data);*/
+}
+
+static const struct owl_hdmi_ip_ops owl_hdmi_functions = {
+	.hdmi_devclken		=	ip_hdmi_devclken,
+	.hdmi_clk24Men		=	ip_hdmi_clk24Men,
+	.hdmi_reset 		=   ip_hdmi_reset,
+	.pll_enable			=	ip_hdmi_pll_enable,
+	.pll_disable		=	ip_hdmi_pll_disable,
+	.read_reg 			=   ip_hdmi_read_reg,
+	.write_reg 			=   ip_hdmi_write_reg,
+	.cable_check		=	ip_hdmi_cable_check_state,
+	.detect			    =	ip_hdmi_detect,
+	.hpd_enable		    =	ip_hdmi_hpd_enable,
+	.hpd_clear_plug     =   ip_hdmi_clear_plugstatus,
+	.phy_enable		    =	ip_hdmi_phy_enable,
+	.phy_disable		=	ip_hdmi_phy_disable,	
+	.video_enable		=	ip_hdmi_video_start,
+	.video_disable		=	ip_hdmi_video_stop,	
+	.dump_hdmi		    =	ip_hdmi_dump,
+	.video_configure	=	ip_hdmi_basic_configure,
+	.get_irq_state      =   ip_hdmi_get_irq_state,
+
+};
+
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data)
+{
+	ip_data->ops = &owl_hdmi_functions;
+
+	WARN_ON(ip_data->ops == NULL);
+}
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.h b/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.h
new file mode 100755
index 0000000..42c74cf
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_ip.h
@@ -0,0 +1,189 @@
+/*
+ * hdmi_ip.h
+ *
+ * HDMI header definition for OWL IP.
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _HDMI_ACTS_OWL_H_
+#define _HDMI_ACTS_OWL_H_
+
+	#define     HDMI_VICTL                                                        (0x0000)
+	#define     HDMI_VIVSYNC                                                      (0x0004)
+	#define     HDMI_VIVHSYNC                                                     (0x0008)
+	#define     HDMI_VIALSEOF                                                     (0x000C)
+	#define     HDMI_VIALSEEF                                                     (0x0010)
+	#define     HDMI_VIADLSE                                                      (0x0014)
+	#define     HDMI_AIFRAMEC                                                     (0x0020)
+	#define     HDMI_AICHSTABYTE0TO3                                              (0x0024)
+	#define     HDMI_AICHSTABYTE4TO7                                              (0x0028)
+	#define     HDMI_AICHSTABYTE8TO11                                             (0x002C)
+	#define     HDMI_AICHSTABYTE12TO15                                            (0x0030)
+	#define     HDMI_AICHSTABYTE16TO19                                            (0x0034)
+	#define     HDMI_AICHSTABYTE20TO23                                            (0x0038)
+	#define     HDMI_AICHSTASCN                                                   (0x003C)
+	#define     HDMI_VR                                                           (0x0050)
+	#define     HDMI_CR                                                           (0x0054)
+	#define     HDMI_SCHCR                                                        (0x0058)
+	#define     HDMI_ICR                                                          (0x005C)
+	#define     HDMI_SCR                                                          (0x0060)
+	#define     HDMI_LPCR                                                         (0x0064)
+	#define     HDCP_CR                                                           (0x0068)
+	#define     HDCP_SR                                                           (0x006C)
+	#define     HDCP_ANLR                                                         (0x0070)
+	#define     HDCP_ANMR                                                         (0x0074)
+	#define     HDCP_ANILR                                                        (0x0078)
+	#define     HDCP_ANIMR                                                        (0x007C)
+	#define     HDCP_DPKLR                                                        (0x0080)
+	#define     HDCP_DPKMR                                                        (0x0084)
+	#define     HDCP_LIR                                                          (0x0088)
+	#define     HDCP_SHACR                                                        (0x008C)
+	#define     HDCP_SHADR                                                        (0x0090)
+	#define     HDCP_ICR                                                          (0x0094)
+	#define     HDCP_KMMR                                                         (0x0098)
+	#define     HDCP_KMLR                                                         (0x009C)
+	#define     HDCP_MILR                                                         (0x00A0)
+	#define     HDCP_MIMR                                                         (0x00A4)
+	#define     HDCP_KOWR                                                         (0x00A8)
+	#define     HDCP_OWR                                                          (0x00AC)
+	#define     TMDS_STR0                                                         (0x00B8)
+	#define     TMDS_STR1                                                         (0x00BC)
+	#define     TMDS_EODR0                                                        (0x00C0)
+	#define     TMDS_EODR1                                                        (0x00C4)
+	#define     HDMI_ASPCR                                                        (0x00D0)
+	#define     HDMI_ACACR                                                        (0x00D4)
+	#define     HDMI_ACRPCR                                                       (0x00D8)
+	#define     HDMI_ACRPCTSR                                                     (0x00DC)
+	#define     HDMI_ACRPPR                                                       (0x00E0)
+	#define     HDMI_GCPCR                                                        (0x00E4)
+	#define     HDMI_RPCR                                                         (0x00E8)
+	#define     HDMI_RPRBDR                                                       (0x00EC)
+	#define     HDMI_OPCR                                                         (0x00F0)
+	#define     HDMI_DIPCCR                                                       (0x00F4)
+	#define     HDMI_ORP6PH                                                       (0x00F8)
+	#define     HDMI_ORSP6W0                                                      (0x00FC)
+	#define     HDMI_ORSP6W1                                                      (0x0100)
+	#define     HDMI_ORSP6W2                                                      (0x0104)
+	#define     HDMI_ORSP6W3                                                      (0x0108)
+	#define     HDMI_ORSP6W4                                                      (0x010C)
+	#define     HDMI_ORSP6W5                                                      (0x0110)
+	#define     HDMI_ORSP6W6                                                      (0x0114)
+	#define     HDMI_ORSP6W7                                                      (0x0118)
+	#define     HDMI_CECCR                                                        (0x011C)
+	#define     HDMI_CECRTCR                                                      (0x0120)
+	#define     HDMI_CECRXCR                                                      (0x0124)
+	#define     HDMI_CECTXCR                                                      (0x0128)
+	#define     HDMI_CECTXDR                                                      (0x012C)
+	#define     HDMI_CECRXDR                                                      (0x0130)
+	#define     HDMI_CECRXTCR                                                     (0x0134)
+	#define     HDMI_CECTXTCR0                                                    (0x0138)
+	#define     HDMI_CECTXTCR1                                                    (0x013C)
+	#define     HDMI_CRCCR                                                        (0x0140)
+	#define     HDMI_CRCDOR                                                       (0x0144)
+	#define     HDMI_TX_1                                                         (0x0154)
+	#define     HDMI_TX_2                                                         (0x0158)
+	#define     CEC_DDC_HPD                                                       (0x015C)
+	#define     MHL_PHYCTL1                                                       (0x0160)
+	#define     MHL_PHYCTL2                                                       (0x0164)
+	#define     MHL_PHYCTL3                                                       (0x0168)
+	#define     MHL_CR                                                            (0x0180)
+	#define     MHL_INTMSK                                                        (0x0184)
+	#define     MHL_INTPD                                                         (0x0188)
+	#define     MHL_INTSR                                                         (0x018c)
+	#define     MSC_REQMSGR                                                       (0x0190)
+	#define     MSC_REQRMSGR                                                      (0x0194)
+	#define     MSC_RSPRMR                                                        (0x0198)
+	#define     MSC_RSPRFIFO                                                      (0x019c)
+	#define     MSC_RSPRRMR                                                       (0x01a0)
+	#define     MHL_DDCCSR                                                        (0x01a4)
+	#define     MHL_DDCPR                                                         (0x01a8)
+	#define     CBUS_DCR0TO3                                                      (0x01b0)
+	#define     CBUS_DCR4TO7                                                      (0x01b4)
+	#define     CBUS_DCR8TOB                                                      (0x01b8)
+	#define     CBUS_DCRCTOF                                                      (0x01bc)
+	#define     CBUS_DEVINTR                                                      (0x01c0)
+	#define     CBUS_DEVSR                                                        (0x01c4)
+	#define     CBUS_SPR0TO3                                                      (0x01c8)
+	#define     CBUS_SPR4TO7                                                      (0x01cc)
+	#define     CBUS_SPR8TOB                                                      (0x01d0)
+	#define     CBUS_SPRCTOF                                                      (0x01d4)
+	#define     CBUS_VID                                                          (0x01d8)
+	#define     CBUS_LLTCR                                                        (0x01e0)
+	#define     CBUS_TLTCR                                                        (0x01e4)
+	#define     MHL_DEBUG                                                         (0x1f0)
+
+	/********************************************************/
+	/* HDMI_LPCR */
+	#define HDMI_LPCR_CURLINECNTR                       (0xFFF << 16)
+	#define HDMI_LPCR_CURPIXELCNTR                      (0xFFF << 0)
+
+	/********************************************************/
+	/* HDCP_CR */
+	#define HDCP_CR_EN1DOT1_FEATURE                     (1 << 31)
+	#define HDCP_CR_DOWNSTRISREPEATER                   (1 << 30)
+	#define HDCP_CR_ANINFREQ                            (1 << 25)
+	#define HDCP_CR_SEEDLOAD                            (1 << 24)
+	#define HDCP_CR_ENRIUPDINT                          (1 << 9)
+	#define HDCP_CR_ENPJUPDINT                          (1 << 8)
+	#define HDCP_CR_ANINFLUENCEMODE                     (1 << 7)
+	#define HDCP_CR_HDCP_ENCRYPTENABLE                  (1 << 6)
+	#define HDCP_CR_RESETKMACC                          (1 << 4)
+	#define HDCP_CR_FORCETOUNAUTHENTICATED              (1 << 3)
+	#define HDCP_CR_DEVICEAUTHENTICATED                 (1 << 2)
+	#define HDCP_CR_AUTHCOMPUTE                         (1 << 1)
+	#define HDCP_CR_AUTHREQUEST                         (1 << 0)
+
+	/********************************************************/
+	/* HDCP_SR */
+	#define HDCP_SR_HDCPCIPHERSTATE(x)                  (((x) & 0xFF) << 24)
+	#define HDCP_SR_RIUPDATED                           (1 << 5)
+	#define HDCP_SR_PJUPDATED                           (1 << 4)
+	#define HDCP_SR_CURDPKACCDONE                       (1 << 3)
+	#define HDCP_SR_HDCP_ENCRYPT_STATUS                 (1 << 2)
+	#define HDCP_SR_ANTHENTICATEDOK                     (1 << 1)
+	#define HDCP_SR_ANREADY                             (1 << 0)
+
+
+	/********************************************************/
+	/* HDCP_LIR */
+	#define HDCP_LIR_RI(x)                              (((x) & 0xFFFF) << 16)
+	#define HDCP_LIR_PJ(x)                              (((x) & 0xFF) << 8)
+
+	/********************************************************/
+	/* HDCP_SHACR */
+	#define HDCP_SHACR_VMATCH                           (1 << 4)
+	#define HDCP_SHACR_SHAREADY                         (1 << 3)
+	#define HDCP_SHACR_SHASTART                         (1 << 2)
+	#define HDCP_SHACR_SHAFIRST                         (1 << 1)
+	#define HDCP_SHACR_RSTSHAPTR                        (1 << 0)
+
+	/********************************************************/
+	/* HDCP_ICR */
+	#define HDCP_ICR_RIRATE(x)                          (((x) & 0xFF) << 8)
+	#define HDCP_ICR_PJRATE(x)                          (((x) & 0xFF) << 0)
+
+	/* HDCP_KOWR */
+	#define HDCP_KOWR_HDCPREKEYKEEPOUTWIN(x)            (((x) & 0xFF) << 24)
+	#define HDCP_KOWR_HDCPVERKEEPOUTWINEND(x)           (((x) & 0xFFF) << 12)
+	#define HDCP_KOWR_HDCPVERTKEEPOUTWINSTART(x)        (((x) & 0xFFF) << 0)
+
+	/********************************************************/
+	/* HDCP_OWR */
+	#define HDCP_OWR_HDCPOPPWINEND(x)                   (((x) & 0xFFF) << 12)
+	#define HDCP_OWR_HDCPOPPWINSTART(x)                 (((x) & 0xFFF) << 0)
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_packet.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_packet.c
new file mode 100755
index 0000000..61047db
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_packet.c
@@ -0,0 +1,453 @@
+/*
+ * asoc_hdmi_packet.c
+ *
+ * Copyright (C) 2011 Actions Semiconductor, Inc
+ * Author:  Geng A-nan <genganan at actions-semi.com >
+ * Data: Monday August 22, 2008
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/seq_file.h>
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+/* Internal SRAM allocation for Periodic Data Island Packet */
+
+#define HDMI_RAMPKT_AVI_SLOT    0
+#define HDMI_RAMPKT_AUDIO_SLOT  1
+#define HDMI_RAMPKT_SPD_SLOT    2
+#define HDMI_RAMPKT_GBD_SLOT    3
+#define HDMI_RAMPKT_VS_SLOT     4
+#define HDMI_RAMPKT_MPEG_SLOT   5
+
+#define HDMI_RAMPKT_PERIOD      1
+
+
+#define owl_hdmi_write(a, b)  hdmi.ip_data.ops->write_reg(&hdmi.ip_data, a, b)
+#define owl_hdmi_read(a)      hdmi.ip_data.ops->read_reg(&hdmi.ip_data, a)
+
+/* Packet Command */
+
+int hdmi_EnableWriteRamPacket(void)
+{
+    
+    int i;  
+    unsigned int tmp_reg_value;
+ 
+    tmp_reg_value = owl_hdmi_read(HDMI_OPCR);
+    tmp_reg_value |= (1<<31);
+    owl_hdmi_write(HDMI_OPCR,tmp_reg_value); 
+    
+	i=100;
+    while(i--)
+    {
+        tmp_reg_value = owl_hdmi_read(HDMI_OPCR);
+        tmp_reg_value = tmp_reg_value>>31;
+        if (tmp_reg_value==0)
+           break;
+		udelay(1); 
+    }
+    
+    return 0;
+}
+
+int hdmi_SetRamPacketPeriod(unsigned int no, int period)
+{
+    unsigned int tmp_reg_value;
+    
+    if(no>5 || no<0)
+        return -1;
+    if(period>0xf || period<0)
+        return -1;
+
+    tmp_reg_value = owl_hdmi_read(HDMI_RPCR);
+    tmp_reg_value &= (~(1<<no));
+    owl_hdmi_write(HDMI_RPCR,  tmp_reg_value);
+    
+    tmp_reg_value = owl_hdmi_read(HDMI_RPCR);
+    tmp_reg_value &= (~(0xf<<(no*4+8)));
+    owl_hdmi_write(HDMI_RPCR,  tmp_reg_value);
+
+
+    if(period) {    // enable and set period
+        tmp_reg_value = owl_hdmi_read(HDMI_RPCR);
+        tmp_reg_value |= (period<<(no*4+8));
+        owl_hdmi_write(HDMI_RPCR,  tmp_reg_value);
+
+        tmp_reg_value = owl_hdmi_read(HDMI_RPCR);
+        tmp_reg_value |= (1<<no);
+        owl_hdmi_write(HDMI_RPCR,  tmp_reg_value);
+        
+    }
+
+    return 0;
+}
+
+/*
+    convert readable Data Island packet to RAM packet format,
+    and write to RAM packet area
+*/
+
+int hdmi_SetRamPacket(unsigned int no, unsigned char *pkt)
+{
+    unsigned char tpkt[36];
+    unsigned int reg[9];
+    int i,j;
+    unsigned int addr = 126 + no * 14;
+
+
+    if(no > 5 || no < 0)
+        return -1;
+
+    //Packet Header
+    tpkt[0] = pkt[0];
+    tpkt[1] = pkt[1];
+    tpkt[2] = pkt[2];
+    tpkt[3] = 0;
+    //Packet Word0
+    tpkt[4] = pkt[3];
+    tpkt[5] = pkt[4];
+    tpkt[6] = pkt[5];
+    tpkt[7] = pkt[6];
+    //Packet Word1
+    tpkt[8] = pkt[7];
+    tpkt[9] = pkt[8];
+    tpkt[10] = pkt[9];
+    tpkt[11] = 0;
+    //Packet Word2
+    tpkt[12] = pkt[10];
+    tpkt[13] = pkt[11];
+    tpkt[14] = pkt[12];
+    tpkt[15] = pkt[13];
+    //Packet Word3
+    tpkt[16] = pkt[14];
+    tpkt[17] = pkt[15];
+    tpkt[18] = pkt[16];
+    tpkt[19] = 0;
+    //Packet Word4
+    tpkt[20] = pkt[17];
+    tpkt[21] = pkt[18];
+    tpkt[22] = pkt[19];
+    tpkt[23] = pkt[20];
+    //Packet Word5
+    tpkt[24] = pkt[21];
+    tpkt[25] = pkt[22];
+    tpkt[26] = pkt[23];
+    tpkt[27] = 0;
+    //Packet Word6
+    tpkt[28] = pkt[24];
+    tpkt[29] = pkt[25];
+    tpkt[30] = pkt[26];
+    tpkt[31] = pkt[27];
+    //Packet Word7
+    tpkt[32] = pkt[28];
+    tpkt[33] = pkt[29];
+    tpkt[34] = pkt[30];
+    tpkt[35] = 0;
+
+    for(i=0;i<9;i++)        //for atm9009a change*******************
+    {
+        reg[i] = 0;
+        for(j=0;j<4;j++)
+        reg[i] |= (tpkt[i*4+j])<<(j*8);
+    }
+    
+    owl_hdmi_write(HDMI_OPCR, (1<<8) | (addr&0xff));
+    owl_hdmi_write(HDMI_ORP6PH, reg[0]);
+    owl_hdmi_write(HDMI_ORSP6W0, reg[1]);
+    owl_hdmi_write(HDMI_ORSP6W1, reg[2]);
+    owl_hdmi_write(HDMI_ORSP6W2, reg[3]);
+    owl_hdmi_write(HDMI_ORSP6W3, reg[4]);
+    owl_hdmi_write(HDMI_ORSP6W4, reg[5]);
+    owl_hdmi_write(HDMI_ORSP6W5, reg[6]);
+    owl_hdmi_write(HDMI_ORSP6W6, reg[7]);
+    owl_hdmi_write(HDMI_ORSP6W7, reg[8]);
+
+    hdmi_EnableWriteRamPacket();
+
+    return 0;
+}
+
+int hdmi_gen_spd_infoframe(void)
+{
+    static u8 pkt[32];
+    unsigned int checksum=0;
+    unsigned int i;
+    static char spdname[8]="Vienna";
+    static char spddesc[16]="DTV SetTop Box";
+
+    // clear buffer 
+    for(i=0;i<32;i++)
+                pkt[i]=0;
+        
+    // header 
+    pkt[0] = 0x80 | 0x03;   //HB0: Packet Type = 0x83
+    pkt[1] = 1;             //HB1: version = 1
+    pkt[2] = 0x1f & 25;     //HB2: len = 25 
+    pkt[3] = 0x00;          //PB0: checksum = 0 
+
+    // data
+    // Vendor Name, 8 bytes 
+    memcpy(&pkt[4], spdname, 8);
+    // Product Description, 16 bytes
+    memcpy(&pkt[12], spddesc, 16);
+    // Source Device Information 
+    pkt[28] = 0x1;          //Digital STB
+
+    // count checksum
+    for(i=0; i<31; i++)
+        checksum += pkt[i];
+    pkt[3] = (~checksum + 1)  & 0xff;
+
+    // set to RAM Packet
+    hdmi_SetRamPacket(HDMI_RAMPKT_SPD_SLOT, pkt);
+    hdmi_SetRamPacketPeriod(HDMI_RAMPKT_SPD_SLOT, HDMI_RAMPKT_PERIOD);
+    
+    return 0;
+}
+
+/*
+function:hdmi_gen_avi_infoframe
+input:  colorformat :   0--RGB444;1--YCbCr422;2--YCbCr444
+        AR          :   1--4:3;   2--16:9
+return: 0
+*/
+int hdmi_gen_avi_infoframe(struct hdmi_ip_data *ip_data)
+{
+    static u8 pkt[32];
+    u32 checksum=0, i=0;
+    u8 AR=2;
+    /* clear buffer */
+    for(i=0;i<32;i++)
+        pkt[i]=0;
+    
+    //1. header
+    pkt[0] = 0x80 | 0x02;   //header = 0x82
+    pkt[1] = 2;         //version = 2
+    pkt[2] = 0x1f & 13; // len = 13
+    pkt[3] = 0x00;      // checksum = 0 
+    
+    //2. data 
+    //PB1--Y1:Y0=colorformat;R3:R1 is invalid ;no bar info and scan info
+    pkt[4] = (ip_data->settings.pixel_encoding<<5) | (0<<4) | (0<<2) | (0); 
+
+    //0--Normal YCC601 or YCC709; 1--xvYCC601; 2--xvYCC709
+    if(ip_data->settings.color_xvycc == 0)
+    {
+        //PB2--Colorimetry:SMPTE 170M|ITU601; Picture aspect Ratio; same as picture aspect ratio  
+        pkt[5] = (0x1<<6) | (AR<<4) | (0x8); 
+        //PB3--No known non-uniform scaling
+        pkt[6] = 0x0;
+    }
+    else if(ip_data->settings.color_xvycc == 1)
+    {
+        //PB2--Colorimetry:SMPTE 170M|ITU601; Picture aspect Ratio; same as picture aspect ratio  
+        pkt[5] = (0x3<<6) | (AR<<4) | (0x8); 
+        //PB3--xvYCC601;No known non-uniform scaling
+        pkt[6] = 0x0;   
+        
+    }
+    else
+    {
+        //PB2--Colorimetry:SMPTE 170M|ITU601; Picture aspect Ratio; same as picture aspect ratio  
+        pkt[5] = (0x3<<6) | (AR<<4) | (0x8); 
+        //PB3--xvYCC709;No known non-uniform scaling
+        pkt[6] = 0x1<<4;    
+    }
+
+    //PB4--Video Id
+    pkt[7] = ip_data->cfg.cm.code;
+    //PB5--Pixel repeat time:
+    pkt[8] = 0;
+    //PB6--PB13: Bar Info, no bar info
+    pkt[9] = 0;
+    pkt[10] = 0;
+    pkt[11] = 0;
+    pkt[12] = 0;
+    pkt[13] = 0;
+    pkt[14] = 0;
+    pkt[15] = 0;
+    pkt[16] = 0;
+    
+    // count checksum
+    for(i=0; i<31; i++)
+        checksum += pkt[i];
+    pkt[3] = (~checksum + 1) & 0xff;
+
+    /* set to RAM Packet */
+    hdmi_SetRamPacket(HDMI_RAMPKT_AVI_SLOT, pkt);
+    hdmi_SetRamPacketPeriod(HDMI_RAMPKT_AVI_SLOT, HDMI_RAMPKT_PERIOD);
+
+    return 0;
+}
+
+/*
+function:hdmi_gen_gbd_infoframe
+input:  Color_xvYCC :   0--Normal YCC601 or YCC709; 1--xvYCC601; 2--xvYCC709
+        ColorDepth  :   0--24bit;   1--30bit;   2--36bit
+return: 0
+*/
+
+int hdmi_gen_gbd_infoframe(struct hdmi_ip_data *ip_data)
+{
+#if 0   
+    static u8 pkt[32];
+    u32 checksum = 0;
+
+    unsigned int deep_color = core->deep_color;
+    unsigned int color_xvycc = core->color_xvycc;
+    int i;
+
+    /* clear buffer */
+    for(i=0;i<32;i++)
+        pkt[i]=0;
+    
+    //1. header
+    pkt[0] = 0xa;       //header
+    pkt[1] = (0x1<<7) | (0x0<<4) | (0x1);         //Next_Field = 1; GBD_Profile = P0; Affected Gamut seq num = 1;
+    pkt[2] = (0x3<<4) | (0x1);                    //Only Packet in sequence; current Gamut seq num = 1;
+    pkt[3] = 0x00;      // checksum = 0 
+    
+    //2. data 
+    //PB1--Format Flag; GBD_Color_Precision; GBD_Color_Space
+    pkt[4] = (0x1<<7) | (deep_color<<3) | (color_xvycc); 
+    
+    if (deep_color == 0)        //24bit
+    {
+        pkt[5] = 0x0;                   //min Red data
+        pkt[6] = 0xfe;              //max Red data
+        pkt[7] = 0x0;                   //min Green data
+        pkt[8] = 0xfe;              //max Green data
+        pkt[9] = 0x0;                   //min Blue data
+        pkt[10] = 0xfe;             //max Blue data     
+    }
+    if (deep_color == 1)        //30bit
+    {
+        pkt[5] = 0x0;                   //min Red data: 0x0
+        pkt[6] = 0x3f;              //max Red data: 0x3f8
+        pkt[7] = 0x80;              //min Green data
+        pkt[8] = 0x3;                   //max Green data
+        pkt[9] = 0xf8;              //min Blue data
+        pkt[10] = 0x0;              //max Blue data  
+        pkt[11] = 0x3f;
+        pkt[12] = 0x80;   
+    }
+    if (deep_color == 2)        //36bit
+    {
+        pkt[5] = 0x0;                   //min Red data: 0x0
+        pkt[6] = 0xf;                 //max Red data: 0xfe0
+        pkt[7] = 0xe0;              //min Green data
+        pkt[8] = 0x0;                   //max Green data
+        pkt[9] = 0xf;                 //min Blue data
+        pkt[10] = 0xe0;             //max Blue data  
+        pkt[11] = 0x0;
+        pkt[12] = 0xf;
+        pkt[13] = 0xe0;   
+    }
+        
+    // count checksum
+    for(i=0; i<31; i++)
+        checksum += pkt[i];
+    pkt[3] = (~checksum + 1) & 0xff;
+
+    /* set to RAM Packet */
+    
+    hdmi_SetRamPacket(HDMI_RAMPKT_GBD_SLOT, pkt);
+    hdmi_SetRamPacketPeriod(HDMI_RAMPKT_GBD_SLOT, HDMI_RAMPKT_PERIOD);
+#endif
+    return 0;
+}
+
+/*
+* hdmi_gen_vs_infoframe(Vendor Specific)
+* input:  3D format
+* return: 0
+*/
+
+int hdmi_gen_vs_infoframe(struct hdmi_ip_data *ip_data)
+{
+    static u8 pkt[32];
+    u32 checksum = 0;
+    int i;
+    
+    /* clear buffer */
+    for (i = 0; i < 32; i++)
+        pkt[i] = 0;
+    
+    //1. header
+    pkt[0] = 0x81;       //header
+    pkt[1] = 0x1;        //Version
+
+    if (ip_data->cfg.cm.code == 2) {
+
+        pkt[2] = 0x6;        //length,  for Side-by-Side Half 3D
+
+    } else {
+
+        pkt[2] = 0x5;        //length,  for Frame 3D and Top-Bottom Half 3D
+
+    }
+    
+    pkt[3] = 0x00;      // checksum = 0 
+    
+    //2. data 
+    //PB1--PB3:24bit IEEE Registration Identifier
+    pkt[4] = 0x03;
+    pkt[5] = 0x0c;
+    pkt[6] = 0x00; 
+    
+    //PB4: HDMI_Video_Format:000--no additional;001--extended resolution(4k*2k);010--3D format
+    pkt[7] = 0x2<<5;       //3D format
+    switch(ip_data->cfg.cm.code)
+    {
+     case   1:  pkt[8] = 0x0<<4;                //3D Frame
+                pkt[9] = 0x0;
+                break;
+     case   2:  pkt[8] = 0x8<<4;                //Side-by-Side (Half)
+                pkt[9] = 0x1<<4;
+                break;
+     case   3:  pkt[8] = 0x6<<4;                //Top-and-bottom (Half)
+                pkt[9] = 0x0;
+                break;
+     default :  break;              
+    }
+        
+    // count checksum
+    for(i=0; i<31; i++)
+        checksum += pkt[i];
+    pkt[3] = (~checksum + 1) & 0xff;
+
+    /* set to RAM Packet */
+    
+    hdmi_SetRamPacket(HDMI_RAMPKT_VS_SLOT, pkt);
+    hdmi_SetRamPacketPeriod(HDMI_RAMPKT_VS_SLOT, HDMI_RAMPKT_PERIOD);
+
+    return 0;
+}
+
+int  asoc_hdmi_gen_infoframe(struct hdmi_ip_data *ip_data)
+{
+    HDMI_DEBUG("asoc_hdmi_gen_infoframe\n");
+    hdmi_gen_spd_infoframe();
+    if (hdmi_gen_avi_infoframe(ip_data))
+        return -EINVAL;
+    
+
+//  hdmi_gen_gbd_infoframe(ip_data);
+//  hdmi_gen_vs_infoframe(ip_data);
+    
+
+    return 0;
+}
+
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_panel.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_panel.c
new file mode 100755
index 0000000..f88e9b8
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_panel.c
@@ -0,0 +1,343 @@
+/*
+ * hdmi_panel.c
+ *
+ * HDMI library support functions for TI OWL4 processors.
+ *
+ * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/
+ * Authors:	Mythri P k <mythripk at ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <mach/bootdev.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include "../../dss/dss_features.h"
+
+#include "hdmi.h"
+
+static struct {
+	/* This protects the panel ops, mainly when accessing the HDMI IP. */
+	struct mutex lock;
+
+} hdmi_panel;
+
+static int hdmi_panel_probe(struct owl_dss_device *dssdev)
+{
+	/* Initialize default timings to VGA in DVI mode */
+	
+	HDMI_DEBUG("ENTER hdmi_panel_probe\n");
+	//owldss_hdmi_display_set_vid(dssdev, &dssdev->timings, 1);
+	HDMI_DEBUG("hdmi_panel_probe x_res= %d y_res = %d\n",
+		dssdev->timings.x_res,
+		dssdev->timings.y_res);
+
+	return owldss_hdmi_panel_init(dssdev);
+}
+
+static void hdmi_panel_remove(struct owl_dss_device *dssdev)
+{
+
+}
+
+static int hdmi_panel_suspend(struct owl_dss_device *dssdev)
+{
+	HDMI_DEBUG("ENTER hdmi_panel_suspend\n");
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_panel_suspend(dssdev);
+
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return 0;
+}
+
+static int hdmi_panel_resume(struct owl_dss_device *dssdev)
+{
+	HDMI_DEBUG("ENTER hdmi_panel_resume\n");
+	mutex_lock(&hdmi_panel.lock);
+
+	owldss_hdmi_panel_resume(dssdev);
+	
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return 0;
+}
+
+static int hdmi_panel_enable(struct owl_dss_device *dssdev)
+{
+	int r = 0;
+	HDMI_DEBUG("ENTER hdmi_panel_enable\n");
+	mutex_lock(&hdmi_panel.lock);
+
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE) {
+		r = 0;
+		goto err;
+	}
+
+//	owldss_hdmi_display_set_timing(dssdev, &dssdev->timings);
+
+	r = owldss_hdmi_display_enable(dssdev);
+	if (r) {
+		DEBUG_ERR("failed to power on\n");
+		goto err;
+	}
+
+	dssdev->state = OWL_DSS_DISPLAY_ACTIVE;
+
+err:
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return r;
+}
+
+static void hdmi_panel_disable(struct owl_dss_device *dssdev)
+{
+	mutex_lock(&hdmi_panel.lock);
+
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE) {
+		owldss_hdmi_display_disable(dssdev);
+		dssdev->state = OWL_DSS_DISPLAY_DISABLED;		
+	}
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_get_timings(struct owl_dss_device *dssdev,
+			struct owl_video_timings *timings)
+{
+	mutex_lock(&hdmi_panel.lock);
+
+	*timings = dssdev->timings;
+
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_set_timings(struct owl_dss_device *dssdev,
+			struct owl_video_timings *timings)
+{
+	HDMI_DEBUG("hdmi_set_timings\n");
+
+	mutex_lock(&hdmi_panel.lock);
+
+	owldss_hdmi_display_set_timing(dssdev, timings);
+
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static int hdmi_check_timings(struct owl_dss_device *dssdev,
+			struct owl_video_timings *timings)
+{
+	int r = 0;
+
+	HDMI_DEBUG("hdmi_check_timings\n");
+
+	mutex_lock(&hdmi_panel.lock);
+
+	r = owldss_hdmi_display_check_timing(dssdev, timings);
+
+	mutex_unlock(&hdmi_panel.lock);
+	return r;
+}
+
+static void hdmi_set_vid(struct owl_dss_device *dssdev,
+			int vid)
+{
+	HDMI_DEBUG("hdmi_set_vid\n");
+
+	mutex_lock(&hdmi_panel.lock);
+
+	owldss_hdmi_display_set_vid(dssdev, vid);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_get_vid(struct owl_dss_device *dssdev,
+			int *vid)
+{
+	HDMI_DEBUG("hdmi_get_vid\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_display_get_vid(dssdev, vid);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_enable_hpd(struct owl_dss_device *dssdev,
+			bool enable)
+{
+	HDMI_DEBUG("hdmi_enable_hpd\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_display_enable_hotplug(dssdev, enable);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_enable_hdcp(struct owl_dss_device *dssdev,
+			bool enable)
+{
+	HDMI_DEBUG("hdmi_enable_hdcp\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_display_enable_hdcp(dssdev, enable);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_get_over_scan(struct owl_dss_device *dssdev, u16 * over_scan_width,u16 * over_scan_height)
+{
+	HDMI_DEBUG("hdmi_get_over_scan\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_display_get_overscan(dssdev, over_scan_width,over_scan_height);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static void hdmi_set_over_scan(struct owl_dss_device *dssdev,u16 over_scan_width,u16 over_scan_height)
+{
+	HDMI_DEBUG("hdmi_set_over_scan\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	owldss_hdmi_display_set_overscan(dssdev, over_scan_width,over_scan_height);
+	
+	mutex_unlock(&hdmi_panel.lock);
+}
+
+static int hdmi_get_vid_cap(struct owl_dss_device *dssdev,
+			int *vid_cap)
+{
+	int r;
+	
+	HDMI_DEBUG("hdmi_get_vid_cap\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	r = owldss_hdmi_display_get_vid_cap(dssdev, vid_cap);
+	
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return r;
+}
+
+static int hdmi_read_edid(struct owl_dss_device *dssdev,u8 *buf, int len)
+{
+	int r;
+	
+	HDMI_DEBUG("hdmi_read_edid\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	r = owldss_hdmi_read_edid(dssdev, buf, len);
+	
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return r;
+}
+
+static int hdmi_get_cable_status(struct owl_dss_device *dssdev)
+{
+	int r;
+	HDMI_DEBUG("hdmi_get_cable_status\n");
+
+	mutex_lock(&hdmi_panel.lock);
+	
+	r = owldss_hdmi_display_get_cable_status(dssdev);
+	
+	mutex_unlock(&hdmi_panel.lock);
+	
+	return r;
+}
+
+static int generic_hdmi_panel_get_effect_parameter(struct owl_dss_device *dssdev,
+                                              enum owl_plane_effect_parameter parameter_id)
+{
+	return owl_hdmi_get_effect_parameter(dssdev, parameter_id);
+}
+
+static void generic_hdmi_panel_set_effect_parameter(struct owl_dss_device *dssdev,
+                                           enum owl_plane_effect_parameter parameter_id ,int value)
+{
+	owl_hdmi_set_effect_parameter(dssdev, parameter_id,value);
+}
+
+static struct owl_dss_driver hdmi_driver = {
+	.probe			  = hdmi_panel_probe,
+	.remove			  = hdmi_panel_remove,
+	.suspend		  = hdmi_panel_suspend,
+	.resume 		  = hdmi_panel_resume,
+	.enable			  = hdmi_panel_enable,
+	.disable		  = hdmi_panel_disable,
+	.get_timings	  = hdmi_get_timings,
+	.set_timings	  = hdmi_set_timings,
+	.check_timings	  = hdmi_check_timings,
+	.set_vid   	 	  = hdmi_set_vid,
+	.get_vid    	  = hdmi_get_vid,
+	.enable_hpd		  = hdmi_enable_hpd,
+	.enable_hdcp	  = hdmi_enable_hdcp,
+	.get_vid_cap 	  = hdmi_get_vid_cap, 
+	.get_cable_status = hdmi_get_cable_status,
+	.get_effect_parameter   = generic_hdmi_panel_get_effect_parameter,
+	.set_effect_parameter   = generic_hdmi_panel_set_effect_parameter,
+	.get_over_scan = hdmi_get_over_scan,
+	.set_over_scan = hdmi_set_over_scan,
+	.read_edid        = hdmi_read_edid,
+	.driver			= {
+		.name   = "hdmi_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+int __init hdmi_panel_init(void)
+{
+   
+   
+   int r = -1; 
+   if (owl_get_boot_mode() == OWL_BOOT_MODE_UPGRADE) {
+		printk("upgrade process hdmi disabled!!\n");
+		return -ENODEV;
+	}
+	mutex_init(&hdmi_panel.lock);
+	
+	r = owl_hdmi_init_platform();
+	
+	if(r)
+	{
+		return r;
+	}
+	return owl_dss_register_driver(&hdmi_driver);
+
+}
+
+void __exit hdmi_panel_exit(void)
+{
+	
+	owl_hdmi_uninit_platform();
+	
+	owl_dss_unregister_driver(&hdmi_driver);
+
+}
+
+module_init(hdmi_panel_init);
+module_exit(hdmi_panel_exit);
+MODULE_LICENSE("GPL");
\ No newline at end of file
diff --git a/drivers/video/fbdev/owl/displays/hdmi/hdmi_sysfs.c b/drivers/video/fbdev/owl/displays/hdmi/hdmi_sysfs.c
new file mode 100755
index 0000000..7d6b3a5
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/hdmi/hdmi_sysfs.c
@@ -0,0 +1,440 @@
+/*
+ * hdmi_sysfs.c
+ *
+ * HDMI OWL IP driver Library
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Guo Long  <guolong at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/string.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/poll.h>
+
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+
+#include "hdmi_ip.h"
+#include "hdmi.h"
+
+static ssize_t store_hdmi_src(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+	hdmi_send_uevent(0);	
+	hdmi.ip_data.settings.hdmi_src = val;
+	hdmi_send_uevent(1);		
+	return r ? r : count;
+}
+
+static ssize_t show_hdmi_src(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", hdmi.ip_data.settings.hdmi_src);
+}
+
+static ssize_t store_hdmi_plug(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+		
+	owldss_hdmi_hotplug_debug(hdmi.dssdev,val);	
+	
+	return r ? r : count;
+}
+
+static ssize_t store_hdmi_cable(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+		
+	owldss_hdmi_cable_debug(hdmi.dssdev,val);	
+	
+	return r ? r : count;
+}
+
+static ssize_t store_hdmi_uevent(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+		
+	owldss_hdmi_uevent_debug(hdmi.dssdev,val);	
+	
+	return r ? r : count;
+}
+
+static ssize_t show_hdmi_plug(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", hdmi.data.hdmi_sta);
+}
+
+
+static ssize_t show_TX_AMP(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_1);
+	val = 0x0000000F&val;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_TX_AMP(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_1);
+	tmp= ((tmp&0xFFFFFFF8)|val); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_1);
+	return r ? r : count;
+}
+
+static ssize_t show_TX_IBIAS(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_1);
+	val = ((0x00000030&val)>>4);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_TX_IBIAS(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_1);
+	tmp= ((tmp&0xFFFFFFCF)|(val<<4)); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_1);
+	return r ? r : count;
+}
+
+static ssize_t show_TER_EN(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_2);
+	val = ((0x00020000&val)>>17);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_TER_EN(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_2);
+	tmp= ((tmp&0xfffdffff)|(val<<17)); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_2);
+	return r ? r : count;
+}
+
+
+static ssize_t show_TER_SET(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_2);
+	val = ((0x000c0000&val)>>18);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_TER_SET(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_2);
+	tmp= ((tmp&0xfff3ffff)|(val<<18)); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_2);
+	return r ? r : count;
+}
+
+
+
+static ssize_t show_TMDS_LDO(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_2);
+	val = ((0x0000000e&val)>>1);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_TMDS_LDO(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_2);
+	tmp= ((tmp&0xfffffff1)|(val<<1)); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_2);
+	return r ? r : count;
+}
+
+
+static ssize_t show_SLEW(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_2);
+	val = ((0x000000c0&val)>>6);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_SLEW(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_2);
+	tmp= ((tmp&0xffffff3f)|(val<<6)); 
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_2);
+	return r ? r : count;
+}
+
+
+static ssize_t show_EMP_EN(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_1);
+	val = ((0x00000040&val)>>6);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_EMP_EN(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_1);
+
+	tmp= ((tmp&0xffffffbf)|(val<<6)); 
+
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_1);
+	return r ? r : count;
+}
+
+
+
+static ssize_t show_EMP_SET(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	int val;
+	val = readl(hdmi.ip_data.base+HDMI_TX_1);
+	val = ((0x00000380&val)>>7);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t store_EMP_SET(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val,tmp;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+  tmp=readl(hdmi.ip_data.base+HDMI_TX_1);
+
+	tmp= ((tmp&0xfffffc7f)|(val<<7)); 
+
+	writel(tmp,hdmi.ip_data.base+HDMI_TX_1);
+	return r ? r : count;
+}
+
+
+static ssize_t store_hdmi_vid(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+
+	owldss_hdmi_display_disable(hdmi.dssdev);
+	hdmi.dssdev->driver->set_vid(hdmi.dssdev, val);
+	owldss_hdmi_display_enable(hdmi.dssdev);		
+	return r ? r : count;
+}
+
+static ssize_t show_hdmi_vid(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	
+	return snprintf(buf, PAGE_SIZE, "%d\n", hdmi.ip_data.cfg.cm.code);
+}
+
+static ssize_t show_hdmi_dump(struct device *dev, struct device_attribute *attr, char *buf)
+{
+
+	hdmi.ip_data.ops->dump_hdmi(&hdmi.ip_data);
+	return 0;
+}
+
+static ssize_t show_edid_ok(struct device *dev, struct device_attribute *attr, char *buf)
+{
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", hdmi.edid.read_ok);
+}
+
+static ssize_t show_edid_buf(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	int i;
+	for(i=0; i< 512; i++){
+		DEBUG_ON("EDID_Buf[0x%x]=0x%x\n", i, hdmi.edid.EDID_Buf[i]);	
+	}
+	return 0;
+}
+
+static ssize_t store_hdcp_switch(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+
+	hdmi_send_uevent(0);
+	hdmi.dssdev->driver->enable_hdcp(hdmi.dssdev, val);
+	hdmi_send_uevent(1);	
+	return r ? r : count;
+}
+
+static ssize_t store_hpd_switch(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	int val;
+	int r;
+	r = kstrtoint(buf, 0, &val);
+	if (r)
+		return r;
+
+	owldss_hdmi_display_enable_hotplug(hdmi.dssdev, val);	
+	
+	return r ? r : count;
+}
+
+static struct device_attribute asoc_hdmi_attrs[] = {
+	__ATTR(reg_dump, S_IRUGO, show_hdmi_dump, NULL),
+	__ATTR(edid_ok, S_IRUGO, show_edid_ok, NULL),
+	__ATTR(edid_buf, S_IRUGO, show_edid_buf, NULL),
+	__ATTR(TX_IBIAS, S_IRUGO| S_IWUSR, show_TX_IBIAS, store_TX_IBIAS),
+	__ATTR(TX_AMP, S_IRUGO| S_IWUSR, show_TX_AMP, store_TX_AMP),
+	__ATTR(TER_EN, S_IRUGO| S_IWUSR, show_TER_EN, store_TER_EN),
+	__ATTR(TER_SET, S_IRUGO| S_IWUSR, show_TER_SET, store_TER_SET),
+	__ATTR(TMDS_LDO, S_IRUGO| S_IWUSR, show_TMDS_LDO, store_TMDS_LDO),
+	__ATTR(EMP_EN, S_IRUGO| S_IWUSR, show_EMP_EN, store_EMP_EN),
+	__ATTR(SLEW, S_IRUGO| S_IWUSR, show_SLEW, store_SLEW),
+	__ATTR(EMP_SET, S_IRUGO| S_IWUSR, show_EMP_SET, store_EMP_SET),
+	__ATTR(hdcp_switch, S_IWUSR, NULL, store_hdcp_switch),
+	__ATTR(vid, S_IRUGO | S_IWUSR, show_hdmi_vid, store_hdmi_vid),
+	__ATTR(src, S_IRUGO | S_IWUSR, show_hdmi_src, store_hdmi_src),
+	__ATTR(plug, S_IRUGO | S_IWUSR, show_hdmi_plug, store_hdmi_plug),
+	__ATTR(cable, S_IRUGO | S_IWUSR, show_hdmi_plug, store_hdmi_cable),
+	__ATTR(switchuevent, S_IRUGO | S_IWUSR, show_hdmi_plug, store_hdmi_uevent),
+	__ATTR(hpd_switch, S_IWUSR, NULL, store_hpd_switch),
+};
+
+int owl_hdmi_create_sysfs(struct device *dev)
+{
+	int r, t;
+
+	for (t = 0; t < ARRAY_SIZE(asoc_hdmi_attrs); t++) 
+	{
+		r = device_create_file(dev, &asoc_hdmi_attrs[t]);
+
+		if (r) {
+			dev_err(dev, "failed to create sysfs file\n");
+			return r;
+		}
+	}
+
+	return 0;
+}
+
+void asoc_hdmi_remove_sysfs(struct device *dev)
+{
+	int  t;
+	
+	for (t = 0; t < ARRAY_SIZE(asoc_hdmi_attrs); t++) 
+	{
+		device_remove_file(dev, &asoc_hdmi_attrs[t]);
+	}
+}
+
diff --git a/drivers/video/fbdev/owl/displays/lcdc/Kconfig b/drivers/video/fbdev/owl/displays/lcdc/Kconfig
new file mode 100755
index 0000000..a59d8ad
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/lcdc/Kconfig
@@ -0,0 +1,9 @@
+config VIDEO_OWL_LCDC
+	tristate "OWL lcd controller support"
+	---help---
+	  Actions OWL Soc lcd controller support.
+
+	  Say Y here if you need it in your system.
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
diff --git a/drivers/video/fbdev/owl/displays/lcdc/Makefile b/drivers/video/fbdev/owl/displays/lcdc/Makefile
new file mode 100755
index 0000000..ab83a08
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/lcdc/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_VIDEO_OWL_LCDC) += owl_lcdc.o
+
+owl_lcdc-y := lcdchw.o panel-lcd.o
diff --git a/drivers/video/fbdev/owl/displays/lcdc/lcdchw.c b/drivers/video/fbdev/owl/displays/lcdc/lcdchw.c
new file mode 100755
index 0000000..c550cb8
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/lcdc/lcdchw.c
@@ -0,0 +1,1079 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/lcdc.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "LCDC"
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/export.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/pm_runtime.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+
+#include <mach/hardware.h>
+
+#include <video/owldss.h>
+
+#include "../../dss/dss_features.h"
+#include "../../dss/dss.h"
+#include "lcdchw.h"
+
+#define POWER_REGULATOR_NAME        "lcdvcc"
+
+struct owl_lcdc_gpio {
+    int gpio;
+    int active_low;
+};
+
+struct owl_videomode {
+    u32                     refresh;
+    u32                     xres;
+    u32                     yres;
+
+    /*in pico second, 0.000 000 000 001s*/
+    u32                     pixclock;
+
+    u32                     left_margin;
+    u32                     right_margin;
+    u32                     upper_margin;
+    u32                     lower_margin;
+    u32                     hsync_len;
+    u32                     vsync_len;
+
+    /*0: FB_VMODE_NONINTERLACED, 1:FB_VMODE_INTERLACED*/
+    u32                     vmode;
+};
+
+struct lcdc_data {
+    struct platform_device  *pdev;
+    void __iomem            *base;
+    struct owl_dss_device   *dssdev;
+
+    struct clk              *lcdc_clk;
+    struct regulator        *lcdc_power;
+
+    /* the followings are strict with DTS */
+    struct owl_lcdc_gpio    power_gpio;
+	struct owl_lcdc_gpio    reset_gpio;
+	struct owl_lcdc_gpio    standby_gpio;
+
+    #define LCD_PORT_TYPE_RGB       0
+    #define LCD_PORT_TYPE_CPU       1
+    #define LCD_PORT_TYPE_LVDS      2
+    #define LCD_PORT_TYPE_EDP       3
+    u32                     port_type;
+
+    u32                     data_width;
+    u32                     vsync_inversion;
+    u32                     hsync_inversion;
+    u32                     dclk_inversion;
+    u32                     lde_inversion;
+    u32                      lightness;
+    u32                      saturation;
+    u32                      contrast;
+
+	u32                     lvds_ctl;
+	u32                     lvds_alg_ctl0;
+	
+    u32                     num_modes;
+    struct owl_videomode   *modes;
+    /* end of strict with DTS */
+
+    bool                    lcdc_enabled;
+    
+    struct mutex            lock;
+};
+
+static bool boot_lcd0_inited;
+
+static struct platform_device *lcdc_pdev_map[MAX_NUM_LCD];
+
+inline struct lcdc_data *lcdchw_get_lcdcdrv_data(struct platform_device *lcdcdev)
+{
+    return dev_get_drvdata(&lcdcdev->dev);
+}
+
+inline void lcdchw_write_reg(struct platform_device *lcdcdev,const u16 index, u32 val)
+{
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    DSSDBG("lcdchw_write_reg  ~~~ %p index %d\n",lcdc->base,index);
+    writel(val, lcdc->base + index);
+}
+
+inline u32 lcdchw_read_reg(struct platform_device *lcdcdev,const u16 index)
+{
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    DSSDBG("lcdchw_read_reg  ~~~ %p index %d\n",lcdc->base,index);
+    return readl(lcdc->base + index);
+}
+
+void lcdchw_dump_regs(struct platform_device *lcdcdev){
+#define DUMPREG(r) DSSDBG("%08x ~~ %08x\n",r,lcdchw_read_reg(lcdcdev,r))
+     DUMPREG(LCDCHW_CTL);
+     DUMPREG(LCDCHW_SIZE);
+     DUMPREG(LCDCHW_STATUS);
+     DUMPREG(LCDCHW_TIM0);
+     DUMPREG(LCDCHW_TIM1);
+     DUMPREG(LCDCHW_TIM2);
+     DUMPREG(LCDCHW_COLOR);
+     DUMPREG(LCDCHW_IMG_XPOS);
+     DUMPREG(LCDCHW_IMG_YPOS);
+#if 1
+     DUMPREG(LCDCHW_LVDS_CTL);
+     DUMPREG(LCDCHW_LVDS_ALG_CTL0);
+     DUMPREG(LCDCHW_LVDS_DEBUG);
+#endif
+}
+
+/* TODO */
+#if 0
+static int lcdchw_set_lcdc_clk(struct platform_device *lcdcdev, bool is_tft,
+                               unsigned long pck_req, unsigned long *fck,
+                               int *lck_div, int *pck_div)
+{
+    return 0;
+}
+#endif
+
+static void lcdchw_set_size(struct platform_device *lcdcdev, u16 width, u16 height)
+{
+    u32 val;
+    
+    BUG_ON((width > (1 << 12)) || (height > (1 << 12)));
+    
+    val = REG_VAL(height - 1, 27, 16) | REG_VAL(width - 1, 11, 0);
+    
+    lcdchw_write_reg(lcdcdev,LCDCHW_SIZE, val);
+}
+
+static void lcdchw_set_preline(struct platform_device *lcdcdev,u16 preline)
+{
+    u32 val;
+        
+    val = 0;
+    
+    val = REG_SET_VAL(val, preline, 12, 8);
+    
+    val = REG_SET_VAL(val, 1, 13, 13);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM0, val);
+}
+
+static void lcdchw_set_default_color(struct platform_device *lcdcdev, u32 color)
+{    
+    lcdchw_write_reg(lcdcdev,LCDCHW_COLOR, color);
+}
+
+static void lcdchw_set_vsync_inv(struct platform_device *lcdcdev, u8 vsync_inv)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_TIM0);
+    
+    val = REG_SET_VAL(val, vsync_inv, 7, 7);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM0, val);
+}
+static void lcdchw_set_hsync_inv(struct platform_device *lcdcdev, u8 hsync_inv)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_TIM0);
+    
+    val = REG_SET_VAL(val, hsync_inv, 6, 6);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM0, val);
+}
+
+static void lcdchw_set_dclk_inv(struct platform_device *lcdcdev, u8 dclk_inv)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_TIM0);
+    
+    val = REG_SET_VAL(val, dclk_inv, 5, 5);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM0, val);
+}
+
+static void lcdchw_set_lde_inv(struct platform_device *lcdcdev, u8 led_inv)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_TIM0);
+    
+    val = REG_SET_VAL(val, led_inv, 4, 4);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM0, val);
+}
+static void lcdchw_set_timings(struct platform_device *lcdcdev, u16 hbp ,u16 hfp, u16 hsw, u16 vbp ,u16 vfp, u16 vsw)
+{    
+    u32 val;
+    
+    BUG_ON((hbp > (1 << 9)) || (hfp > (1 << 9)) || (hsw > (1 << 9)));    
+    
+    BUG_ON((vbp > (1 << 9)) || (vfp > (1 << 9)) || (vsw > (1 << 9)));
+       
+    val = REG_VAL(hsw - 1, 29, 20) | REG_VAL(hfp - 1, 19, 10) | REG_VAL(hbp - 1, 9, 0) ;
+    
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM1, val);
+    
+    val = REG_VAL(vsw - 1, 29, 20) | REG_VAL(vfp - 1, 19, 10) | REG_VAL(vbp - 1, 9, 0) ;
+    
+    lcdchw_write_reg(lcdcdev,LCDCHW_TIM2, val);
+    
+}
+
+static void lcdchw_set_single_fromat(struct platform_device *lcdcdev,u8 format)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, format, 12, 10);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_set_all_pad_pulldown(struct platform_device *lcdcdev,bool pull_down)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, pull_down, 20, 20);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_set_rb_swap(struct platform_device *lcdcdev, bool rb_swap)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, rb_swap, 1, 1);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_set_data_width(struct platform_device *lcdcdev, int data_width)
+{    
+    u32 val;
+
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, data_width, 18, 16);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_set_single_from(struct platform_device *lcdcdev, u8 single)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, single, 7, 6);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_single_enable(struct platform_device *lcdcdev, bool enable)
+{    
+    u32 val;
+        
+    val = lcdchw_read_reg(lcdcdev,LCDCHW_CTL);
+    
+    val = REG_SET_VAL(val, enable, 0, 0);
+        
+    lcdchw_write_reg(lcdcdev,LCDCHW_CTL, val);
+}
+
+static void lcdchw_lvds_port_enable(struct platform_device *lcdcdev, bool enable)
+{    
+    u32 val;
+	struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+	
+    if(enable){        
+        val = lcdchw_read_reg(lcdcdev,LCDCHW_LVDS_ALG_CTL0);
+               
+        val = REG_SET_VAL(val, 3, 31, 30);
+       
+        val = REG_SET_VAL(val, 3, 5, 4);
+        
+        lcdchw_write_reg(lcdcdev,LCDCHW_LVDS_ALG_CTL0, lcdc->lvds_alg_ctl0);
+        
+        val = lcdchw_read_reg(lcdcdev,LCDCHW_LVDS_CTL);
+        
+        val = REG_SET_VAL(val, enable, 0, 0);
+        
+        lcdchw_write_reg(lcdcdev,LCDCHW_LVDS_CTL, lcdc->lvds_ctl);
+                    
+    }else{
+        val = lcdchw_read_reg(lcdcdev,LCDCHW_LVDS_ALG_CTL0);
+		        
+        val = REG_SET_VAL(val, 0, 31, 30);
+		   
+        val = REG_SET_VAL(val, 0, 5, 4);
+        
+        lcdchw_write_reg(lcdcdev,LCDCHW_LVDS_ALG_CTL0, val);
+        
+        val = lcdchw_read_reg(lcdcdev,LCDCHW_LVDS_CTL);
+        
+        val = REG_SET_VAL(val, enable, 0, 0);
+        
+        lcdchw_write_reg(lcdcdev,LCDCHW_LVDS_CTL, val);        
+    }
+    
+}
+
+static void lcdchw_display_init_lcdc(struct owl_dss_device *dssdev)
+{
+    struct platform_device * lcdcdev = lcdc_pdev_map[0];
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    struct owl_video_timings * timings = &(dssdev->timings);
+    
+    BUG_ON(!timings);
+    
+    lcdchw_set_size(lcdcdev,timings->x_res,timings->y_res);
+
+    lcdchw_set_timings(lcdcdev,timings->hbp ,timings->hfp, timings->hsw, timings->vbp ,timings->vfp, timings->vsw);
+    
+    lcdchw_set_preline(lcdcdev,8);
+    
+    if(lcdc->port_type == LCD_PORT_TYPE_RGB){ 
+	
+		lcdchw_set_all_pad_pulldown(lcdcdev,false);
+	
+	}    
+    
+    lcdchw_set_data_width(lcdcdev,lcdc->data_width);
+
+    lcdchw_set_default_color(lcdcdev,0);
+    
+    lcdchw_set_single_fromat(lcdcdev,0);
+    
+    lcdchw_set_rb_swap(lcdcdev,0);
+    
+    lcdchw_set_vsync_inv(lcdcdev,lcdc->vsync_inversion);
+    
+    lcdchw_set_hsync_inv(lcdcdev,lcdc->hsync_inversion);    
+    
+    lcdchw_set_dclk_inv(lcdcdev, lcdc->dclk_inversion);
+
+    lcdchw_set_lde_inv(lcdcdev, lcdc->lde_inversion);
+    
+    lcdchw_set_single_from(lcdcdev,0x02);
+
+}
+
+static int lcdchw_get_clocks(struct platform_device *lcdcdev)
+{
+#if 0
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    struct clk *clk;
+    clk = clk_get(&lcdcdev->dev, "lcd");
+    if (IS_ERR(clk)) {
+        DSSERR("can't get fck\n");
+        return PTR_ERR(clk);
+    }
+
+    lcdc->lcdc_clk = clk;
+#endif 
+    return 0;
+}
+
+static void lcdchw_put_clocks(struct platform_device *lcdcdev)
+{
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+
+    if (lcdc->lcdc_clk)
+        clk_put(lcdc->lcdc_clk);
+
+}
+
+static void lcdchw_check_boot_lcd0_inited(struct platform_device *lcdcdev) {
+    boot_lcd0_inited = lcdchw_read_reg(lcdcdev, LCDCHW_CTL) & 0x1;
+
+    DSSINFO("LCD INITED FROM UBOOT??  %d\n", boot_lcd0_inited);
+
+    return ;
+}
+
+static int lcdchw_power_init(struct platform_device *lcdcdev) {
+    int ret = 0;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+
+    if (boot_lcd0_inited) {
+        if (gpio_is_valid(lcdc->power_gpio.gpio)) {
+            gpio_direction_output(lcdc->power_gpio.gpio,
+                                  !lcdc->power_gpio.active_low);
+        }
+
+        if (lcdc->lcdc_power) {
+            ret = regulator_enable(lcdc->lcdc_power);
+        }
+
+        lcdc->lcdc_enabled = true;
+    } else {
+        if (gpio_is_valid(lcdc->power_gpio.gpio)) {
+            gpio_direction_output(lcdc->power_gpio.gpio,
+                                  lcdc->power_gpio.active_low);
+        }
+        lcdc->lcdc_enabled = false;
+    }
+
+    return ret;
+}
+
+static int lcdchw_power_enable(struct platform_device *lcdcdev, bool enable) {
+    int ret = 0;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+
+    if (enable) {
+        if (gpio_is_valid(lcdc->power_gpio.gpio)) {
+            gpio_direction_output(lcdc->power_gpio.gpio,
+                                  !lcdc->power_gpio.active_low);
+        }
+
+        if (lcdc->lcdc_power) {
+            ret = regulator_enable(lcdc->lcdc_power);
+        }
+		
+		if (gpio_is_valid(lcdc->reset_gpio.gpio)){
+			printk("reset_gpio  is ok %d\n", lcdc->reset_gpio.active_low);
+	        gpio_direction_output(lcdc->reset_gpio.gpio,
+                                  lcdc->reset_gpio.active_low);
+			mdelay(10);
+	        gpio_direction_output(lcdc->reset_gpio.gpio,
+                                  !lcdc->reset_gpio.active_low);
+
+		}
+		
+        if (gpio_is_valid(lcdc->standby_gpio.gpio)) {
+            gpio_direction_output(lcdc->standby_gpio.gpio,
+                                  !lcdc->standby_gpio.active_low);
+        }
+    } else {	
+        if (gpio_is_valid(lcdc->standby_gpio.gpio)) {
+            gpio_direction_output(lcdc->standby_gpio.gpio,
+                                  lcdc->standby_gpio.active_low);
+        }
+		
+		if (gpio_is_valid(lcdc->reset_gpio.gpio)){
+	        gpio_direction_output(lcdc->reset_gpio.gpio,
+                                  lcdc->reset_gpio.active_low);
+		}
+								  
+        if (gpio_is_valid(lcdc->power_gpio.gpio)) {
+            gpio_direction_output(lcdc->power_gpio.gpio,
+                                  lcdc->power_gpio.active_low);
+        }
+		
+		if (lcdc->lcdc_power) {
+            ret = regulator_disable(lcdc->lcdc_power);
+        }
+    }
+
+    return ret;
+}
+
+int owl_lcdc_display_enable(struct owl_dss_device *dssdev)
+{
+    int r;
+
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    
+    mutex_lock(&lcdc->lock);
+    
+    if (dssdev->manager == NULL) {
+        DSSERR("failed to enable display: no manager\n");
+        return -ENODEV;
+    }
+
+    r = owl_dss_start_device(dssdev);
+    
+    if (r) {
+        DSSERR("failed to start device\n");
+        goto err_start_dev;
+    }
+
+    r = dss_mgr_enable(dssdev->manager);
+    if (r)
+        goto err_mgr_enable;
+    
+    if (!lcdc->lcdc_enabled) {
+        lcdchw_power_enable(lcdcdev, true);
+
+        lcdchw_display_init_lcdc(dssdev);
+        
+        if(lcdc->port_type == LCD_PORT_TYPE_LVDS){   
+			lcdchw_lvds_port_enable(lcdcdev,true);
+		}
+        
+        lcdchw_single_enable(lcdcdev,true);    
+
+        lcdc->lcdc_enabled = true;
+    }
+
+   
+    mutex_unlock(&lcdc->lock);
+    lcdchw_dump_regs(lcdcdev);
+    return 0;
+    
+err_mgr_enable:
+err_start_dev:
+    mutex_unlock(&lcdc->lock);
+    return r;
+}
+
+void owl_lcdc_display_disable(struct owl_dss_device *dssdev)
+{
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    
+    mutex_lock(&lcdc->lock);
+	
+	if(lcdc->port_type == LCD_PORT_TYPE_LVDS){ 
+	
+		lcdchw_lvds_port_enable(lcdcdev,false);
+	
+    }
+    lcdchw_single_enable(lcdcdev,false);    
+    
+    dss_mgr_disable(dssdev->manager);
+	 
+	lcdchw_power_enable(lcdcdev, false);
+	
+	if(lcdc->port_type == LCD_PORT_TYPE_RGB){ 
+	
+		lcdchw_set_all_pad_pulldown(lcdcdev,true);
+	
+	}
+	
+    owl_dss_stop_device(dssdev);
+    
+    lcdc->lcdc_enabled = false;
+
+    mutex_unlock(&lcdc->lock);
+
+    lcdchw_dump_regs(lcdcdev);
+}
+
+/* temp, TODO pls fix me */
+void owl_lcdc_select_video_timings(struct owl_dss_device *dssdev, u32 num,
+                                   struct owl_video_timings *timings)
+{
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+
+    struct owl_videomode *mode = &lcdc->modes[num];
+
+    timings->x_res          = mode->xres;
+    timings->y_res          = mode->yres;
+    timings->pixel_clock    = mode->pixclock;
+    timings->hfp            = mode->left_margin;
+    timings->hbp            = mode->right_margin;
+    timings->vfp            = mode->upper_margin;
+    timings->vbp            = mode->lower_margin;
+    timings->hsw            = mode->hsync_len;
+    timings->vsw            = mode->vsync_len;
+	
+	timings->data_width     = 24;
+	switch(lcdc->data_width){
+		case 0:
+		timings->data_width     = 24;
+		break;
+		case 1:
+		timings->data_width     = 18;
+		break;
+		case 2:
+		timings->data_width     = 16;
+		break;
+	}
+    return;
+}
+
+int owl_lcdc_get_effect_parameter(struct owl_dss_device *dssdev, enum owl_plane_effect_parameter parameter_id)
+{
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+    switch(parameter_id){
+    	case OWL_DSS_VIDEO_LIGHTNESS:
+    		return lcdc->lightness;
+    	case OWL_DSS_VIDEO_SATURATION:
+    		return lcdc->saturation;
+    	case OWL_DSS_VIDEO_CONSTRAST:
+    		return lcdc->contrast;
+    	default:
+    		printk("invalid plane effect parameter \n");
+    		return -1;
+    }
+}
+
+void owl_lcdc_set_effect_parameter(struct owl_dss_device *dssdev,enum owl_plane_effect_parameter parameter_id ,int value)
+{
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(lcdcdev);
+     switch(parameter_id){
+    	case OWL_DSS_VIDEO_LIGHTNESS:
+    		lcdc->lightness = value;
+    		break;
+    	case OWL_DSS_VIDEO_SATURATION:
+    		lcdc->saturation = value;
+    		break;
+    	case OWL_DSS_VIDEO_CONSTRAST:
+    		lcdc->contrast = value;
+    		break;
+    	case OWL_DSS_DEF_EFFECT:
+    		lcdc->lightness = DEF_LIGHTNESS;
+			lcdc->saturation = DEF_SATURATION;
+			lcdc->contrast = DEF_CONTRAST;
+    		break;			
+    	default:
+    		printk("invalid plane effect parameter parameter_id %d value %d\n",parameter_id,value);
+    		break;
+    }
+
+}
+void owl_lcdc_display_dump()
+{
+    struct platform_device *lcdcdev = lcdc_pdev_map[0] ;    
+    lcdchw_dump_regs(lcdcdev);
+}
+
+struct port_type_param {
+    const char *name;
+    u32 port_type;
+};
+
+struct port_type_param port_types[] = {
+    {"rgb", LCD_PORT_TYPE_RGB},
+    {"cpu", LCD_PORT_TYPE_CPU},
+    {"lvds", LCD_PORT_TYPE_LVDS},
+    {"edp", LCD_PORT_TYPE_EDP},
+};
+
+static u32 string_to_port_type(const char *name)
+{
+    int i;
+    for (i = 0; i < ARRAY_SIZE(port_types); i++) {
+        if (!strcmp(port_types[i].name, name))
+            return port_types[i].port_type;
+    }
+
+    return -EINVAL;
+}
+
+static int lcdchw_parse_gpio(struct device_node *of_node,
+                             const char *propname,
+                             struct owl_lcdc_gpio *gpio)
+{
+    enum of_gpio_flags flags;
+    int                gpio_num;
+
+    gpio_num = of_get_named_gpio_flags(of_node, propname, 0, &flags);
+    if (gpio_num >= 0) {
+        gpio->gpio = gpio_num;
+    } else {
+        gpio->gpio = -1;
+    }
+
+    gpio->active_low = flags & OF_GPIO_ACTIVE_LOW;
+
+    DSSDBG("%s, gpio = %d\n", __func__, gpio->gpio);
+    DSSDBG("%s, active low = %d\n", __func__, gpio->active_low);
+
+    return 0;
+}
+
+static int lcdchw_parse_params(struct platform_device *pdev,
+                               struct lcdc_data *lcdc)
+{
+    struct device_node      *of_node;
+    char                    propname[20];
+    const char              *portname;
+    int                     mode_num;
+    struct device_node      *mode_node;
+    struct owl_videomode    *modes;
+    int                     i, ret;
+
+    of_node = pdev->dev.of_node;
+
+    /* 
+     * power gpio
+     */
+    lcdchw_parse_gpio(of_node, "lcd_power_gpios", &lcdc->power_gpio);
+    if (lcdc->power_gpio.gpio < 0) {
+        DSSERR("%s, fail to get lcd power gpio\n", __func__);
+    }
+	
+	 /* 
+     * reset gpio
+     */
+    lcdchw_parse_gpio(of_node, "lcd_reset_gpios", &lcdc->reset_gpio);
+    if (lcdc->reset_gpio.gpio < 0) {
+        DSSERR("%s, fail to get lcd reset gpio\n", __func__);
+    }
+	 /* 
+     * standby gpio
+     */
+    lcdchw_parse_gpio(of_node, "lcd_standby_gpios", &lcdc->standby_gpio);
+    if (lcdc->standby_gpio.gpio < 0) {
+        DSSERR("%s, fail to get lcd standby gpio\n", __func__);
+    }
+
+    /* 
+     * interface timing
+     */
+    if (of_property_read_string(of_node, "port_type", &portname)) {
+        return -EINVAL;
+    }
+    DSSDBG("portname = %s\n", portname);
+
+    lcdc->port_type = string_to_port_type(portname);
+
+    if (of_property_read_u32(of_node, "data_width", &lcdc->data_width)) {
+        return -EINVAL;
+    }
+    DSSDBG("data_width = %d\n", lcdc->data_width);
+
+    if (of_property_read_u32(of_node, "vsync_inversion",
+                             &lcdc->vsync_inversion)) {
+        return -EINVAL;
+    }
+    DSSDBG("vsync_inversion = %d\n", lcdc->vsync_inversion);
+
+    if (of_property_read_u32(of_node, "hsync_inversion",
+                             &lcdc->hsync_inversion)) {
+        return -EINVAL;
+    }
+    DSSDBG("hsync_inversion = %d\n", lcdc->hsync_inversion);
+
+    if (of_property_read_u32(of_node, "dclk_inversion",
+                             &lcdc->dclk_inversion)) {
+        return -EINVAL;
+    }
+    DSSDBG("dclk_inversion = %d\n", lcdc->dclk_inversion);
+
+    if (of_property_read_u32(of_node, "lde_inversion",
+                             &lcdc->lde_inversion)) {
+        return -EINVAL;
+    }
+    DSSDBG("lde_inversion = %d\n", lcdc->lde_inversion);
+	
+	if(lcdc->port_type == LCD_PORT_TYPE_LVDS){
+	    if (of_property_read_u32(of_node, "lvds_ctl", &lcdc->lvds_ctl)) {
+	        lcdc->lvds_ctl = 0x000a9521;
+	    } 
+	    
+	    if (of_property_read_u32(of_node, "lvds_alg_ctl0", &lcdc->lvds_alg_ctl0)) {
+	        lcdc->lvds_alg_ctl0 = 0xc141a030;
+	    } 
+	    printk("lvds_ctl 0x%x lvds_alg_ctl0 0x%x \n",lcdc->lvds_ctl,lcdc->lvds_alg_ctl0);
+	}
+
+    if (of_property_read_u32(of_node, "lightness", &lcdc->lightness)) {
+        lcdc->lightness = DEF_LIGHTNESS;
+    } 
+          
+    DSSDBG("lightness = %d\n", lcdc->lightness);
+        
+    if (of_property_read_u32(of_node, "saturation", &lcdc->saturation)) {
+        lcdc->saturation = DEF_SATURATION;
+    }
+    DSSDBG("saturation = %d\n", lcdc->saturation);
+    
+    if (of_property_read_u32(of_node, "contrast", &lcdc->contrast)) {
+        lcdc->contrast = DEF_CONTRAST; 
+    }
+    DSSDBG("contrast = %d\n", lcdc->contrast); 
+    /* 
+     * video mode
+     */
+
+    /* get  mode number */
+    for (mode_num = 0; ; mode_num++) {
+        sprintf(propname, "videomode-%d", mode_num);
+        DSSDBG("propname = %s\n", propname);
+
+        mode_node = of_parse_phandle(of_node, propname, 0);
+        if (!mode_node) {
+            break;
+        }
+    }
+    DSSDBG("mode num = %d\n", mode_num);
+
+    /* alloc memory */
+    modes = kzalloc(sizeof(struct owl_videomode) * mode_num, GFP_KERNEL);
+    if (!modes) {
+        return -EINVAL;
+    }
+
+    for (i = 0; i < mode_num; i++) {
+        struct owl_videomode *vmode;
+
+        sprintf(propname, "videomode-%d", i);
+        mode_node = of_parse_phandle(of_node, propname, 0);
+
+        vmode = &modes[i];
+        if (of_property_read_u32(mode_node, "refresh", &vmode->refresh)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("refresh = %d\n", vmode->refresh);
+
+        if (of_property_read_u32(mode_node, "xres", &vmode->xres)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("xres = %d\n", vmode->xres);
+
+        if (of_property_read_u32(mode_node, "yres", &vmode->yres)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("yres = %d\n", vmode->yres);
+
+        if (of_property_read_u32(mode_node, "pixclock", &vmode->pixclock)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("pixclock = %d\n", vmode->pixclock);
+
+        if (of_property_read_u32(mode_node, "left_margin", &vmode->left_margin)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("left_margin = %d\n", vmode->left_margin);
+
+        if (of_property_read_u32(mode_node, "right_margin", &vmode->right_margin)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("right_margin = %d\n", vmode->right_margin);
+
+        if (of_property_read_u32(mode_node, "upper_margin", &vmode->upper_margin)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("upper_margin = %d\n", vmode->upper_margin);
+
+        if (of_property_read_u32(mode_node, "lower_margin", &vmode->lower_margin)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("lower_margin = %d\n", vmode->lower_margin);
+
+        if (of_property_read_u32(mode_node, "hsync_len", &vmode->hsync_len)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("hsync_len = %d\n", vmode->hsync_len);
+
+        if (of_property_read_u32(mode_node, "vsync_len", &vmode->vsync_len)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("vsync_len = %d\n", vmode->vsync_len);
+
+        if (of_property_read_u32(mode_node, "vmode", &vmode->vmode)) {
+            ret = -EINVAL;
+            goto parse_mode_fail;
+        }
+        DSSDBG("vmode = %d\n", vmode->vmode);
+    }
+
+    lcdc->num_modes     = mode_num;
+    lcdc->modes         = modes;
+
+    return 0;
+
+parse_mode_fail:
+    kfree(modes);
+    return ret;
+}
+
+static int owl_lcdchw_probe(struct platform_device *pdev)
+{
+    int r;
+    struct resource     *lcdc_mem;
+    struct lcdc_data    *lcdc;
+
+    DSSINFO("%s\n", __func__);
+
+    lcdc = kzalloc(sizeof(*lcdc), GFP_KERNEL);
+    if (!lcdc) {
+        r = -ENOMEM;
+        goto err_alloc;
+    }
+
+    lcdc->pdev          = pdev;
+    lcdc_pdev_map[0]    = pdev;
+
+    dev_set_drvdata(&pdev->dev, lcdc);
+
+    mutex_init(&lcdc->lock);
+
+    r = lcdchw_get_clocks(pdev);
+    if (r)
+        goto err_get_clk;
+
+    pm_runtime_enable(&pdev->dev);
+
+    lcdc_mem = platform_get_resource(lcdc->pdev, IORESOURCE_MEM, 0);
+    
+    if (!lcdc_mem) {
+        DSSERR("can't get IORESOURCE_MEM DSI\n");
+        r = -EINVAL;
+        goto err_ioremap;
+    }    
+    
+    lcdc->base = ioremap(lcdc_mem->start, resource_size(lcdc_mem));
+    if (!lcdc->base) {
+        DSSERR("can't ioremap lcdc \n");
+        r = -ENOMEM;
+        goto err_ioremap;
+    }
+    DSSDBG("lcdc->base  ~~~ %p \n",lcdc->base);    
+
+    lcdchw_check_boot_lcd0_inited(pdev);
+
+    r = lcdchw_parse_params(pdev, lcdc);
+    if (r) {
+        DSSERR("%s, parse lcdc params error\n", __func__);
+        goto err_parse_params;
+    }
+
+    /*
+     * configure gpio
+     */
+    if (gpio_is_valid(lcdc->power_gpio.gpio)) {
+        r = gpio_request(lcdc->power_gpio.gpio, NULL);
+        if (r) {
+            DSSERR("%s, request power gpio failed\n", __func__);
+            goto err_parse_params;
+        }
+    } 
+    if (gpio_is_valid(lcdc->reset_gpio.gpio)) {
+        r = gpio_request(lcdc->reset_gpio.gpio, NULL);
+        if (r) {
+            DSSERR("%s, request reset_gpio failed\n", __func__);
+            goto err_parse_params;
+        }
+    } 
+    if (gpio_is_valid(lcdc->standby_gpio.gpio)) {
+        r = gpio_request(lcdc->standby_gpio.gpio, NULL);
+        if (r) {
+            DSSERR("%s, request standby_gpio failed\n", __func__);
+            goto err_parse_params;
+        }
+    } 
+	
+    lcdc->lcdc_power = regulator_get(&pdev->dev, POWER_REGULATOR_NAME);
+    if (IS_ERR(lcdc->lcdc_power)) {
+        lcdc->lcdc_power = NULL;
+    }
+    DSSDBG("%s, lcdc_power: %p\n", __func__, lcdc->lcdc_power);
+
+    lcdchw_power_init(pdev);
+
+    DSSINFO("owl_lcdchw_probe called  ok ~~~~~~~~~~~~~\n");
+    return 0;
+
+err_parse_params:
+    iounmap(lcdc->base);
+err_ioremap:
+    pm_runtime_disable(&pdev->dev);
+err_get_clk:
+    kfree(lcdc);
+err_alloc:
+    return r;
+}
+
+static int owl_lcdchw_remove(struct platform_device *pdev)
+{
+    struct lcdc_data *lcdc = lcdchw_get_lcdcdrv_data(pdev);
+
+    pm_runtime_disable(&pdev->dev);
+
+    lcdchw_put_clocks(pdev);
+
+    lcdchw_power_enable(pdev, false);
+
+    if (lcdc->lcdc_power != NULL) {
+        regulator_put(lcdc->lcdc_power);
+        lcdc->lcdc_power = NULL;
+    }
+
+    iounmap(lcdc->base);
+
+    kfree(lcdc);
+
+    lcdc->lcdc_enabled = false;
+    return 0;
+}
+
+static struct of_device_id owl_lcdchw_of_match[] = {
+    { .compatible = "actions,owl-lcd", },
+    { },
+};
+
+static struct platform_driver owl_lcdc_driver = {
+    .driver = {
+        .name           = "owl_lcdchw",
+        .owner          = THIS_MODULE,
+        .of_match_table = owl_lcdchw_of_match,
+    },
+    .probe              = owl_lcdchw_probe,
+    .remove             = owl_lcdchw_remove,
+};
+
+int owl_lcdc_init_platform(void)
+{
+    int ret = 0;
+    
+    ret = platform_driver_register(&owl_lcdc_driver);
+    
+    if (ret) {
+        DSSERR("Failed to initialize lcdc platform driver\n");
+        return ret;
+    }
+    return 0;
+}
+
+int owl_lcdc_uninit_platform(void)
+{   
+    platform_driver_unregister(&owl_lcdc_driver);
+    
+    return 0;
+}
diff --git a/drivers/video/fbdev/owl/displays/lcdc/lcdchw.h b/drivers/video/fbdev/owl/displays/lcdc/lcdchw.h
new file mode 100755
index 0000000..220e39a
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/lcdc/lcdchw.h
@@ -0,0 +1,88 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/lcdchw.h
+ *
+ * Copyright (C) 2011 Actions
+ * Author: Hui Wang <wanghui at actions-semi.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __ASOC_LCDCHW_REG_H
+#define __ASOC_LCDCHW_REG_H
+
+
+#define ATM7059A 
+
+#ifdef ATM9009A
+    #define    LCDCHW_REG_MEM_BASE                                                  0xE02A0000
+    #define    LCDCHW_REG_MEM_END                                                   0xE02A020c
+    
+    #define    LCDCHW_CTL                                                           (0x0000)
+	#define    LCDCHW_SIZE                                                          (0x0004)
+	#define    LCDCHW_STATUS                                                        (0x0008)
+	#define    LCDCHW_TIM0                                                          (0x000C)
+	#define    LCDCHW_TIM1                                                          (0x0010)
+	#define    LCDCHW_TIM2                                                          (0x0014)
+	#define    LCDCHW_COLOR                                                         (0x0018)
+	#define    LCDCHW_IMG_XPOS                                                      (0x001C)
+	#define    LCDCHW_IMG_YPOS                                                      (0x0020)
+	#define    LCDCHW_LVDS_CTL                                                      (0x0200)
+	#define    LCDCHW_LVDS_ALG_CTL0                                                 (0x0204)
+	#define    LCDCHW_LVDS_DEBUG                                                    (0x0208)
+			
+#endif
+
+
+#ifdef ATM7059A
+	#define    LCDCHW_REG_MEM_BASE                                                  0xB02A0000
+    #define    LCDCHW_REG_MEM_END                                                   0xB02A020C
+    
+    #define    LCDCHW_CTL                                                           (0x0000)
+	#define    LCDCHW_SIZE                                                          (0x0004)
+	#define    LCDCHW_STATUS                                                        (0x0008)
+	#define    LCDCHW_TIM0                                                          (0x000C)
+	#define    LCDCHW_TIM1                                                          (0x0010)
+	#define    LCDCHW_TIM2                                                          (0x0014)
+	#define    LCDCHW_COLOR                                                         (0x0018)
+	#define    LCDCHW_CPU_CTL                                                       (0x001c)
+    #define    LCDCHW_CPU_CMD                                                       (0x0020)
+	#define    LCDCHW_IMG_XPOS                                                      (0x002c)
+	#define    LCDCHW_IMG_YPOS                                                      (0x0030)
+	#define    LCDCHW_LVDS_CTL                                                      (0x0200)
+	#define    LCDCHW_LVDS_ALG_CTL0                                                 (0x0204)
+	#define    LCDCHW_LVDS_DEBUG                                                    (0x0208)
+
+#endif
+
+#ifdef ATM7039C
+	#define    LCDCHW_REG_MEM_BASE                                                  0xB02A0000
+    #define    LCDCHW_REG_MEM_END                                                   0xB02A020C
+    
+    #define    LCDCHW_CTL                                                           (0x0000)
+	#define    LCDCHW_SIZE                                                          (0x0004)
+	#define    LCDCHW_STATUS                                                        (0x0008)
+	#define    LCDCHW_TIM0                                                          (0x000C)
+	#define    LCDCHW_TIM1                                                          (0x0010)
+	#define    LCDCHW_TIM2                                                          (0x0014)
+	#define    LCDCHW_COLOR                                                         (0x0018)
+	#define    LCDCHW_CPU_CTL                                                       (0x001c)
+    #define    LCDCHW_CPU_CMD                                                       (0x0020)
+	#define    LCDCHW_IMG_XPOS                                                      (0x002c)
+	#define    LCDCHW_IMG_YPOS                                                      (0x0030)
+	#define    LCDCHW_LVDS_CTL                                                      (0x0200)
+	#define    LCDCHW_LVDS_ALG_CTL0                                                 (0x0204)
+	#define    LCDCHW_LVDS_DEBUG                                                    (0x0208)
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/owl/displays/lcdc/panel-lcd.c b/drivers/video/fbdev/owl/displays/lcdc/panel-lcd.c
new file mode 100755
index 0000000..df11408
--- /dev/null
+++ b/drivers/video/fbdev/owl/displays/lcdc/panel-lcd.c
@@ -0,0 +1,257 @@
+/*
+ * Generic LCDC Panels support
+ *
+ * Copyright (C) 2010 Canonical Ltd.
+ * Author: Bryan Wu <bryan.wu at canonical.com>
+ *
+ * LCD panel driver for Sharp LQ043T1DG01
+ *
+ * Copyright (C) 2009 Actions Inc
+ * Author: Vaibhav Hiremath <hvaibhav at ti.com>
+ *
+ * LCD panel driver for Toppoly TDO35S
+ *
+ * Copyright (C) 2009 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike at compulab.co.il>
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <video/owldss.h>
+
+struct panel_config {
+	struct owl_video_timings timings;
+
+	//enum owl_panel_config config;
+
+	int power_on_delay;
+	
+	int power_off_delay;
+
+	/*
+	 * Used to match device to panel configuration
+	 * when use generic panel driver
+	 */
+	const char *name;
+
+	int (*platform_enable)(struct owl_dss_device *dssdev);
+	
+	void (*platform_disable)(struct owl_dss_device *dssdev);
+};
+
+/* Panel configurations */
+static struct panel_config generic_lcdc_panels[] = {
+	/* rgb/lvds lcd  */
+	{
+		//.config			= OWL_DSS_LCD_TFT,
+		.power_on_delay		= 0,
+		.power_off_delay	= 0,
+		.name			= "lcd",
+	},	
+};
+
+struct panel_drv_data {
+
+	struct owl_dss_device *dssdev;
+
+	struct panel_config *panel_config;
+};
+
+extern enum owl_display_type get_current_display_type(void);
+
+static int generic_lcdc_panel_power_on(struct owl_dss_device *dssdev)
+{
+	int r;
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE)
+		return 0;
+
+	r = owl_lcdc_display_enable(dssdev);
+	
+	if (r)
+		goto err0;
+
+	/* wait couple of vsyncs until enabling the LCD */
+	if (panel_config->power_on_delay)
+		msleep(panel_config->power_on_delay);
+
+	if (panel_config->platform_enable) {
+		r = panel_config->platform_enable(dssdev);
+		if (r)
+			goto err1;
+	}
+
+	return 0;
+err1:
+	owl_lcdc_display_disable(dssdev);
+err0:
+	return r;
+}
+
+static void generic_lcdc_panel_power_off(struct owl_dss_device *dssdev)
+{
+
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+	struct panel_config *panel_config = drv_data->panel_config;
+
+	if (dssdev->state != OWL_DSS_DISPLAY_ACTIVE)
+		return;
+
+	if (panel_config->platform_disable)
+		panel_config->platform_disable(dssdev);
+
+	/* wait couple of vsyncs after disabling the LCD */
+	if (panel_config->power_off_delay)
+		msleep(panel_config->power_off_delay);
+
+	owl_lcdc_display_disable(dssdev);
+}
+
+static int generic_lcdc_panel_probe(struct owl_dss_device *dssdev)
+{
+
+	struct panel_config *panel_config = NULL;
+	struct panel_drv_data *drv_data = NULL;
+
+	dev_dbg(&dssdev->dev, "probe\n");
+
+	panel_config = &generic_lcdc_panels[0];
+    
+	if (!panel_config)
+		return -EINVAL;
+
+	/* temp in here, TODO */
+	owl_lcdc_select_video_timings(dssdev, 0, &panel_config->timings);
+
+	dssdev->timings = panel_config->timings;
+
+	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
+	if (!drv_data)
+		return -ENOMEM;
+
+	drv_data->dssdev = dssdev;
+	drv_data->panel_config = panel_config;
+
+	dev_set_drvdata(&dssdev->dev, drv_data);
+
+	return 0;
+}
+
+static void __exit generic_lcdc_panel_remove(struct owl_dss_device *dssdev)
+{
+	struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev);
+
+	dev_dbg(&dssdev->dev, "remove\n");
+
+	kfree(drv_data);
+
+	dev_set_drvdata(&dssdev->dev, NULL);
+}
+
+extern void owl_backlight_set_onoff(int onoff);
+
+static int generic_lcdc_panel_enable(struct owl_dss_device *dssdev)
+{
+	int r = 0;
+
+	r = generic_lcdc_panel_power_on(dssdev);
+	if (r)
+		return r;
+
+	dssdev->state = OWL_DSS_DISPLAY_ACTIVE;
+
+	/* at last enable backlight */
+	owl_backlight_set_onoff(1);
+
+	return 0;
+}
+
+static void generic_lcdc_panel_disable(struct owl_dss_device *dssdev)
+{
+    /* disable backlight first */
+    owl_backlight_set_onoff(0);
+
+	generic_lcdc_panel_power_off(dssdev);
+
+	dssdev->state = OWL_DSS_DISPLAY_DISABLED;
+}
+
+static int generic_lcdc_panel_dump(struct owl_dss_device *dssdev)
+{
+	owl_lcdc_display_dump();
+
+    return 0;
+}
+
+static void generic_lcdc_panel_get_timings(struct owl_dss_device *dssdev,
+                                           struct owl_video_timings *timings)
+{
+	*timings = dssdev->timings;
+}
+
+static int generic_lcdc_panel_get_effect_parameter(struct owl_dss_device *dssdev,
+                                              enum owl_plane_effect_parameter parameter_id)
+{
+	return owl_lcdc_get_effect_parameter(dssdev, parameter_id);
+}
+
+static void generic_lcdc_panel_set_effect_parameter(struct owl_dss_device *dssdev,
+                                           enum owl_plane_effect_parameter parameter_id ,int value)
+{
+	owl_lcdc_set_effect_parameter(dssdev, parameter_id,value);
+}
+static struct owl_dss_driver lcdc_driver = {
+	.probe		= generic_lcdc_panel_probe,
+	.remove		= __exit_p(generic_lcdc_panel_remove),
+
+	.enable		= generic_lcdc_panel_enable,
+	.disable	= generic_lcdc_panel_disable,
+	.get_timings	= generic_lcdc_panel_get_timings,
+	.get_effect_parameter   = generic_lcdc_panel_get_effect_parameter,
+	.set_effect_parameter   = generic_lcdc_panel_set_effect_parameter,
+	.dump       = generic_lcdc_panel_dump,
+
+	.driver         = {
+		.name   = "generic_lcdc_panel",
+		.owner  = THIS_MODULE,
+	},
+};
+
+static int __init generic_lcdc_panel_drv_init(void)
+{
+	owl_lcdc_init_platform();
+	if(get_current_display_type()==OWL_DISPLAY_TYPE_LCD){
+		printk("current type lcd \n");
+		owl_dss_register_driver(&lcdc_driver);
+	}
+	return 0;
+}
+
+static void __exit generic_lcdc_panel_drv_exit(void)
+{
+	owl_dss_unregister_driver(&lcdc_driver);
+	owl_lcdc_uninit_platform();
+}
+
+module_init(generic_lcdc_panel_drv_init);
+module_exit(generic_lcdc_panel_drv_exit);
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/dss/Kconfig b/drivers/video/fbdev/owl/dss/Kconfig
new file mode 100755
index 0000000..a8fea95
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/Kconfig
@@ -0,0 +1,45 @@
+config VIDEO_OWL_DSS
+	tristate "OWL Display Subsystem support"
+	---help---
+	  Actions OWL Soc Display Subsystem support.
+
+	  Say Y here if you need it in your system.
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
+
+config VIDEO_OWL_DE_ATM7059
+	bool "ATM7059 Display Engine"
+	depends on VIDEO_OWL_DSS
+	---help---
+	  Say Y here if you need support ATM7059 DE.
+
+	  If unsure, say Y.
+
+config VIDEO_OWL_DE_ATM9009
+	bool "ATM9009 Display Engine"
+	depends on VIDEO_OWL_DSS
+	---help---
+	  Say Y here if you need support ATM9009 DE.
+
+	  If unsure, say Y.
+
+config VIDEO_OWL_MMU_SUPPORT
+	bool "OWL DE MMU Support"
+	depends on VIDEO_OWL_DE_ATM9009 || VIDEO_OWL_DE_ATM7059
+	---help---
+	  Actions OWL Soc Display Engine MMU support.
+
+	  Say Y here if you need MMU function.
+
+	  If unsure, say Y.
+
+config VIDEO_OWL_MMU_ION_SUPPORT
+	bool "OWL DE MMU ION Support"
+	depends on VIDEO_OWL_MMU_SUPPORT
+	---help---
+	  Actions OWL Soc Display Engine MMU ION support
+
+	  Say Y here if you need MMU ION function.
+
+	  If unsure, say Y.
diff --git a/drivers/video/fbdev/owl/dss/Makefile b/drivers/video/fbdev/owl/dss/Makefile
new file mode 100755
index 0000000..2176b4e
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/Makefile
@@ -0,0 +1,8 @@
+obj-$(CONFIG_VIDEO_OWL_DSS) += owl_dss.o
+
+# Core DSS files
+owl_dss-y := core.o display.o dss_features.o de.o manager.o overlay.o
+owl_dss-$(CONFIG_VIDEO_OWL_MMU_SUPPORT) += mmu.o
+
+owl_dss-$(CONFIG_VIDEO_OWL_DE_ATM7059) += de_atm7059.o
+
diff --git a/drivers/video/fbdev/owl/dss/core.c b/drivers/video/fbdev/owl/dss/core.c
new file mode 100755
index 0000000..4c41e18
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/core.c
@@ -0,0 +1,681 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/core.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "CORE"
+#include <mach/bootdev.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/seq_file.h>
+#include <linux/debugfs.h>
+#include <linux/io.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/suspend.h>
+#include <linux/earlysuspend.h>
+
+#include <video/owldss.h>
+
+#include <mach/powergate.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "de.h"
+
+struct {
+	struct platform_device *pdev;
+} core;
+
+/* Board specific data */
+struct owl_dss_board_info {
+	int num_devices;
+	struct owl_dss_device **devices;
+};
+
+#ifdef DSS_DEBUG_ENABLE
+/* 0, error; 1, error+info; 2, error+info+debug */
+int owl_dss_debug = 1;
+module_param_named(debug, owl_dss_debug, int, 0644);
+#endif
+
+#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OWL_DSS_DEBUG_SUPPORT)
+static int dss_debug_show(struct seq_file *s, void *unused)
+{
+	void (*func)(struct seq_file *) = s->private;
+	func(s);
+	return 0;
+}
+
+static int dss_debug_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, dss_debug_show, inode->i_private);
+}
+
+static const struct file_operations dss_debug_fops = {
+	.open           = dss_debug_open,
+	.read           = seq_read,
+	.llseek         = seq_lseek,
+	.release        = single_release,
+};
+
+static struct dentry *dss_debugfs_dir;
+
+static int dss_initialize_debugfs(void)
+{
+	dss_debugfs_dir = debugfs_create_dir("owldss", NULL);
+	if (IS_ERR(dss_debugfs_dir)) {
+		int err = PTR_ERR(dss_debugfs_dir);
+		dss_debugfs_dir = NULL;
+		return err;
+	}
+
+	debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
+			&dss_debug_dump_clocks, &dss_debug_fops);
+
+#ifdef CONFIG_OWL2_DSS_COLLECT_IRQ_STATS
+	debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
+			&dispc_dump_irqs, &dss_debug_fops);
+#endif
+
+#if defined(CONFIG_OWL2_DSS_LCDC) && defined(CONFIG_OWL2_DSS_COLLECT_IRQ_STATS)
+	lcdc_create_debugfs_files_irq(dss_debugfs_dir, &dss_debug_fops);
+#endif
+
+	debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
+			&dss_dump_regs, &dss_debug_fops);
+	debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
+			&dispc_dump_regs, &dss_debug_fops);
+
+#ifdef CONFIG_OWL2_DSS_DSI
+	dsi_create_debugfs_files_reg(dss_debugfs_dir, &dss_debug_fops);
+#endif
+
+#ifdef CONFIG_OWL4_DSS_HDMI
+	debugfs_create_file("hdmi", S_IRUGO, dss_debugfs_dir,
+			&hdmi_dump_regs, &dss_debug_fops);
+#endif
+	return 0;
+}
+
+static void dss_uninitialize_debugfs(void)
+{
+	if (dss_debugfs_dir)
+		debugfs_remove_recursive(dss_debugfs_dir);
+}
+#else /* CONFIG_DEBUG_FS && CONFIG_OWL_DSS_DEBUG_SUPPORT */
+static int dss_initialize_debugfs(void)
+{
+	return 0;
+}
+static void dss_uninitialize_debugfs(void)
+{
+}
+#endif /* CONFIG_DEBUG_FS && CONFIG_OWL_DSS_DEBUG_SUPPORT */
+
+
+/*=================================================================
+ *              display subsystem bus and its operations
+ *===============================================================*/
+
+static void dss_bus_release(struct device *dev)
+{
+	DSSDBG("bus_release\n");
+}
+
+/* 
+ * dss bus device
+ */
+static struct device dss_bus = {
+	.release = dss_bus_release,
+};
+
+/* 
+ * dss bus
+ */
+static int dss_bus_match(struct device *dev, struct device_driver *driver)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+
+	DSSDBG("bus_match. dev %s/%s, drv %s\n",
+			dev_name(dev), dssdev->driver_name, driver->name);
+
+	return strcmp(dssdev->driver_name, driver->name) == 0;
+}
+
+static ssize_t device_name_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			dssdev->name ?
+			dssdev->name : "");
+}
+
+static DEVICE_ATTR(dss_dev, S_IRUGO, device_name_show, NULL);
+
+static struct attribute *dss_dev_attrs[] = {
+	&dev_attr_dss_dev.attr,
+	NULL
+};
+
+static struct attribute_group dss_dev_attr_group = {
+	.attrs	= dss_dev_attrs,
+};
+
+static const struct attribute_group *dss_dev_attr_groups[] = {
+	&dss_dev_attr_group,
+	NULL
+};
+
+static ssize_t driver_name_show(struct device_driver *drv, char *buf)
+{
+	struct owl_dss_driver *dssdrv = to_dss_driver(drv);
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			dssdrv->driver.name ?
+			dssdrv->driver.name : "");
+}
+
+static DRIVER_ATTR(dss_drv, S_IRUSR | S_IWUSR, driver_name_show, NULL);
+
+static struct attribute *dss_drv_attrs[] = {
+	&driver_attr_dss_drv.attr,
+	NULL
+};
+
+static struct attribute_group dss_drv_attr_group = {
+	.attrs	= dss_drv_attrs,
+};
+
+static const struct attribute_group *dss_drv_attr_groups[] = {
+	&dss_drv_attr_group,
+	NULL
+};
+
+static struct bus_type dss_bus_type = {
+	.name = "owldss",
+	.match = dss_bus_match,
+	.dev_groups = dss_dev_attr_groups,
+	.drv_groups = dss_drv_attr_groups,
+};
+
+
+/* register bus and its device */
+static int owl_dss_bus_register(void)
+{
+	int r;
+
+	r = bus_register(&dss_bus_type);
+	if (r) {
+		DSSERR("bus register failed\n");
+		return r;
+	}
+
+	dev_set_name(&dss_bus, "owldss");
+	r = device_register(&dss_bus);
+	if (r) {
+		DSSERR("bus driver register failed\n");
+		bus_unregister(&dss_bus_type);
+		return r;
+	}
+
+	return 0;
+}
+
+/* unregister bus and its device */
+static void owl_dss_bus_unregister(void)
+{
+	device_unregister(&dss_bus);
+
+	bus_unregister(&dss_bus_type);
+}
+
+/*
+ * bus operations to others
+ */
+
+struct bus_type *dss_get_bus(void)
+{
+	return &dss_bus_type;
+}
+
+static int dss_driver_probe(struct device *dev)
+{
+	int r;
+	struct owl_dss_driver *dssdrv = to_dss_driver(dev->driver);
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+
+	DSSDBG("driver_probe: dev %s/%s, drv %s\n",
+				dev_name(dev), dssdev->driver_name,
+				dssdrv->driver.name);
+
+  	if (owl_get_boot_mode() == OWL_BOOT_MODE_UPGRADE) {
+		printk("product process  not need to dss modules!\n");
+		return -ENODEV;
+	}
+	
+	dss_init_device(core.pdev, dssdev);
+	
+	r = dssdrv->probe(dssdev);
+
+	if (r) {
+		DSSERR("driver probe failed: %d\n", r);
+		dss_uninit_device(core.pdev, dssdev);
+		return r;
+	}
+
+	DSSDBG("probe done for device %s\n", dev_name(dev));
+
+	dssdev->driver = dssdrv;
+
+	return 0;
+}
+
+static int dss_driver_remove(struct device *dev)
+{
+	struct owl_dss_driver *dssdrv = to_dss_driver(dev->driver);
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+
+	DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
+			dssdev->driver_name);
+
+	dssdrv->remove(dssdev);
+
+	dss_uninit_device(core.pdev, dssdev);
+
+	dssdev->driver = NULL;
+
+	return 0;
+}
+
+/* register dss driver to dss bus */
+int owl_dss_register_driver(struct owl_dss_driver *dssdriver)
+{
+	dssdriver->driver.bus = &dss_bus_type;
+	dssdriver->driver.probe = dss_driver_probe;
+	dssdriver->driver.remove = dss_driver_remove;
+
+	if (dssdriver->get_resolution == NULL)
+		dssdriver->get_resolution = owl_default_get_resolution;
+	if (dssdriver->get_recommended_bpp == NULL)
+		dssdriver->get_recommended_bpp =
+			owl_default_get_recommended_bpp;
+
+	return driver_register(&dssdriver->driver);
+}
+EXPORT_SYMBOL(owl_dss_register_driver);
+
+/* unregister dss driver from dss bus */
+void owl_dss_unregister_driver(struct owl_dss_driver *dssdriver)
+{
+	driver_unregister(&dssdriver->driver);
+}
+EXPORT_SYMBOL(owl_dss_unregister_driver);
+
+/* DEVICE */
+static void reset_device(struct device *dev, int check)
+{
+	u8 *dev_p = (u8 *)dev;
+	u8 *dev_end = dev_p + sizeof(*dev);
+	void *saved_pdata;
+
+	saved_pdata = dev->platform_data;
+	if (check) {
+		/*
+		 * Check if there is any other setting than platform_data
+		 * in struct device; warn that these will be reset by our
+		 * init.
+		 */
+		dev->platform_data = NULL;
+		while (dev_p < dev_end) {
+			if (*dev_p) {
+				WARN("%s: struct device fields will be "
+						"discarded\n",
+				     __func__);
+				break;
+			}
+			dev_p++;
+		}
+	}
+	memset(dev, 0, sizeof(*dev));
+	dev->platform_data = saved_pdata;
+}
+
+static void owl_dss_dev_release(struct device *dev)
+{
+	reset_device(dev, 0);
+}
+
+/* register dss deivce to dss bus */
+int owl_dss_register_device(struct owl_dss_device *dssdev)
+{
+	static int dev_num;
+
+	WARN_ON(!dssdev->driver_name);
+
+	reset_device(&dssdev->dev, 1);
+	dssdev->dev.bus = &dss_bus_type;
+	dssdev->dev.parent = &dss_bus;
+	dssdev->dev.release = owl_dss_dev_release;
+	dev_set_name(&dssdev->dev, "display%d", dev_num++);
+	return device_register(&dssdev->dev);
+}
+
+/* unregister dss deivce from dss bus */
+void owl_dss_unregister_device(struct owl_dss_device *dssdev)
+{
+	device_unregister(&dssdev->dev);
+}
+
+/*=================================================================
+ *       platform device & driver for display subsystem
+ *===============================================================*/
+static int __init owl_dss_probe(struct platform_device *pdev)
+{
+	struct owl_dss_board_info *pdata = pdev->dev.platform_data;
+	int r;
+	int i;
+
+	core.pdev = pdev;
+
+	DSSDBG("dss_features_init called \n");
+	dss_features_init();
+
+	DSSDBG("dss_init_overlay_managers called \n");
+	dss_init_overlay_managers(pdev);
+
+	DSSDBG("dss_init_overlays called \n");
+	dss_init_overlays(pdev);
+	
+	DSSDBG("dss_initialize_debugfs called \n");
+	r = dss_initialize_debugfs();
+	if (r)
+		goto err_debugfs;
+
+	/*
+	 * enable DS power gate if need,
+	 * because powergate will maintain a count for every power,
+	 * so we must check if DS power is enabled in U-BOOT,
+	 * it will ensure DS power on count 1 after booting
+	 *
+	 * should not care about the return value,
+	 * powergate is self-adation for different platform
+	 */
+	if (owl_powergate_is_powered(OWL_POWERGATE_DS) <= 0) {
+		DSSDBG("DS powergate on called\n");
+		owl_powergate_power_on(OWL_POWERGATE_DS);
+	}
+
+	DSSDBG("de_init called\n");
+	if (r) {
+		goto err_de;
+	}
+
+	DSSDBG("owl_dss_register_device called \n");
+	for (i = 0; i < pdata->num_devices; ++i) {
+		struct owl_dss_device *dssdev = pdata->devices[i];
+
+		r = owl_dss_register_device(dssdev);
+		if (r) {
+			DSSERR("device %d %s register failed %d\n", i,
+				dssdev->name ?: "unnamed", r);
+
+			while (--i >= 0)
+				owl_dss_unregister_device(pdata->devices[i]);
+
+			goto err_register;
+		}
+	}
+
+	return 0;
+
+err_register:
+	owl_de_exit();
+
+err_de:
+	owl_powergate_power_off(OWL_POWERGATE_DS);
+
+	dss_uninitialize_debugfs();
+
+err_debugfs:
+	return r;
+}
+
+static int owl_dss_remove(struct platform_device *pdev)
+{
+	struct owl_dss_board_info *pdata = pdev->dev.platform_data;
+	int i;
+
+	for (i = 0; i < pdata->num_devices; ++i)
+		owl_dss_unregister_device(pdata->devices[i]);
+
+	owl_de_exit();
+
+	owl_powergate_power_off(OWL_POWERGATE_DS);
+
+	dss_uninitialize_debugfs();
+	
+	dss_uninit_overlays(pdev);
+	dss_uninit_overlay_managers(pdev);
+
+	return 0;
+}
+
+atomic_t devices_suspended_from_early_suspend = ATOMIC_INIT(false);
+
+#ifdef CONFIG_EARLYSUSPEND
+static void owl_dss_early_suspend(struct early_suspend *h)
+{
+	if(!owl_dss_is_devices_suspended())
+	{
+		DSSINFO("early suspending displays \n");
+		dss_suspend_all_devices();
+		atomic_set(&devices_suspended_from_early_suspend,true);
+		DSSINFO("early suspending displays end\n");
+	}
+
+}
+static void owl_dss_late_resume(struct early_suspend *h)
+{
+	
+	
+	if(owl_dss_is_devices_suspended())
+	{
+		DSSINFO("late resuming displays \n");	
+		dss_resume_all_devices();
+		atomic_set(&devices_suspended_from_early_suspend,false);
+		DSSINFO("late resuming displays end \n");
+	}
+}
+
+static struct early_suspend owl_dss_early_suspend_desc = {
+	.suspend = owl_dss_early_suspend,
+	.resume  = owl_dss_late_resume,
+};
+#endif
+
+#ifdef CONFIG_PM
+static int owl_dss_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	DSSINFO("suspending dss \n");
+	
+	if(!owl_dss_is_devices_suspended())
+	{
+		DSSINFO("suspending displays \n");
+		dss_suspend_all_devices();
+		DSSINFO("suspending displays end\n");
+	}
+	
+	owl_de_suspend();
+	
+	DSSINFO("suspending dss end\n");
+	
+	return 0;
+}
+
+static int owl_dss_resume(struct platform_device *pdev)
+{
+	DSSINFO("resuming dss \n");
+
+	/*
+	 * should not care about the return value,
+	 * powergate is self-adation for different platform
+	 */
+
+	owl_de_resume();
+
+	if(owl_dss_is_devices_suspended() && !atomic_read(&devices_suspended_from_early_suspend))
+	{
+		DSSINFO("resuming displays \n");
+		dss_resume_all_devices();
+		DSSINFO("resuming displays end \n");
+	}
+	DSSINFO("resuming dss  end\n");
+
+	return 0;
+}
+#else
+#define owl_dss_suspend    NULL
+#define owl_dss_resume     NULL
+#endif
+
+static void owl_dss_shutdown(struct platform_device *pdev)
+{
+	DSSDBG("shutdown\n");
+	dss_disable_all_devices();
+}
+
+static struct owl_dss_device asoc_lcd_device = {
+	.name			= "lcd",
+	.driver_name		= "generic_lcdc_panel",
+	.type			= OWL_DISPLAY_TYPE_LCD,
+	.data_lines	= 24,
+};
+static struct owl_dss_device asoc_edp_device = {
+	.name			= "edp",
+	.driver_name		= "generic_edp_panel",
+	.type			= OWL_DISPLAY_TYPE_EDP,
+	.data_lines	= 24,
+};
+
+static struct owl_dss_device asoc_dsi_device = {
+	.name			= "dsi",
+	.driver_name		= "generic_dsi_panel",
+	.type			= OWL_DISPLAY_TYPE_DSI,
+	.data_lines	= 24,
+};
+static struct owl_dss_device asoc_hdmi_device = {
+	.name			= "hdmi",
+	.driver_name		= "hdmi_panel",
+	.type			= OWL_DISPLAY_TYPE_HDMI,
+	.data_lines	= 16,
+};
+
+static struct owl_dss_device asoc_cvbs_device = {
+	.name			= "cvbs",
+	.driver_name		= "cvbs_panel",
+	.type			= OWL_DISPLAY_TYPE_CVBS,
+	.data_lines	= 16,
+};
+
+static struct owl_dss_device *owl_dss_devices[] = {
+	&asoc_lcd_device,
+	&asoc_dsi_device,
+	&asoc_edp_device,
+	&asoc_hdmi_device,
+	&asoc_cvbs_device,
+};
+
+static struct owl_dss_board_info owl_dss_data = {
+	.num_devices	= ARRAY_SIZE(owl_dss_devices),
+	.devices	= owl_dss_devices,
+};
+
+static struct platform_device owl_dss_device = {
+	.name          = "owldss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = &owl_dss_data,
+	},
+};
+
+static struct platform_driver owl_dss_driver = {
+	.remove         = owl_dss_remove,
+	.shutdown	= owl_dss_shutdown,
+	.suspend	= owl_dss_suspend,
+	.resume		= owl_dss_resume,
+	.driver         = {
+		.name   = "owldss",
+		.owner  = THIS_MODULE,
+	},
+};
+
+
+/*=================================================================
+ *       the entry and exit of display subsystem
+ *===============================================================*/
+static int __init owl_dss_init(void)
+{
+	int r;
+
+	r = owl_dss_bus_register();
+	if (r)
+		return r;
+	
+	r = platform_device_register(&owl_dss_device);
+	
+	if (r) {
+		owl_dss_bus_unregister();
+		return r;
+	}	
+
+	r = platform_driver_probe(&owl_dss_driver, owl_dss_probe);
+	if (r) {
+		owl_dss_bus_unregister();
+		platform_device_unregister(&owl_dss_device);
+		return r;
+	}	
+#ifdef CONFIG_EARLYSUSPEND
+	register_early_suspend(&owl_dss_early_suspend_desc);
+#endif
+	return 0;
+}
+
+static void owl_dss_exit(void)
+{
+	
+	platform_driver_unregister(&owl_dss_driver);
+	
+	platform_device_unregister(&owl_dss_device);
+	
+	owl_de_exit();
+	
+	owl_dss_bus_unregister();
+}
+
+module_init(owl_dss_init);
+module_exit(owl_dss_exit);
+
+MODULE_AUTHOR("Hui Wang  <wanghui at actions-semi.com>");
+MODULE_DESCRIPTION("OWL Display Subsystem");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/owl/dss/de.c b/drivers/video/fbdev/owl/dss/de.c
new file mode 100755
index 0000000..5afe3a61
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/de.c
@@ -0,0 +1,1004 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/de.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Lipeng  <lipeng at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#define DSS_SUBSYS_NAME "DE"
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/of_device.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+
+#include <mach/clkname.h>
+#include <mach/module-owl.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "de.h"
+
+
+/* some convenient pointers */
+static struct owl_de_pdata		*de_pdata = NULL;
+static const struct owl_de_hwops	*de_ops = NULL;
+
+static bool 				de_boot_inited = false;
+
+/*===================={ internal interfaces======================*/
+
+bool de_channel_check_boot_inited(enum owl_de_path_id path)
+{
+	return de_ops->path_is_enabled(path);
+}
+
+/*****************TODO*********************/
+#define DECLK1_MAX		300000000
+#define DECLK2_MAX		150000000
+#define DECLK_TARGET		300000000
+
+static void de_clk_init(void)
+{
+	struct clk      *parent_clk;
+	struct clk      *de1_clk;
+	struct clk      *de2_clk;
+	struct clk      *nic_clk;
+
+	unsigned long   parent_rate;
+	unsigned long   declk1_rate;
+	unsigned long   declk2_rate;
+	unsigned long   nic_rate;
+
+	/* CLKNAME_DEVPLL is used, TODO(CLKNAME_DISPLAYPLL) */
+	parent_clk  = clk_get(NULL, CLKNAME_DEVPLL);
+	parent_rate = clk_get_rate(parent_clk);
+	DSSINFO("de parent pll is %ldhz\n", parent_rate);
+
+	nic_clk     = clk_get(NULL, CLKNAME_NIC_CLK);
+	nic_rate    = clk_get_rate(nic_clk);
+
+	de1_clk     = clk_get(NULL, CLKNAME_DE1_CLK);
+	clk_set_parent(de1_clk, parent_clk);
+
+	de2_clk     = clk_get(NULL, CLKNAME_DE2_CLK);
+	clk_set_parent(de2_clk, parent_clk);
+
+#ifdef DECLK_TARGET
+	if (nic_rate < DECLK_TARGET) {
+		printk(KERN_ERR "DE clk > nic clk!!\n");
+		printk(KERN_ERR "DE clk target %dhz\n", DECLK_TARGET);
+		printk(KERN_ERR "nic clk %lu\n", nic_rate);
+	}
+	declk1_rate = DECLK_TARGET;
+#else
+	/*de clk1 will be a little lower than nic clk*/
+	if (nic_rate > DECLK1_MAX) {
+		declk1_rate = DECLK1_MAX;
+	} else {
+		declk1_rate = nic_rate - 1;
+	}
+#endif
+
+	/* de clk2 will not be higher than de clk1*/
+	declk1_rate = clk_round_rate(de1_clk, declk1_rate);
+	if (declk1_rate > DECLK2_MAX) {
+		declk2_rate = DECLK2_MAX;
+	} else {
+		declk2_rate = declk1_rate;
+	}
+
+	clk_set_rate(de1_clk, declk1_rate);
+	clk_set_rate(de2_clk, declk2_rate);
+
+	clk_prepare(parent_clk);
+	clk_enable(parent_clk);
+
+	clk_prepare(de1_clk);
+	clk_enable(de1_clk);
+
+	clk_prepare(de2_clk);
+	clk_enable(de2_clk);
+
+	module_clk_enable(MODULE_CLK_DE);
+}
+
+#if 0
+static void de_clk_deinit(void)
+{
+	/* TODO */
+}
+#endif
+
+static inline void de_clk_enable(void)
+{
+	module_clk_enable(MODULE_CLK_DE);
+}
+
+static inline void de_clk_disable(void)
+{
+	DSSINFO("%s\n", __func__);
+	module_clk_disable(MODULE_CLK_DE);
+}
+
+static inline void de_clk_reset(void)
+{
+    DSSDBG("##DE RESET DE!!!######\n");
+    module_reset(MODULE_RST_DE);
+}
+
+static void de_set_irqs(void)
+{
+	int 			i;
+	u32 			mask, old_mask, enable;
+	struct de_isr_data	*isr_data;
+	
+	mask = 0;
+
+	for (i = 0; i < DE_MAX_NR_ISRS; i++) {
+		isr_data = &de_pdata->registered_isr[i];
+
+		if (isr_data->isr == NULL) {
+			continue;
+		}
+
+		mask |= isr_data->mask;
+	}
+
+	old_mask = de_ops->irq_status_get();
+
+	/* clear the irqstatus for newly enabled irqs */
+	de_ops->irq_status_set((mask ^ old_mask) & mask);
+
+	de_pdata->irq_mask = mask;
+	enable = de_ops->irq_mask_to_enable(mask);
+
+	de_ops->irq_enable_set(enable);
+}
+
+static irqreturn_t de_irq_handler(int irq, void *dev)
+{
+	int			i;
+	u32 			irqstatus, vb_mask, masks, val;
+	u32 			handledirqs = 0;
+	u32 			unhandled_errors;
+	struct de_isr_data 	*isr_data;
+	struct de_isr_data 	registered_isr[DE_MAX_NR_ISRS];
+	
+	irqstatus = de_ops->irq_status_get();
+	
+	//printk("de_irq_handler irqstatus 0x%x \n",irqstatus);
+
+	spin_lock(&de_pdata->irq_lock);
+
+	masks = de_pdata->irq_mask;
+
+	/* IRQ is not for us */
+	if (!(irqstatus & masks)) {
+		spin_unlock(&de_pdata->irq_lock);
+		return IRQ_NONE;
+	}
+
+	/* make a copy and unlock, so that isrs can unregister themselves */
+	memcpy(registered_isr, de_pdata->registered_isr, sizeof(registered_isr));
+	
+
+	spin_unlock(&de_pdata->irq_lock);
+
+
+	/* 
+	 * Ack the interrupt. Do it here before clocks are possibly turned off.
+	 * NOTE: do not clear VB bits
+	 */
+	de_ops->irq_status_set(masks & irqstatus);
+	/* flush posted write */
+	de_ops->irq_status_get();
+	
+	/* wait for VB according to PRELINE irq status */
+	vb_mask = de_ops->irq_mask_to_vb_mask(masks & irqstatus);
+
+	i = 100;
+	while (i--) {
+		val = de_ops->irq_status_get() & vb_mask;
+		if (val == vb_mask) {
+			break;
+		}
+		udelay(5);
+	};
+	de_pdata->vb_timeout_cnt += (val != vb_mask);
+
+	/* handling preline irq */
+	for (i = 0; i < DE_MAX_NR_ISRS; i++) {
+		isr_data = &registered_isr[i];
+
+		if (!isr_data->isr) {
+			continue;
+		}
+
+		if (isr_data->mask & irqstatus) {
+		    isr_data->isr(isr_data->irq, isr_data->arg);
+		    handledirqs |= isr_data->mask;
+		}
+	}
+
+
+	unhandled_errors = irqstatus & masks & ~handledirqs;
+	if (unhandled_errors) {
+		DSSINFO("unhandled irq errors: %x\n", unhandled_errors);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int de_irq_init(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&de_pdata->irq_lock, flags);
+
+	memset(de_pdata->registered_isr, 0, sizeof(de_pdata->registered_isr));
+	
+	de_set_irqs();
+	
+	/* TODO */
+	if (request_irq(OWL_IRQ_DE, de_irq_handler , 0, "asoc_de", NULL) != 0) {
+		DSSERR("DE request interrupt %d failed\n", OWL_IRQ_DE);
+		return -EBUSY;
+	}
+	de_pdata->irq = OWL_IRQ_DE;
+
+	DSSINFO("de irq init ok\n");
+	spin_unlock_irqrestore(&de_pdata->irq_lock, flags);
+
+	return 0;
+}
+
+static void de_irq_deinit(void)
+{
+	free_irq(de_pdata->irq, de_pdata->pdev);
+}
+
+
+
+/*===================internal interfaces end }===================*/
+
+/*==================={ external interfaces=======================*/
+int owl_de_register_isr(enum de_irq_type irq, owl_de_isr_t isr, void *arg)
+{
+	int 			i, ret;
+	unsigned long 		flags;
+	struct de_isr_data 	*isr_data;
+
+	/* convert irq to mask */
+	u32			mask = de_ops->irq_to_mask(irq);
+
+	if (isr == NULL) {
+		return -EINVAL;
+	}
+
+	spin_lock_irqsave(&de_pdata->irq_lock, flags);
+
+	/* check for duplicate entry */
+	for (i = 0; i < DE_MAX_NR_ISRS; i++) {
+		isr_data = &de_pdata->registered_isr[i];
+		if (isr_data->irq == irq && isr_data->isr == isr
+			&& isr_data->arg == arg) {
+			ret = -EINVAL;
+			goto err;
+		}
+	}
+
+	isr_data = NULL;
+	ret = -EBUSY;
+
+	for (i = 0; i < DE_MAX_NR_ISRS; i++) {
+		isr_data = &de_pdata->registered_isr[i];
+
+		if (isr_data->isr != NULL) {
+			continue;
+		}
+
+		isr_data->irq = irq;
+		isr_data->isr = isr;
+		isr_data->arg = arg;
+		isr_data->mask = mask;
+		ret = 0;
+
+		break;
+	}
+
+	if (ret) {
+		goto err;
+	}
+
+	de_set_irqs();
+
+	spin_unlock_irqrestore(&de_pdata->irq_lock, flags);
+
+	return 0;
+err:
+	spin_unlock_irqrestore(&de_pdata->irq_lock, flags);
+
+	return 0;
+}
+
+int owl_de_unregister_isr(enum de_irq_type irq, owl_de_isr_t isr, void *arg)
+{
+	int 			i;
+	unsigned long 		flags;
+	int			ret = -EINVAL;
+	struct de_isr_data	*isr_data;
+
+	spin_lock_irqsave(&de_pdata->irq_lock, flags);
+
+	for (i = 0; i < DE_MAX_NR_ISRS; i++) {
+		isr_data = &de_pdata->registered_isr[i];
+		if (isr_data->irq != irq || isr_data->isr != isr
+			|| isr_data->arg != arg) {
+			continue;
+		}
+
+		/* found the correct isr */
+		isr_data->irq = DE_IRQ_MAX;
+		isr_data->isr = NULL;
+		isr_data->arg = NULL;
+		isr_data->mask = 0;
+
+		ret = 0;
+		break;
+	}
+
+	if (ret == 0) {
+		de_set_irqs();
+	}
+
+	spin_unlock_irqrestore(&de_pdata->irq_lock, flags);
+
+	return 0;
+}
+
+enum de_irq_type de_mgr_get_vsync_irq(enum owl_display_type type){
+	switch(type){
+		case OWL_DISPLAY_TYPE_LCD:
+			return DE_IRQ_LCD_PRE;
+		case OWL_DISPLAY_TYPE_DSI:
+			return DE_IRQ_DSI_PRE;
+		case OWL_DISPLAY_TYPE_HDMI:
+			return DE_IRQ_HDMI_PRE;
+		case	OWL_DISPLAY_TYPE_CVBS:
+			return DE_IRQ_CVBS_PRE;
+		default:
+			return DE_IRQ_LCD_PRE;
+	}
+}
+
+static DECLARE_COMPLETION(completion);
+
+static void de_irq_wait_handler(enum de_irq_type irq, void *data)
+{
+	complete((struct completion *)data);
+}
+
+void dehw_mgr_wait_for_go(enum owl_de_path_id path_id)
+{
+	ktime_t expires ,end ;
+	u32 val;
+	int i = 70;
+	ktime_t being = ktime_get();
+	do{				
+		val = de_ops->fcr_get(path_id);
+		
+		if(val == 0 || i == 0){
+			break;
+		}
+						
+        expires = ktime_add_ns(ktime_get(), 200 * 1000);   
+
+	    set_current_state(TASK_UNINTERRUPTIBLE);
+	    
+	    i--;
+	    
+	    while(schedule_hrtimeout(&expires, HRTIMER_MODE_ABS) != 0);
+	    
+    }while(val); 
+    end = ktime_get();
+    if(ktime_to_ns(end) - ktime_to_ns(being) > 10000000){
+    	//printk("dehw_mgr_wait_for_go ~~ %lld (ns)\n",(ktime_to_ns(end) - ktime_to_ns(being)));   
+	}
+}
+
+
+int de_wait_for_irq_interruptible_timeout(enum de_irq_type irq,enum owl_de_path_id path_id, unsigned long timeout)
+{
+	int r;
+	//DSSINFO("de_wait_for_irq_interruptible_timeout path_id %d  irq 0x%x  irq status 0x%x\n",path_id,irq,de_ops->irq_status_get());	
+	r = owl_de_register_isr(irq, de_irq_wait_handler, &completion);
+	
+	if (r) {
+			return r;
+	}
+	
+	timeout = wait_for_completion_interruptible_timeout(&completion, timeout);
+	
+	owl_de_unregister_isr(irq, de_irq_wait_handler, &completion);
+	
+	if (timeout == 0) {
+		return -ETIMEDOUT;
+	}
+	
+	if (timeout == -ERESTARTSYS) {
+		return -ERESTARTSYS;
+	}
+	
+	
+	dehw_mgr_wait_for_go(path_id);	
+	return 0;
+}
+
+void owl_de_get_histogram_info(u32 * hist, u32 * totaly)
+{
+}
+EXPORT_SYMBOL(owl_de_get_histogram_info);
+
+bool de_is_vb_valid(enum owl_de_path_id path, enum owl_display_type type)
+{
+	u32 mask, vb_mask;
+
+	mask = de_ops->irq_to_mask(de_mgr_get_vsync_irq(type));
+	vb_mask = de_ops->irq_mask_to_vb_mask(mask);
+
+	return (de_ops->irq_status_get() & vb_mask);
+}
+
+bool owl_de_is_atm7059tc(void)
+{
+	return (DE_HW_ID_ATM7059TC == de_pdata->id);
+}
+
+int owl_de_get_ictype(void)
+{
+	if(DE_HW_ID_ATM7059A == de_pdata->id){
+		return 0x705A;
+	}else if(DE_HW_ID_ATM9009A == de_pdata->id){
+		return 0x900A;
+	}else{
+		return 0x705A;
+	}
+}
+EXPORT_SYMBOL(owl_de_get_ictype);
+
+void de_set_gamma_table(enum owl_de_path_id channel, u32 *gamma)
+{
+	DSSDBG("set gamma\n");
+	de_ops->set_gamma_table(channel, gamma);
+}
+
+void de_get_gamma_table(enum owl_de_path_id channel, u32 *gamma)
+{
+	de_ops->get_gamma_table(channel, gamma);
+}
+
+void de_enable_gamma_table(enum owl_de_path_id channel, bool enable)
+{
+	DSSDBG("enable gamma, %d\n", enable);
+	de_ops->enable_gamma_table(channel, enable);
+}
+
+
+void de_mgr_set_path_size(enum owl_de_path_id channel, u16 width, u16 height)
+{
+	de_ops->path_size_set(channel, width, height);
+}
+
+void de_mgr_set_device_type(enum owl_de_path_id channel,enum owl_display_type type)
+{
+	/* TODO */
+	de_ops->display_type_set(channel, type);
+}
+
+void de_mgr_enable(enum owl_de_path_id channel, bool enable)
+{
+	de_ops->path_enable(channel, enable);
+}
+
+void de_mgr_set_dither(enum owl_de_path_id channel, enum owl_dither_mode mode)
+{
+	de_ops->dither_set(channel, mode);
+}
+
+void de_mgr_enable_dither(enum owl_de_path_id channel, bool enable)
+{
+	de_ops->dither_enable(channel, enable);
+}
+
+bool de_mgr_is_enabled(enum owl_de_path_id channel)
+{
+	return de_ops->path_is_enabled(channel);
+}
+
+void de_mgr_go(enum owl_de_path_id channel)
+{
+	de_ops->fcr_set(channel);
+}
+
+void de_mgr_setup(enum owl_de_path_id channel, struct owl_overlay_manager_info *info)
+{
+	/* TODO */
+}	
+
+void de_mgr_cursor_setup(enum owl_de_path_id channel, struct owl_cursor_info *info)
+{
+	if(!info->enable){
+		de_ops->curosr_enable(channel,false);
+	}else{
+		printk("de_mgr_cursor_setup info->pos_x 0x%x info->pos_y 0x%x\n ",info->pos_x,info->pos_y);
+		de_ops->curosr_set_position(channel,info->pos_x,info->pos_y);
+		de_ops->curosr_set_addr(channel,info->paddr);
+		de_ops->curosr_set_str(channel,info->stride);
+		de_ops->curosr_enable(channel,true);
+	}	
+}	
+
+int de_ovl_setup(enum owl_de_path_id channel, enum owl_plane plane,
+	   	 struct owl_overlay_info *oi, bool ilace)
+{
+    	bool mmu_enable = false;
+
+	/* 
+	 * some soc does not support RGBX format, 
+	 * we can use global alpha with 0xff to emulate 'X'
+	 */
+	bool alpha_en = false;
+
+    	u16 outw, outh;
+	int ret;
+
+	struct owl_overlay *ovl = owl_dss_get_overlay(plane);
+
+	DSSDBGF("channel %d, plnae %d, pa %lx, pa_uv %x, sw %d, %d,%d, %dx%d -> "
+	    "%dx%d, cmode %x, rot %d, mir %d, ilace %d\n",
+	    channel, plane, oi->paddr, 0,
+	    oi->screen_width, oi->pos_x, oi->pos_y, oi->width, oi->height,
+	    oi->out_width, oi->out_height, oi->color_mode, oi->rotation,
+	    0, ilace);
+
+	if (oi->paddr == 0 && (oi->vaddr != 0 || oi->buffer_id >= 0)) {
+		/* MMU */
+		u32 da = 0;
+
+		if (oi->vaddr != 0)
+			ret = mmu_va_to_da(oi->vaddr, oi->img_width
+					* oi->img_height * 3 / 2, &da);		
+		else
+			ret = mmu_fd_to_da(oi->buffer_id, &da);
+		
+	
+		/* MMU map error, or we do not support MMU, BUG */
+		if (ret) {
+			DSSERR("Do not support MMU or MMU error!\n");
+			BUG();
+		}
+		
+		//owl_de_mmu_enable(plane, true);
+		oi->paddr = da;
+		mmu_enable = true;
+		DSSDBG("mmu_enable %d , oi->vaddr 0x%lx da 0x%x\n",
+			mmu_enable, oi->vaddr, da);
+	}
+
+
+	outw = (oi->out_width == 0 ? oi->width : oi->out_width);
+	outh = (oi->out_height == 0 ? oi->height : oi->out_height);
+
+	if (ilace) {
+		oi->height 	/= 2;
+		oi->pos_y 	/= 2;
+		outh 		/= 2;
+		DSSDBG("adjusting for ilace: height %d, pos_y %d, out_height %d\n",
+			oi->height, oi->pos_y, outh);
+	}
+	DSSDBG("dss_feat_color_mode_supported plane %d oi->color_mode %d\n",
+		plane, oi->color_mode);
+	if (!dss_feat_color_mode_supported(plane, oi->color_mode)) {
+		return -EINVAL;
+	}
+
+	alpha_en = de_ops->format_set(plane, oi->color_mode);
+
+	/* set fb addr and bypass according to color mode */
+	switch(oi->color_mode) {
+	case OWL_DSS_COLOR_RGB16:
+	case OWL_DSS_COLOR_BGR16:
+	case OWL_DSS_COLOR_ARGB16:
+	case OWL_DSS_COLOR_ABGR16:
+	case OWL_DSS_COLOR_RGBA16:
+	case OWL_DSS_COLOR_BGRA16:
+		de_ops->fb_addr_set(plane, DE_VIDEO_FB0,
+			(void *)oi->paddr + oi->yoff * oi->img_width * 2
+					+ oi->xoff * 2);
+
+		/* TODO if we need effective adjust */
+		if(oi->lightness != 0x80 || oi->saturation != 0x07 || oi->contrast != 0x07){
+		    de_ops->bypass_enable(plane, false);
+		}else{
+		    de_ops->bypass_enable(plane, true);
+		}
+		break;
+	case OWL_DSS_COLOR_ARGB32:
+	case OWL_DSS_COLOR_ABGR32:
+	case OWL_DSS_COLOR_RGBA32:
+	case OWL_DSS_COLOR_BGRA32:
+	case OWL_DSS_COLOR_RGBX32:
+	case OWL_DSS_COLOR_XBGR32:
+    case OWL_DSS_COLOR_XRGB32:
+		de_ops->fb_addr_set(plane, DE_VIDEO_FB0,
+			(void *)oi->paddr + oi->yoff * oi->img_width * 4
+					+ oi->xoff * 4);
+
+		/* TODO if we need effective adjust */
+		if(oi->lightness != 0x80 || oi->saturation != 0x07 || oi->contrast != 0x07){
+		    de_ops->bypass_enable(plane, false);
+		}else{
+		    de_ops->bypass_enable(plane, true);
+		}
+		break;
+	case OWL_DSS_COLOR_YU12:
+	case OWL_DSS_COLOR_NV21:
+	{
+ 		
+ 		void *ba0 = (void *)oi->paddr;
+		void *ba1 = ba0 + oi->img_width * oi->img_height;
+		void *ba2 = ba1 + oi->img_width * oi->img_height / 4;
+		/* adjust for offset */
+		ba0 += (oi->yoff * oi->img_width + oi->xoff);
+		ba1 += (oi->yoff * oi->img_width / 4 + oi->xoff / 2);
+		ba2 += (oi->yoff * oi->img_width / 4 + oi->xoff / 2);
+
+		de_ops->fb_addr_set(plane, DE_VIDEO_FB0, ba0);
+
+		if (oi->color_mode == OWL_DSS_COLOR_NV12) {
+			de_ops->fb_addr_set(plane, DE_VIDEO_FB1, ba2);
+			de_ops->fb_addr_set(plane, DE_VIDEO_FB2, ba1);
+		} else {
+			de_ops->fb_addr_set(plane, DE_VIDEO_FB1, ba1);
+			de_ops->fb_addr_set(plane, DE_VIDEO_FB2, ba2);
+		}
+
+		de_ops->bypass_enable(plane, false);
+		break;
+	}
+	case OWL_DSS_COLOR_NV12:
+	case OWL_DSS_COLOR_NU21:
+	{
+		void *ba0 = (void *)oi->paddr;
+		void *ba1 = ba0 + oi->img_width * oi->img_height;
+
+		/* adjust for offset */
+		ba0 += (oi->yoff * oi->img_width + oi->xoff);
+		ba1 += (oi->yoff * oi->img_width / 2 + oi->xoff);
+
+		de_ops->fb_addr_set(plane, DE_VIDEO_FB0, ba0);
+		de_ops->fb_addr_set(plane, DE_VIDEO_FB1, ba1);
+
+		de_ops->bypass_enable(plane, false);
+		break;
+	}
+	default:
+		DSSERR("fomat %d not support\n", oi->color_mode);
+		BUG();
+		break;
+	}
+
+	DSSDBG("set isize plane %d oi->width %d  oi->height %d \n",
+	    	plane, oi->width, oi->height);
+	de_ops->isize_set(plane, oi->width, oi->height);
+
+	DSSDBG("set str plane %d oi->color_mode %d oi->img_width %d \n",
+		plane, oi->color_mode, oi->img_width);
+	de_ops->str_set(plane, oi->color_mode,oi->img_width);
+
+	DSSDBG("set pos plane %d oi->pos_x %d oi->pos_y %d \n",
+		plane, oi->pos_x, oi->pos_y);
+    	de_ops->position_set(channel, plane, oi->pos_x, oi->pos_y);
+
+	if (ovl->caps & OWL_DSS_OVL_CAP_SCALE) {
+		DSSDBG("de_ovl_set_scaling \n");
+		de_ops->scaling_set(plane, oi->width, oi->height, outw, outh, ilace);
+	}
+
+	DSSDBG("set osize plane %d oi->width %d  oi->height %d \n", plane, outw, outh);
+	de_ops->osize_set(plane, outw, outh);
+
+	DSSDBG("set plane %d oi->rotation %d \n", plane, oi->rotation);
+	de_ops->rotation_set(plane, oi->rotation);
+	
+	DSSDBG("set plane %d lightness %d \n", plane, oi->lightness);
+	de_ops->lightness_set(plane, oi->lightness);
+	
+	DSSDBG("set plane %d  saturation %d \n", plane, oi->saturation);
+	de_ops->saturation_set(plane, oi->saturation);
+	
+	DSSDBG("set plane %d contrast %d \n", plane, oi->contrast);
+	de_ops->contrast_set(plane, oi->contrast);
+
+	if (alpha_en) {
+		oi->global_alpha_en = true;
+		oi->global_alpha = 0xff;
+		oi->pre_mult_alpha_en = false;
+	}
+	DSSDBG("set alpha %d value %d is premult %d\n", plane,
+			oi->global_alpha, oi->pre_mult_alpha_en);
+	de_ops->alpha_set(channel, plane, oi->global_alpha,
+				oi->global_alpha_en, oi->pre_mult_alpha_en);
+	
+	de_ops->critical_set(channel, plane);
+	
+	DSSDBG("de_ovl_setup ok\n");
+	return 0;
+}
+
+int owl_de_mmu_config(u32 base_addr)
+{
+	return de_ops->mmu_config(base_addr);
+}
+
+int owl_de_mmu_enable(enum owl_plane plane, bool enable)
+{
+	return de_ops->mmu_enable(plane, enable);
+}
+
+int de_ovl_enable(enum owl_de_path_id channel, enum owl_plane plane, bool enable)
+{
+    	de_ops->video_enable(channel, plane, enable);
+
+	return 0;
+}
+
+
+void owl_de_suspend(void)
+{
+	DSSINFO("%s\n", __func__);
+	de_ops->suspend(de_pdata->pdev, PMSG_SUSPEND);
+
+}
+
+/* 
+ * temp in here, for DSS's suspend/resume
+ * I have to treat differently for normal boot and mini-charger boot,
+ * it's an awlful design, should be discarded later!
+ */
+static int bootmode = 0;
+
+static int __init bootmode_setup(char *str)
+{
+	if (strcmp(str, "charger") == 0) {
+		pr_info("mini charger boot\n");
+		bootmode = OWL_DSS_BOOT_CHARGER;
+	}else if(strcmp(str, "recovery1") == 0 || strcmp(str, "recovery2") == 0 ){
+		pr_info("recovery boot\n");
+		bootmode = OWL_DSS_BOOT_RECOVERY;
+	}else{
+		pr_info("Normal boot\n");
+		bootmode = OWL_DSS_BOOT_NORMAL;
+	}
+
+	return 1;
+}
+__setup("androidboot.mode=", bootmode_setup);
+ 
+int owl_de_get_boot_mode(void)
+{
+	return bootmode;
+} 
+EXPORT_SYMBOL(owl_de_get_boot_mode);
+void owl_de_resume(void)
+{
+	DSSINFO("%s\n", __func__);
+
+	de_ops->resume(de_pdata->pdev);
+
+	/* make sure gamma is disabled, awful design */
+	de_enable_gamma_table(OWL_DSS_PATH1_ID, false);
+	de_enable_gamma_table(OWL_DSS_PATH2_ID, false);
+
+	/* mini charger boot, set path0's FCR, TODO */
+	if (bootmode == 1)
+		de_ops->fcr_set(0);
+}
+
+
+/*===================external interfaces end }====================*/
+
+/*==================={ driver attributes====================*/
+/*
+ * regitsers dump and write
+ */
+static ssize_t de_regs_show(struct device_driver *drv, char *buf)
+{
+	de_ops->dump_regs();
+
+	return 0;
+}
+
+static ssize_t de_regs_store(struct device_driver *drv,
+				const char *buf, size_t count)
+{
+	return de_ops->write_regs(buf, count);
+}
+static DRIVER_ATTR(regs, S_IWUSR | S_IRUGO,
+		de_regs_show, de_regs_store);
+
+static ssize_t de_vb_timout_cnt_show(struct device_driver *ddp, char *buf)
+{
+	return scnprintf(buf, PAGE_SIZE, "%d\n", de_pdata->vb_timeout_cnt);
+}
+static DRIVER_ATTR(vb_timeout_cnt, S_IRUGO, de_vb_timout_cnt_show, NULL);
+
+
+
+/*===================driver attributes end }==================*/
+
+
+/* TODO */
+static const struct of_device_id owl_de_match[] = {
+#ifdef CONFIG_VIDEO_OWL_DE_ATM7059
+	{
+		.compatible	= "actions,atm7059tc-de",
+		.data		= &owl_de_atm7059,
+	},
+	{
+		.compatible	= "actions,atm7059a-de",
+		.data		= &owl_de_atm7059,
+	},
+#endif
+#ifdef CONFIG_VIDEO_OWL_DE_ATM9009
+	{
+		.compatible	= "actions,atm9009a-de",
+		.data		= &owl_de_atm9009,
+	},
+#endif
+};
+
+static int __init owl_de_probe(struct platform_device *pdev) {
+	struct device 			*dev = &pdev->dev;
+	struct resource 		*res;
+	int				ret = 0;
+
+	const struct of_device_id 	*match;
+
+	DSSINFO("%s, pdev = 0x%p\n", __func__, pdev);
+
+	match = of_match_device(of_match_ptr(owl_de_match), dev);
+	if (!match) {
+		DSSERR("Error: No device match found\n");
+		return -ENODEV;
+	}
+
+
+	/* get DE's private data pointer */
+	de_pdata = (struct owl_de_pdata *)match->data;
+	de_ops = de_pdata->hwops;
+	if (!de_pdata) {
+		DSSERR("private data is NULL\n");
+		return -EINVAL;
+	}
+
+	/* set de hw id */
+	if (strcmp(match->compatible, "actions,atm7059tc-de") == 0)
+		de_pdata->id = DE_HW_ID_ATM7059TC;
+	else if (strcmp(match->compatible, "actions,atm7059a-de") == 0)
+		de_pdata->id = DE_HW_ID_ATM7059A;
+	else if (strcmp(match->compatible, "actions,atm9009a-de") == 0)
+		de_pdata->id = DE_HW_ID_ATM9009A;
+
+	de_pdata->pdev 	= pdev;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		DSSERR("can't get IORESOURCE_MEM\n");
+		return -ENODEV;
+	}
+
+	de_pdata->base = devm_ioremap_resource(&pdev->dev, res);
+	if (IS_ERR(de_pdata->base)) {
+		DSSERR("can't remap IORESOURCE_MEM\n");
+		return PTR_ERR(de_pdata->base);
+	}
+	DSSDBG("de base is 0x%p\n", de_pdata->base);
+	
+	de_boot_inited = de_channel_check_boot_inited(OWL_DSS_PATH1_ID) 
+	                 | de_channel_check_boot_inited(OWL_DSS_PATH2_ID);
+	
+	DSSINFO("DE INITED FROM UBOOT ?? %d \n", de_boot_inited);
+
+	if (!de_boot_inited) {
+		de_clk_init();
+	}
+
+	ret = de_irq_init();
+	if (ret) {
+		return ret;
+	}
+
+	mmu_init();
+
+	return 0;
+}
+
+static int __exit owl_de_remove(struct platform_device *pdev)
+{
+	de_irq_deinit();
+
+	de_clk_disable();
+
+	return 0;
+}
+
+
+static struct platform_driver __refdata owl_de_driver = {
+	.driver = {
+		.name		= "de-owl",
+		.owner		= THIS_MODULE,
+		.of_match_table	= owl_de_match,
+	},
+	.probe			= owl_de_probe,
+	.remove			= owl_de_remove,
+};
+
+int __init owl_de_init(void) {
+	int ret = 0;
+	
+	ret = platform_driver_register(&owl_de_driver);
+	if (ret) {
+		DSSERR("Failed to register de platform driver\n");
+		return ret;
+	}
+
+	/* and regs attribute */
+	ret = driver_create_file(&owl_de_driver.driver, &driver_attr_regs);
+	ret |= driver_create_file(&owl_de_driver.driver, &driver_attr_vb_timeout_cnt);
+	if (ret) {
+		DSSERR("driver_create_file failed!!\n");
+	}
+
+	return 0;
+}
+
+void owl_de_exit(void) {
+	platform_driver_unregister(&owl_de_driver);
+
+	driver_remove_file(&owl_de_driver.driver, &driver_attr_regs);
+	driver_remove_file(&owl_de_driver.driver, &driver_attr_vb_timeout_cnt);
+}
+
+module_init(owl_de_init);
+module_exit(owl_de_exit);
diff --git a/drivers/video/fbdev/owl/dss/de.h b/drivers/video/fbdev/owl/dss/de.h
new file mode 100755
index 0000000..17c4c01
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/de.h
@@ -0,0 +1,248 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/de.h
+ *
+ * Copyright (C) 2014 Actions
+ * Author: Lipeng<lipeng at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _OWL_DSS_DE_H_
+#define _OWL_DSS_DE_H_
+
+#include <video/owldss.h>
+
+#define DE_MAX_NR_ISRS				5
+
+#define DE_SCLCOEF_ZOOMIN			0
+#define DE_SCLCOEF_HALF_ZOOMOUT			1
+#define DE_SCLCOEF_SMALLER_ZOOMOUT		2
+
+#define DE_SCALE_CONST_VALUE			8192
+
+enum de_hw_id {
+	DE_HW_ID_ATM7059TC,
+	DE_HW_ID_ATM7059A,
+	DE_HW_ID_ATM9009A,
+};
+
+enum de_irq_type {
+	DE_IRQ_CVBS_PRE = 0x01,
+	DE_IRQ_DSI_PRE = 0x02, 
+	DE_IRQ_HDMI_PRE =0x04,
+	DE_IRQ_LCD_PRE = 0x08,
+	DE_IRQ_LCD2_PRE,
+	DE_IRQ_EDP_PRE,
+	DE_IRQ_MAX,
+};
+
+enum de_video_fb {
+        DE_VIDEO_FB0 = 0,
+        DE_VIDEO_FB1,
+        DE_VIDEO_FB2,
+        DE_VIDEO_FB_R0,
+        DE_VIDEO_FB_R1,
+        DE_VIDEO_FB_R2,
+};
+
+struct owl_de_hwops {
+	/* global operations */
+	u32 (*irq_status_get)(void);
+	void (*irq_status_set)(u32 status);
+
+	u32 (*irq_enable_get)(void);
+	void (*irq_enable_set)(u32 enable);
+
+	u32 (*irq_to_mask)(enum de_irq_type irq);
+	u32 (*irq_mask_to_enable)(u32 mask);
+	u32 (*irq_mask_to_vb_mask)(u32 mask);
+
+	int (*mmu_config)(u32 base_addr);
+	int (*mmu_enable)(enum owl_plane video, bool enable);
+
+	void (*special_init)(void);
+
+	int (*suspend)(struct platform_device *pdev, pm_message_t state);
+	int (*resume)(struct platform_device *pdev);
+
+	/* path operations */
+	void (*path_enable)(enum owl_de_path_id path, bool enbale);
+	bool (*path_is_enabled)(enum owl_de_path_id path);
+
+	void (*path_size_set)(enum owl_de_path_id path, u32 width, u32 height);
+	
+	void (*display_type_set)(enum owl_de_path_id path, enum owl_display_type type);
+
+	void (*video_enable)(enum owl_de_path_id path,
+			     enum owl_plane video, bool enbale);
+	bool (*video_is_enabled)(enum owl_de_path_id path, enum owl_plane video);
+
+	void (*fcr_set)(enum owl_de_path_id path);
+	bool (*fcr_get)(enum owl_de_path_id path);
+
+	void (*set_gamma_table)(enum owl_de_path_id path, u32 *gamma);
+	void (*get_gamma_table)(enum owl_de_path_id path, u32 *gamma);
+	void (*enable_gamma_table)(enum owl_de_path_id path, bool enable);
+
+	void (*dither_set)(enum owl_de_path_id path, enum owl_dither_mode mode);
+	void (*dither_enable)(enum owl_de_path_id path, bool enable);
+
+	/* video layer operations */
+	bool (*format_set)(enum owl_plane video, enum owl_color_mode color_mode);
+
+	void (*bypass_enable)(enum owl_plane video, bool enable);
+
+	void (*fb_addr_set)(enum owl_plane video, enum de_video_fb fb, void *paddr);
+
+	void (*isize_set)(enum owl_plane video, u32 width, u32 height);
+	void (*osize_set)(enum owl_plane video, u32 width, u32 height);
+	void (*position_set)(enum owl_de_path_id path, enum owl_plane video,
+				u32 x_pos, u32 u_pos);
+
+	void (*scaling_set)(enum owl_plane video, u32 org_width, u32 org_height,
+				u32 out_width, u32 out_height, bool ilace);
+	void (*rotation_set)(enum owl_plane video, u8 rotation);
+	void (*alpha_set)(enum owl_de_path_id path, enum owl_plane video,
+				u8 alpha_value, bool alpha_en,  bool pre_mult_en);
+
+	void (*critical_set)(enum owl_de_path_id path,enum owl_plane video);
+	void (*lightness_set)(enum owl_plane video, u8 lightness);
+	void (*saturation_set)(enum owl_plane video, u8 saturation);
+	void (*contrast_set)(enum owl_plane video, u8 contrast);
+			
+	void (*str_set)(enum owl_plane video,
+			enum owl_color_mode color_mode, u32 width);
+			
+	void (*curosr_enable)(enum owl_de_path_id path, bool enable);
+	
+	void (*curosr_set_position)(enum owl_de_path_id path, int pos_x, int pos_y);
+	
+	void (*curosr_set_addr)(enum owl_de_path_id path, void *paddr);
+	
+	void (*curosr_set_str)(enum owl_de_path_id path, u32 str);
+
+	void (*dump_regs)(void);
+	
+	ssize_t (*write_regs)(const char *buf, size_t len);
+};
+
+struct owl_de_path_pdata {
+	const enum owl_de_path_id		id;
+
+	const enum owl_display_type	supported_displays;
+};
+
+struct owl_de_video_pdata {
+	const enum owl_plane		id;
+
+	const enum owl_color_mode	supported_colors;
+};
+
+typedef void (*owl_de_isr_t) (enum de_irq_type irq, void *arg);
+
+struct de_isr_data {
+	enum de_irq_type 		irq;
+	owl_de_isr_t			isr;
+	void				*arg;
+	u32				mask;
+};
+
+struct de_regs_t {
+	int reg;
+	u32 value;
+};
+
+/*
+ * The private data of OWL display engine.
+ * num_paths,	the number of DE paths
+ * num_videos,	the numbers of DE video layers
+ */
+struct owl_de_pdata {
+	enum de_hw_id			id;
+
+	/*
+	 * constant information
+	 */
+	const u8			num_paths;
+	const u8			num_videos;
+
+	const struct owl_de_path_pdata	*path_pdata;
+	const struct owl_de_video_pdata	*video_pdata;
+
+	const struct owl_de_hwops	*hwops;
+
+	/*
+	 * platform data
+	 */
+	struct platform_device 		*pdev;
+	void __iomem    		*base;
+
+	int 				irq;
+        spinlock_t 			irq_lock;
+        u32 				irq_mask;
+        struct de_isr_data 		registered_isr[DE_MAX_NR_ISRS];
+
+	/* wait VB timeout times */
+	u32				vb_timeout_cnt;
+};
+
+int __init owl_de_init(void);
+void owl_de_exit(void);
+
+void de_mgr_set_path_size(enum owl_de_path_id channel, u16 width, u16 height);
+void de_mgr_set_device_type(enum owl_de_path_id channel,enum owl_display_type type);
+void de_mgr_enable(enum owl_de_path_id channel, bool enable);
+void de_mgr_set_dither(enum owl_de_path_id channel, enum owl_dither_mode mode);
+void de_mgr_enable_dither(enum owl_de_path_id channel, bool enable);
+bool de_mgr_is_enabled(enum owl_de_path_id channel);
+void de_mgr_go(enum owl_de_path_id channel);
+void de_mgr_setup(enum owl_de_path_id channel, struct owl_overlay_manager_info *info);
+void de_mgr_cursor_setup(enum owl_de_path_id channel, struct owl_cursor_info *info);
+enum de_irq_type de_mgr_get_vsync_irq(enum owl_display_type type);
+
+int owl_de_register_isr(enum de_irq_type irq, owl_de_isr_t isr, void *arg);
+int owl_de_unregister_isr(enum de_irq_type irq, owl_de_isr_t isr, void *arg);
+
+int de_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
+int de_wait_for_irq_interruptible_timeout(enum de_irq_type irq,enum owl_de_path_id path, unsigned long timeout);
+
+
+
+int de_ovl_setup(enum owl_de_path_id channel ,enum owl_plane plane, struct owl_overlay_info *oi, bool ilace);
+int de_ovl_enable(enum owl_de_path_id channel ,enum owl_plane plane, bool enable);
+
+int owl_de_mmu_config(u32 base_addr);
+int owl_de_mmu_enable(enum owl_plane plane, bool enable);
+
+void de_set_gamma_table(enum owl_de_path_id path, u32 *gamma);
+void de_get_gamma_table(enum owl_de_path_id path, u32 *gamma);
+void de_enable_gamma_table(enum owl_de_path_id path, bool enable);
+bool de_channel_check_boot_inited(enum owl_de_path_id path);
+
+
+int hdmi_en(void);
+
+int cvbs_en(void);
+
+void io_remap(void);
+
+bool de_is_vb_valid(enum owl_de_path_id path, enum owl_display_type type);
+
+#ifdef CONFIG_VIDEO_OWL_DE_ATM7059
+extern struct owl_de_pdata 		owl_de_atm7059;
+#endif
+#ifdef CONFIG_VIDEO_OWL_DE_ATM9009
+extern struct owl_de_pdata 		owl_de_atm9009;
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/owl/dss/de_atm7059.c b/drivers/video/fbdev/owl/dss/de_atm7059.c
new file mode 100755
index 0000000..cfdcad3
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/de_atm7059.c
@@ -0,0 +1,1222 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/de_atm7059.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: lipeng<lipeng at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "DE"
+
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+#include <linux/hardirq.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/err.h>
+
+#include <mach/clkname.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "de.h"
+#include "de_atm7059.h"
+
+#define DE_ATM7059_PATH_NUM		(2)
+#define DE_ATM7059_VIDEO_NUM		(4)
+
+#define DE_ATM7059_GAMMA_SIZE		(256 * 3)
+
+const static struct owl_de_path_pdata de_atm7059_paths[] = {
+	{
+		.id			= OWL_DSS_PATH1_ID,
+		.supported_displays	= OWL_DISPLAY_TYPE_LCD
+					| OWL_DISPLAY_TYPE_DSI
+					| OWL_DISPLAY_TYPE_EDP
+					| OWL_DISPLAY_TYPE_HDMI					
+					| OWL_DISPLAY_TYPE_CVBS,
+	},
+	{
+		.id			= OWL_DSS_PATH2_ID,
+		.supported_displays	= OWL_DISPLAY_TYPE_HDMI
+					| OWL_DISPLAY_TYPE_LCD
+					| OWL_DISPLAY_TYPE_DSI
+					| OWL_DISPLAY_TYPE_EDP
+					| OWL_DISPLAY_TYPE_CVBS,
+	},
+};
+
+const static struct owl_de_video_pdata de_atm7059_videos[] = {
+	{
+		.id			= OWL_DSS_VIDEO1,
+		.supported_colors	=
+				OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16
+        			| OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32
+        			| OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32
+        			| OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21
+        			| OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16
+        			| OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16 ,
+	},
+	{
+		.id			= OWL_DSS_VIDEO2,
+		.supported_colors	=
+				OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16
+				| OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32
+				| OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32
+				| OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21
+				| OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16
+				| OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16,
+	},
+	{
+		.id			= OWL_DSS_VIDEO3,
+		.supported_colors	=
+				OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16
+				| OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32
+				| OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32
+				| OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21
+				| OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16
+				| OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16,
+	},
+	{
+		.id			= OWL_DSS_VIDEO4,
+		.supported_colors	=
+				OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16
+				| OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32
+				| OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32
+				| OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21
+				| OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16
+				| OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16,
+	},
+};
+
+static struct de_regs_t		de_atm7059_regs[256];
+static int			de_atm7059_regs_cnt = 0;
+
+struct owl_de_pdata 		owl_de_atm7059;
+
+static void inline de_write_reg(int idx, u32 val)
+{
+	writel(val, owl_de_atm7059.base + idx);
+}
+
+static u32 inline de_read_reg(int idx)
+{
+	return readl(owl_de_atm7059.base + idx);
+}
+
+static u32 de_irq_status_get(void)
+{
+	return de_read_reg(DE_IRQSTATUS);
+}
+
+static void de_irq_status_set(u32 status)
+{
+	de_write_reg(DE_IRQSTATUS, status);
+}
+
+static u32 de_irq_enable_get(void)
+{
+	return de_read_reg(DE_IRQENABLE);
+}
+
+static void de_irq_enable_set(u32 enable)
+{
+	de_write_reg(DE_IRQENABLE, enable);
+}
+
+static u32 de_irq_to_mask(enum de_irq_type irq)
+{
+	switch (irq) {
+	case DE_IRQ_CVBS_PRE:
+		return (1 << 0);
+		break;
+	case DE_IRQ_DSI_PRE:
+		return (1 << 1);
+		break;
+	case DE_IRQ_HDMI_PRE:
+		return (1 << 2);
+		break;
+	case DE_IRQ_LCD_PRE:
+		return (1 << 3);
+		break;
+	case DE_IRQ_LCD2_PRE:
+		return (1 << 4);
+		break;
+	default:
+		return 0;
+		break;
+	}
+}
+
+static u32 de_irq_mask_to_enable(u32 mask)
+{
+	/* TODO */
+	u32 enable = 0;
+
+	if (mask & (1 << 0)) {
+		/* CVBS */
+		enable |= (1 << 3);
+	}
+	if (mask & (1 << 1)) {
+		/* DSI */
+		enable |= (1 << 2);
+	}
+	if (mask & (1 << 2)) {
+		/* HDMI */
+		enable |= (1 << 4);
+	}
+	if (mask & (1 << 3)) {
+		/* LCD */
+		enable |= (1 << 0);
+	}
+
+	return enable;
+}
+
+static u32 de_irq_mask_to_vb_mask(u32 mask)
+{
+	return (mask << 8);
+}
+
+
+static int de_mmu_config(u32 base_addr)
+{
+	DSSDBG("%s: base_addr 0x%x\n", __func__, base_addr);
+
+	de_write_reg(DE_MMU_BASE, base_addr);
+
+	return 0;
+}
+
+static int de_mmu_enable(enum owl_plane video, bool enable)
+{
+	u32 val;		
+
+	DSSDBG("%s: enable=%d\n", __func__, enable);
+
+	val = de_read_reg(DE_MMU_EN);	
+	val = REG_SET_VAL(val, enable, video, video);	
+
+	de_write_reg(DE_MMU_EN, val);
+	return 0;
+}
+
+
+static void de_path_enable(enum owl_de_path_id path, bool enable)
+{
+	u32 val;
+	
+	val = de_read_reg(DE_PATH_EN(path));
+	val = REG_SET_VAL(val, enable, DE_PATH_ENABLE_BIT, DE_PATH_ENABLE_BIT);
+	de_write_reg(DE_PATH_EN(path), val);
+}
+
+static bool de_path_is_enabled(enum owl_de_path_id path)
+{
+	u32 val;
+
+	val = de_read_reg(DE_PATH_EN(path));
+	val = REG_GET_VAL(val, DE_PATH_ENABLE_BIT, DE_PATH_ENABLE_BIT);
+	
+	return val;
+}
+
+static void de_path_size_set(enum owl_de_path_id path, u32 width, u32 height)
+{
+	u32 val;
+	BUG_ON((width > (1 << DE_SIZE_BIT_WIDTH)) || (height > (1 << DE_SIZE_BIT_WIDTH)));
+	
+	val = REG_VAL(height - 1, DE_SIZE_BIT_WIDTH + 16 - 1, 16)
+	         | REG_VAL(width - 1, DE_SIZE_BIT_WIDTH - 1, 0);
+	
+	de_write_reg(DE_PATH_SIZE(path), val);
+}
+	
+static void de_display_type_set(enum owl_de_path_id path, enum owl_display_type type)
+{
+	u32 val,tmp;
+	u32 begin_bit,end_bit;
+	val = de_read_reg(DE_OUTPUT_CON);
+	tmp = de_read_reg(DE_PATH_EN(path));
+	//printk("@@@@@tmp = 0x%x\n",tmp);
+	if(path == OWL_DSS_PATH1_ID){
+		begin_bit = DE_OUTPUT_PATH1_DEVICE_BEGIN_BIT;
+		end_bit = DE_OUTPUT_PATH1_DEVICE_END_BIT;
+	}else{
+		begin_bit = DE_OUTPUT_PATH2_DEVICE_BEGIN_BIT;
+		end_bit = DE_OUTPUT_PATH2_DEVICE_END_BIT;
+	}
+
+	switch (type){
+	case OWL_DISPLAY_TYPE_CVBS:
+		tmp = REG_SET_VAL(tmp, 1, 11,11);
+		tmp = REG_SET_VAL(tmp, 1, 16,16);
+		val = REG_SET_VAL(val, 0, end_bit,begin_bit);
+    break;            
+	case OWL_DISPLAY_TYPE_HDMI:
+		val = REG_SET_VAL(val, 2, end_bit,begin_bit);
+		break;
+	case OWL_DISPLAY_TYPE_LCD:
+		val = REG_SET_VAL(val, 3, end_bit, begin_bit);
+		break;
+	case OWL_DISPLAY_TYPE_DSI:
+		val = REG_SET_VAL(val, 1, end_bit,begin_bit);
+		break;
+	default:
+    		BUG();
+	}
+	
+	de_write_reg(DE_PATH_EN(path), tmp);
+	de_write_reg(DE_OUTPUT_CON, val);
+}
+
+/* TODO */
+static void de_video_enable(enum owl_de_path_id path, enum owl_plane video, bool enable)
+{
+	u32 val;
+	if (enable) {
+		if (path == OWL_DSS_PATH1_ID) {
+			val = de_read_reg(DE_PATH_CTL(OWL_DSS_PATH2_ID));
+			val = REG_SET_VAL(val, 0, DE_PANEL_ENABLE_BIT + video,
+						  DE_PANEL_ENABLE_BIT + video);
+                	de_write_reg(DE_PATH_CTL(OWL_DSS_PATH2_ID), val);
+        	} else {
+			val = de_read_reg(DE_PATH_CTL(OWL_DSS_PATH1_ID));
+			val = REG_SET_VAL(val, 0, DE_PANEL_ENABLE_BIT + video,
+						  DE_PANEL_ENABLE_BIT + video);
+			de_write_reg(DE_PATH_CTL(OWL_DSS_PATH1_ID), val);
+		}
+	}
+
+	val = de_read_reg(DE_PATH_CTL(path));
+	val = REG_SET_VAL(val, enable, DE_PANEL_ENABLE_BIT + video,
+			  	DE_PANEL_ENABLE_BIT + video);   
+	de_write_reg(DE_PATH_CTL(path), val);
+}
+
+static bool de_video_is_enabled(enum owl_de_path_id path, enum owl_plane video)
+{
+	u32 val;
+
+	val = de_read_reg(DE_PATH_CTL(path));
+	val = REG_GET_VAL(val, DE_PANEL_ENABLE_BIT + video,
+			DE_PANEL_ENABLE_BIT + video);
+	
+	return val;
+}
+
+static void de_path_fcr_set(enum owl_de_path_id path)
+{
+	u32 val;
+	int i = 0;
+	bool found_first_layer = true;
+	
+	if(path == OWL_DSS_PATH1_ID){		
+		for(i = 3 ; i >= 0 ; i --){
+			val = de_read_reg(DE_OVL_COOR(path,i));		
+			if(((val  & 0xffff0000) == 0)
+				&& de_video_is_enabled(path,i)){
+				if(found_first_layer){
+					val = de_read_reg(DE_OVL_CFG(i));
+					val = REG_SET_VAL(val, 0, 
+					        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+					        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+						   );
+					de_write_reg(DE_OVL_CFG(i), val);
+					de_write_reg(DE_OVL_CRITICAL_CFG(i), 0x10);
+					found_first_layer = false;
+				}else{
+					val = de_read_reg(DE_OVL_CFG(i));
+					val = REG_SET_VAL(val, 2, 
+					        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+					        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+						   );
+					de_write_reg(DE_OVL_CFG(i), val);
+					de_write_reg(DE_OVL_CRITICAL_CFG(i), 0);
+				
+				}
+			}else{
+				val = de_read_reg(DE_OVL_CFG(i));
+				val = REG_SET_VAL(val, 2, 
+				        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+				        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+					   );
+				de_write_reg(DE_OVL_CFG(i), val);
+			}
+		}
+	}else{
+		val = de_read_reg(DE_OVL_CFG(3));
+					val = REG_SET_VAL(val, 0, 
+					        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+					        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+						   );
+		de_write_reg(DE_OVL_CFG(3), val);
+		de_write_reg(DE_OVL_CRITICAL_CFG(3), 0x10);
+	}
+	val = de_read_reg(DE_PATH_FCR(path));
+	val = REG_SET_VAL(val, 1, DE_PATH_FCR_BIT, DE_PATH_FCR_BIT);
+	
+	de_write_reg(DE_PATH_FCR(path), val);
+	
+	val = de_read_reg(DE_OUTPUT_STAT);
+	if(val!= 0){
+		printk("fifo underflow 0x%x\n",val);
+		de_write_reg(DE_OUTPUT_STAT,val);
+	}
+}
+
+static bool de_path_fcr_get(enum owl_de_path_id path)
+{
+	u32 val;
+
+	val = de_read_reg(DE_PATH_FCR(path));
+	val = REG_GET_VAL(val, DE_PATH_FCR_BIT, DE_PATH_FCR_BIT);
+
+	return val;
+}
+
+static void de_gamma_table_set(enum owl_de_path_id path, u32 *gamma)
+{
+	bool is_busy;
+	u32 idx;
+	u32 val;
+
+	for (idx = 0; idx < (DE_ATM7059_GAMMA_SIZE / 4); idx++) {
+		/* 
+		 * write operation mode(1 for write) and index
+		 */
+		val = de_read_reg(DE_PATH_GAMMA_IDX(path));
+
+		val = REG_SET_VAL(val, idx, DE_PATH_GAMMA_IDX_INDEX_END_BIT,
+						DE_PATH_GAMMA_IDX_INDEX_BEGIN_BIT);
+		val = REG_SET_VAL(val, 1, DE_PATH_GAMMA_IDX_OP_SEL_END_BIT,
+						DE_PATH_GAMMA_IDX_OP_SEL_BEGIN_BIT);
+
+		de_write_reg(DE_PATH_GAMMA_IDX(path), val);
+
+		/* write ram */
+		de_write_reg(DE_PATH_GAMMA_RAM(path), gamma[idx % 64]);
+
+		/* wait for busy bit */
+		do {
+			val = de_read_reg(DE_PATH_GAMMA_IDX(path));
+			is_busy = REG_GET_VAL(val, DE_PATH_GAMMA_IDX_BUSY_BIT,
+							DE_PATH_GAMMA_IDX_BUSY_BIT);
+		} while (is_busy);
+	}
+
+	/* write finish, clear write bit and index */
+	de_write_reg(DE_PATH_GAMMA_IDX(path), 0);
+}
+
+static void de_gamma_table_get(enum owl_de_path_id path, u32 *gamma)
+{
+	/* TODO */
+}
+
+static void de_gamma_table_enable(enum owl_de_path_id path, bool enable)
+{
+	u32 val;
+	
+	val = de_read_reg(DE_PATH_GAMMA_ENABLE(path));
+
+	if (enable != REG_GET_VAL(val, DE_PATH_GAMMA_ENABLE_BIT,
+					DE_PATH_GAMMA_ENABLE_BIT)) {
+		val = REG_SET_VAL(val, enable, DE_PATH_GAMMA_ENABLE_BIT,
+						DE_PATH_GAMMA_ENABLE_BIT);
+	
+		de_write_reg(DE_PATH_GAMMA_ENABLE(path), val);
+	}
+}
+
+static void de_dither_enable(enum owl_de_path_id path, bool enable)
+{
+        u32 val;
+	int dither_idx, dither_enable_bit;
+
+	/* only valid for LCD */
+	BUG_ON(OWL_DSS_PATH1_ID != path);
+
+	if (owl_de_is_atm7059tc()) {
+		dither_idx = DE_PATH_CTL(0);
+		dither_enable_bit = 8;
+	} else {
+		dither_idx = 0x150;
+		dither_enable_bit = 0;
+	}
+
+        val = de_read_reg(dither_idx);
+	val = REG_SET_VAL(val, enable, dither_enable_bit, dither_enable_bit);
+	de_write_reg(dither_idx, val);
+}
+
+static void de_dither_set(enum owl_de_path_id path, enum owl_dither_mode mode)
+{
+	u32 val;
+	int dither_idx;
+
+	BUG_ON(OWL_DSS_PATH1_ID != path);
+
+	if (owl_de_is_atm7059tc())
+		dither_idx = DE_PATH_CTL(0);
+	else
+		dither_idx = 0x150;
+
+        val = de_read_reg(dither_idx);
+
+	/* 
+	 * ATM7059TC
+	 * 	R: 12, G, 13, B: 14
+	 * ATM7059A
+	 *	bit1, mode, 0 is 888->666 1 is 888->565
+	 */
+	switch (mode) {
+	case DITHER_24_TO_18:
+		if (owl_de_is_atm7059tc())
+			val = REG_SET_VAL(val, 7, 14, 12);
+		else
+			val = REG_SET_VAL(val, 0, 1, 1);
+                break;
+
+        case DITHER_24_TO_16:
+		if (owl_de_is_atm7059tc())
+			val = REG_SET_VAL(val, 1, 13, 13);
+		else
+			val = REG_SET_VAL(val, 1, 1, 1);
+                break;
+
+        default:
+		return;
+	}
+
+        de_write_reg(dither_idx, val);
+}
+
+/* TODO */
+static int de_owl_color_mode_to_hw_mode(enum owl_color_mode color_mode){
+	int hw_format = 0;
+
+	switch(color_mode){
+	case OWL_DSS_COLOR_RGB16:
+	case OWL_DSS_COLOR_BGR16:
+		hw_format = 0;
+		break;
+	case OWL_DSS_COLOR_ARGB32:
+	case OWL_DSS_COLOR_RGBA32:
+	case OWL_DSS_COLOR_RGBX32:
+    case OWL_DSS_COLOR_XRGB32:
+		hw_format = 1;
+		break;
+	case OWL_DSS_COLOR_NU21:
+	case OWL_DSS_COLOR_NV12:
+		hw_format = 2;
+		break;
+	case OWL_DSS_COLOR_NV21:		
+	case OWL_DSS_COLOR_YU12:
+    		hw_format = 3;
+		break;
+	case OWL_DSS_COLOR_ARGB16:
+	case OWL_DSS_COLOR_ABGR16:
+		hw_format = 4;
+		break;
+	case OWL_DSS_COLOR_ABGR32:
+	case OWL_DSS_COLOR_BGRA32:
+	case OWL_DSS_COLOR_XBGR32:
+		hw_format = 5;
+		break;
+
+	default:
+		/* TODO */
+		break;
+	}
+	return hw_format;
+}
+
+
+static bool de_video_format_set(enum owl_plane video, enum owl_color_mode color_mode)
+{
+	bool alpha_en = false;
+
+	int hw_format = 0;
+	u32 val;
+
+	hw_format = de_owl_color_mode_to_hw_mode(color_mode);
+
+	val = de_read_reg(DE_OVL_CFG(video));
+	
+	val = REG_SET_VAL(val, 0, 31, 28);
+	
+	if (color_mode == OWL_DSS_COLOR_YU12
+		|| color_mode == OWL_DSS_COLOR_NV12
+		|| color_mode == OWL_DSS_COLOR_NV21
+		|| color_mode == OWL_DSS_COLOR_NU21) {
+		val = REG_SET_VAL(val, 3, 29, 28);
+	}
+	
+	if(color_mode == OWL_DSS_COLOR_NU21){
+		val = REG_SET_VAL(val, 1, 31, 30);
+	}
+
+	if (color_mode == OWL_DSS_COLOR_RGBA32
+		|| color_mode == OWL_DSS_COLOR_RGBX32
+		|| color_mode == OWL_DSS_COLOR_BGRA32) {
+		val = REG_SET_VAL(val, 3, 31, 30);
+	}
+
+	/* enable global aplha to emulate RGBX */
+	if (color_mode == OWL_DSS_COLOR_RGBX32
+		|| color_mode == OWL_DSS_COLOR_XBGR32
+		|| color_mode == OWL_DSS_COLOR_XRGB32)
+		alpha_en = true;
+	
+	
+	val = REG_SET_VAL(val, hw_format, DE_OVL_CFG_FMT_END_BIT, DE_OVL_CFG_FMT_BEGIN_BIT);
+	
+	de_write_reg(DE_OVL_CFG(video), val);
+
+	return alpha_en;
+}
+
+static void de_video_bypass_enable(enum owl_plane video, bool enable)
+{
+	u32 val;
+
+	val = de_read_reg(DE_OVL_CFG(video));
+	val = REG_SET_VAL(val, enable, DE_OVL_CFG_BYPASS_BIT,
+					DE_OVL_CFG_BYPASS_BIT);
+	de_write_reg(DE_OVL_CFG(video), val);
+}
+
+/* TODO */
+static void de_video_fb_addr_set(enum owl_plane video, enum de_video_fb fb, void *paddr)
+{
+	if (fb == DE_VIDEO_FB0) {
+    		de_write_reg(DE_OVL_BA0(video), (u32)paddr);
+	} else if (fb == DE_VIDEO_FB1) {
+    		de_write_reg(DE_OVL_BA1UV(video), (u32)paddr);
+	} else if (fb == DE_VIDEO_FB2) {
+    		de_write_reg(DE_OVL_BA2V(video), (u32)paddr);
+	}
+}
+
+static void de_video_isize_set(enum owl_plane video, u32 width, u32 height)
+{
+	u32 val;
+
+	BUG_ON((width > (1 << DE_SIZE_BIT_WIDTH)) || (height > (1 << DE_SIZE_BIT_WIDTH)));
+	val = REG_VAL(height - 1, DE_SIZE_BIT_WIDTH + 16 - 1, 16)
+		| REG_VAL(width - 1, DE_SIZE_BIT_WIDTH - 1 , 0);
+
+	de_write_reg(DE_OVL_ISIZE(video), val);
+}
+
+static void de_video_osize_set(enum owl_plane video, u32 width, u32 height)
+{
+	u32 val;
+
+	BUG_ON((width > (1 << DE_SIZE_BIT_WIDTH)) || (height > (1 << DE_SIZE_BIT_WIDTH)));
+
+	val = REG_VAL(height - 1, DE_SIZE_BIT_WIDTH + 16 - 1, 16)
+			| REG_VAL(width - 1, DE_SIZE_BIT_WIDTH -1, 0);
+
+	de_write_reg(DE_OVL_OSIZE(video), val);
+}
+
+static void de_video_position_set(enum owl_de_path_id path, enum owl_plane video,
+				u32 x_pos, u32 y_pos)
+{
+	u32 val;
+
+	BUG_ON((x_pos > (1 << DE_SIZE_BIT_WIDTH)) || (y_pos > (1 << DE_SIZE_BIT_WIDTH)));
+	val = REG_VAL(y_pos, DE_SIZE_BIT_WIDTH + 16 - 1, 16)
+		| REG_VAL(x_pos, DE_SIZE_BIT_WIDTH -1, 0);
+
+	de_write_reg(DE_OVL_COOR(path, video), val);
+}
+
+/*
+ * scaling set
+ */
+static void de_ovl_set_scal_coef(enum owl_plane plane, u8 scalmode)
+{
+	switch(scalmode) {
+	case DE_SCLCOEF_ZOOMIN:
+		de_write_reg(DE_OVL_SCOEF0(plane), 0x00400000);
+		de_write_reg(DE_OVL_SCOEF1(plane), 0xFC3E07FF);
+		de_write_reg(DE_OVL_SCOEF2(plane), 0xFA3810FE);
+		de_write_reg(DE_OVL_SCOEF3(plane), 0xF9301BFC);
+		de_write_reg(DE_OVL_SCOEF4(plane), 0xFA2626FA);
+		de_write_reg(DE_OVL_SCOEF5(plane), 0xFC1B30F9);
+		de_write_reg(DE_OVL_SCOEF6(plane), 0xFE1038FA);
+		de_write_reg(DE_OVL_SCOEF7(plane), 0xFF073EFC);
+		break;
+	case DE_SCLCOEF_HALF_ZOOMOUT:
+		de_write_reg(DE_OVL_SCOEF0(plane), 0x00400000);
+		de_write_reg(DE_OVL_SCOEF1(plane), 0x00380800);
+		de_write_reg(DE_OVL_SCOEF2(plane), 0x00301000);
+		de_write_reg(DE_OVL_SCOEF3(plane), 0x00281800);
+		de_write_reg(DE_OVL_SCOEF4(plane), 0x00202000);
+		de_write_reg(DE_OVL_SCOEF5(plane), 0x00182800);
+		de_write_reg(DE_OVL_SCOEF6(plane), 0x00103000);
+		de_write_reg(DE_OVL_SCOEF7(plane), 0x00083800);
+		break;
+	case DE_SCLCOEF_SMALLER_ZOOMOUT:
+		de_write_reg(DE_OVL_SCOEF0(plane), 0x10201000);
+		de_write_reg(DE_OVL_SCOEF1(plane), 0x0E1E1202);
+		de_write_reg(DE_OVL_SCOEF2(plane), 0x0C1C1404);
+		de_write_reg(DE_OVL_SCOEF3(plane), 0x0A1A1606);
+		de_write_reg(DE_OVL_SCOEF4(plane), 0x08181808);
+		de_write_reg(DE_OVL_SCOEF5(plane), 0x06161A0A);
+		de_write_reg(DE_OVL_SCOEF6(plane), 0x04141C0C);
+		de_write_reg(DE_OVL_SCOEF7(plane), 0x02121E0E);
+		break;
+	default:
+		BUG();
+	}   
+}
+
+static void de_video_scaling_set(enum owl_plane video, u32 orig_width, u32 orig_height,
+				u32 out_width, u32 out_height, bool ilace)
+{
+	u16 w_factor;
+	u16 h_factor;
+	u16 factor;
+	u16 scalmode;
+	u32 val;    
+	
+	w_factor = (orig_width * DE_SCALE_CONST_VALUE  +  out_width - 1) / out_width;
+	h_factor = (orig_height * DE_SCALE_CONST_VALUE  +  out_height - 1) / out_height;  
+	   
+	val = REG_VAL(h_factor, 31, 16) | REG_VAL(w_factor, 15, 0);
+	        
+	de_write_reg(DE_OVL_SR(video), val);
+	
+	factor = (orig_width * orig_height) / (out_width * out_height);
+	
+	if (factor <= 1) {
+		scalmode = DE_SCLCOEF_ZOOMIN;        
+	} else if (factor <= 4) {
+		scalmode = DE_SCLCOEF_HALF_ZOOMOUT;        
+	} else if(factor > 4) {
+		scalmode = DE_SCLCOEF_SMALLER_ZOOMOUT;
+	}
+	       
+	de_ovl_set_scal_coef(video, scalmode);
+}
+
+/* TODO */
+static void de_video_rotation_set(enum owl_plane video, u8 rotation)
+{
+	u32 val;
+
+	BUG_ON(rotation != 0 && rotation != 1 && rotation != 2 && rotation != 3);
+	val = de_read_reg(DE_OVL_CFG(video));
+	val = REG_SET_VAL(val, rotation, DE_OVL_CFG_FLIP_BIT + 1, DE_OVL_CFG_FLIP_BIT);
+
+	de_write_reg(DE_OVL_CFG(video), val);
+}
+
+static void __video_enable_global_alpha(enum owl_de_path_id path,
+				      enum owl_plane video, bool enable)
+{
+	u32 val;         
+
+	val = de_read_reg(DE_OVL_ALPHA_ENABLE(path, video));    
+	val = REG_SET_VAL(val, enable ? 1 : 0,
+              		DE_OVL_ALPHA_CFG_ENABLE_END_BIT,
+              		DE_OVL_ALPHA_CFG_ENABLE_BEGIN_BIT);
+
+	de_write_reg(DE_OVL_ALPHA_ENABLE(path, video), val);
+}
+
+static void de_video_alpha_set(enum owl_de_path_id path, enum owl_plane video,
+				u8 alpha_value,bool alpha_en, bool pre_mult_en)
+{
+	u32 val;         
+
+	/* set global alpha */
+	val = de_read_reg(DE_OVL_ALPHA_CFG(path, video));    
+	val = REG_SET_VAL(val, alpha_value, DE_OVL_ALPHA_CFG_VALUE_END_BIT,
+				DE_OVL_ALPHA_CFG_VALUE_BEGIN_BIT);
+    
+	de_write_reg(DE_OVL_ALPHA_CFG(path, video), val);	
+
+	/* set premultied alpha enable */
+	val = de_read_reg(DE_OVL_ALPHA_CFG(path, video));    
+	if (pre_mult_en) {
+		val = REG_SET_VAL(val, 1, DE_OVL_ALPHA_CFG_PRE_MUTI_BIT,
+						DE_OVL_ALPHA_CFG_PRE_MUTI_BIT);
+	} else {
+		val = REG_SET_VAL(val, 0, DE_OVL_ALPHA_CFG_PRE_MUTI_BIT,
+						DE_OVL_ALPHA_CFG_PRE_MUTI_BIT);
+	}
+	de_write_reg(DE_OVL_ALPHA_CFG(path, video), val);
+	
+	__video_enable_global_alpha(path, video, alpha_en);
+}
+
+static void de_video_str_set(enum owl_plane video,
+			  enum owl_color_mode color_mode, u32 width)
+{
+	u32 val;
+
+	switch (color_mode) {
+	case OWL_DSS_COLOR_RGB16:
+	case OWL_DSS_COLOR_BGR16:
+	case OWL_DSS_COLOR_ARGB16:
+	case OWL_DSS_COLOR_ABGR16:
+	case OWL_DSS_COLOR_RGBA16:
+	case OWL_DSS_COLOR_BGRA16:
+		val = width / 4;
+		break;
+
+	case OWL_DSS_COLOR_ARGB32:    
+	case OWL_DSS_COLOR_ABGR32:
+	case OWL_DSS_COLOR_RGBA32:
+	case OWL_DSS_COLOR_RGBX32:
+	case OWL_DSS_COLOR_BGRA32:
+	case OWL_DSS_COLOR_XBGR32:
+    case OWL_DSS_COLOR_XRGB32:
+		val = width / 2;
+		break;
+
+	case OWL_DSS_COLOR_YU12:
+	case OWL_DSS_COLOR_NV21:
+		val = ((width / 4) >> 1) | (((width / 4) >> 2) << 11)
+			| (((width / 4) >> 2) << 21);
+		break;
+
+	case OWL_DSS_COLOR_NV12:
+	case OWL_DSS_COLOR_NU21: 
+		val = ((width / 4) >> 1) | (((width / 4) >> 1) << 11);
+		break;
+	default:
+		BUG();
+		break;            
+	}
+	de_write_reg(DE_OVL_STR(video), val); 
+}
+
+static void de_critical_set(enum owl_de_path_id path,enum owl_plane video)
+{
+	/*u32 val;
+	if(path == OWL_DSS_PATH1_ID){
+		val = de_read_reg(DE_OVL_CFG(video));
+		if(video == 0){
+			val = REG_SET_VAL(val, 2, 
+			        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+			        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+				   );
+			de_write_reg(DE_OVL_CFG(video), val);
+			de_write_reg(DE_OVL_CRITICAL_CFG(video), 0);
+		}else{
+			if(x == 0 &&  y == 0){
+				val = REG_SET_VAL(val, 0, 
+			        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+			        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+				   );
+				de_write_reg(DE_OVL_CFG(video), val);
+				de_write_reg(DE_OVL_CRITICAL_CFG(video), 0x10);	
+			}
+			
+		}		
+	}else{
+		val = de_read_reg(DE_OVL_CFG(video));
+		val = REG_SET_VAL(val, 2, 
+		        DE_OVL_CFG_CRITICAL_CTL_END_BIT,
+		        DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT
+			   );
+		de_write_reg(DE_OVL_CFG(video), val);
+		de_write_reg(DE_OVL_CRITICAL_CFG(video), 0);
+	}*/
+}
+static void de_video_lightness_set(enum owl_plane video, u8 lightness)
+{
+	u32 val;
+	val = de_read_reg(DE_OVL_CFG(video));
+	
+	val = REG_SET_VAL(val, lightness, DE_OVL_CFG_LIGHTNESS_END_BIT, DE_OVL_CFG_LIGHTNESS_BEGIN_BIT);
+    
+	de_write_reg(DE_OVL_CFG(video), val);
+}
+
+static void de_video_saturation_set(enum owl_plane video, u8 saturation)
+{
+	u32 val;
+	
+	val = de_read_reg(DE_OVL_CFG(video));
+	
+	val = REG_SET_VAL(val, saturation, DE_OVL_CFG_SATURATION_END_BIT, DE_OVL_CFG_SATURATION_BEGIN_BIT);
+	
+	de_write_reg(DE_OVL_CFG(video), val);
+}
+
+static void de_video_contrast_set(enum owl_plane video, u8 contrast)
+{
+	u32 val;
+	
+	val = de_read_reg(DE_OVL_CFG(video));
+	
+	val = REG_SET_VAL(val, contrast, DE_OVL_CFG_CONTRAST_END_BIT, DE_OVL_CFG_CONTRAST_BEGIN_BIT);
+   
+	de_write_reg(DE_OVL_CFG(video), val);
+}
+
+static void de_curosr_enable(enum owl_de_path_id path, bool enable)
+{
+	u32 val;
+
+	val = de_read_reg(DE_PATH_CTL(path));
+	
+	val = REG_SET_VAL(val, enable, DE_PANEL_CURSOR_ENABLE_BIT, DE_PANEL_CURSOR_ENABLE_BIT);
+	
+    de_write_reg(DE_PATH_CTL(path), val);
+
+}
+
+static void de_curosr_set_position(enum owl_de_path_id path, int pos_x, int pos_y)
+{
+	u32 val;
+	
+	u32 screen_size_x = de_read_reg(DE_PATH_SIZE(path)) & 0xfff;
+	u32 screen_size_y = (de_read_reg(DE_PATH_SIZE(path)) >> 16 )& 0xfff;
+	
+	if(pos_x < 0)
+	{
+		pos_x = 0;
+	}
+	
+	if(pos_y < 0)
+	{
+		pos_y = 0;
+	}
+	
+	if(pos_x > screen_size_x)
+	{
+		pos_x = screen_size_x;
+	}
+	
+	if(pos_y > screen_size_y)
+	{
+		pos_y = screen_size_y;
+	}
+	
+	val = ((pos_y & 0xfff) << 16) | (pos_x & 0xfff);
+	
+    de_write_reg(DE_PATH_E_COOR(path), val);
+	
+}
+
+static void de_curosr_set_addr(enum owl_de_path_id path, void *paddr)
+{
+	u32 val;
+	
+	val = ((u32)paddr & 0xFFFFFFFc);
+  
+	de_write_reg(DE_PATH_CURSOR_FB(path), val);
+	
+	
+}
+
+static void de_curosr_set_str(enum owl_de_path_id path, u32 str)
+{
+	u32 val;
+	
+	val = (str & 0xFFF);
+  
+	de_write_reg(DE_PATH_CURSOR_STR(path), val);
+}
+
+static inline void __de_backup_reg(struct de_regs_t *p, int reg)
+{
+	p->reg      = reg;
+	p->value    = de_read_reg(reg);
+}
+
+static void de_backup_regs(void)
+{
+	int i = 0, cnt = 0;
+	struct de_regs_t *reg = de_atm7059_regs;
+	
+	DSSINFO("%s\n", __func__);
+	
+	__de_backup_reg(&reg[cnt++], DE_IRQENABLE);
+	__de_backup_reg(&reg[cnt++], DE_IF_CON);
+	__de_backup_reg(&reg[cnt++], DE_OUTPUT_CON);
+	__de_backup_reg(&reg[cnt++], DE_MMU_EN);
+	__de_backup_reg(&reg[cnt++], DE_MMU_BASE);
+	__de_backup_reg(&reg[cnt++], DE_WB_CON);
+	__de_backup_reg(&reg[cnt++], DE_WB_ADDR);
+
+	if (!owl_de_is_atm7059tc())
+		__de_backup_reg(&reg[cnt++], DE_PATH_DITHER);
+	
+	for(i = 0 ; i < 2 ; i++) {
+		__de_backup_reg(&reg[cnt++], DE_PATH_CTL(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_BK(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_SIZE(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_E_COOR(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_GAMMA_IDX(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_GAMMA_RAM(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_CURSOR_FB(i));
+		__de_backup_reg(&reg[cnt++], DE_PATH_CURSOR_STR(i));
+	}
+
+	for (i = 0 ; i < 4 ; i++) {
+		__de_backup_reg(&reg[cnt++], DE_OVL_CFG(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_ISIZE(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_OSIZE(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SR(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF0(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF1(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF2(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF3(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF4(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF5(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF6(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_SCOEF7(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_BA0(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_BA1UV(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_BA2V(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_3D_RIGHT_BA0(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_3D_RIGHT_BA1UV(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_3D_RIGHT_BA2V(i));
+
+		__de_backup_reg(&reg[cnt++], DE_OVL_STR(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_CRITICAL_CFG(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_REMAPPING(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_COOR(0,i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_ALPHA_CFG(0,i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_CKMAX(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_CKMAX(i));
+		__de_backup_reg(&reg[cnt++], DE_OVL_BLEND(i));
+	}
+
+	de_atm7059_regs_cnt = cnt;
+}
+
+static void de_restore_regs(void)
+{
+	int i;
+	void * noc_reg = 0;		
+	DSSINFO("%s\n", __func__);
+	
+	for (i = 1; i < de_atm7059_regs_cnt; i++) {
+	    de_write_reg(de_atm7059_regs[i].reg, de_atm7059_regs[i].value);
+	}
+
+	noc_reg = ioremap(0xb0500108, 4);  
+	DSSINFO("%s  de_write_reg  addr end %p \n", __func__, noc_reg);
+	writel(0x0f, noc_reg);
+	iounmap(noc_reg);	
+	
+	DSSINFO("%s end\n", __func__);
+}
+
+static void de_special_init(void)
+{
+	u32 val = 0;
+
+	/* max outstanding num for read */
+	val = REG_VAL(0x1F, 21, 16);
+	de_write_reg(DE_IF_CON, val);
+}
+
+static int de_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	de_backup_regs();
+
+	return 0;
+}
+
+static int de_resume(struct platform_device *pdev)
+{
+	de_restore_regs();
+
+	return 0;
+}
+
+
+static void de_dump_regs(void)
+{
+	int i = 0;
+
+#define DUMPREG(r) printk("%08x ~~~~ %08x ~~~ %s ~~ \n", r, de_read_reg(r), #r)
+	DUMPREG(DE_IRQSTATUS);
+	DUMPREG(DE_IRQENABLE);
+	DUMPREG(DE_IF_CON);
+	DUMPREG(DE_MMU_EN);
+	DUMPREG(DE_MMU_BASE);
+	DUMPREG(DE_OUTPUT_CON);
+	DUMPREG(DE_OUTPUT_STAT);
+
+	if (!owl_de_is_atm7059tc())
+		DUMPREG(DE_PATH_DITHER);
+
+	for (i = 0 ; i < 2 ; i++) {
+		printk("\npath %d ------------------>\n", i);
+		DUMPREG(DE_PATH_CTL(i));
+		DUMPREG(DE_PATH_FCR(i));
+		DUMPREG(DE_PATH_EN(i));
+		DUMPREG(DE_PATH_BK(i));
+		DUMPREG(DE_PATH_SIZE(i));
+		DUMPREG(DE_PATH_E_COOR(i));
+		DUMPREG(DE_PATH_GAMMA_IDX(i));
+		DUMPREG(DE_PATH_GAMMA_RAM(i));
+		DUMPREG(DE_PATH_CURSOR_FB(i));
+		DUMPREG(DE_PATH_CURSOR_STR(i));
+	}
+	for (i = 0 ; i < 4 ; i++){
+		printk("\nlayer %d ------------------>\n", i);
+		DUMPREG(DE_OVL_CFG(i));
+		DUMPREG(DE_OVL_ISIZE(i));
+		DUMPREG(DE_OVL_OSIZE(i));
+		DUMPREG(DE_OVL_SR(i));
+		DUMPREG(DE_OVL_SCOEF0(i));
+		DUMPREG(DE_OVL_SCOEF1(i));
+		DUMPREG(DE_OVL_SCOEF2(i));
+		DUMPREG(DE_OVL_SCOEF3(i));
+		DUMPREG(DE_OVL_SCOEF4(i));
+		DUMPREG(DE_OVL_SCOEF5(i));
+		DUMPREG(DE_OVL_SCOEF6(i));
+		DUMPREG(DE_OVL_SCOEF7(i));
+		DUMPREG(DE_OVL_BA0(i));
+		DUMPREG(DE_OVL_BA1UV(i));
+		DUMPREG(DE_OVL_BA2V(i));
+		DUMPREG(DE_OVL_3D_RIGHT_BA0(i));
+		DUMPREG(DE_OVL_3D_RIGHT_BA1UV(i));
+		DUMPREG(DE_OVL_3D_RIGHT_BA2V(i));
+
+		DUMPREG(DE_OVL_STR(i));
+		DUMPREG(DE_OVL_CRITICAL_CFG(i));
+		DUMPREG(DE_OVL_REMAPPING(i));
+		DUMPREG(DE_OVL_CSC(i));
+		DUMPREG(DE_OVL_COOR(0,i));
+		DUMPREG(DE_OVL_ALPHA_CFG(0,i));
+		DUMPREG(DE_OVL_CKMAX(i));
+		DUMPREG(DE_OVL_CKMAX(i));
+		DUMPREG(DE_OVL_BLEND(i));
+	}
+#undef DUMPREG
+}
+
+static ssize_t de_write_regs(const char *buf, size_t len)
+{
+	unsigned int reg, reg_val;
+	char *end_ptr;
+	
+	reg = simple_strtoul(buf, &end_ptr, 16);
+	
+	if (*end_ptr++ == '=') {
+		reg_val = simple_strtoul(end_ptr, NULL,16);        
+		de_write_reg(reg, reg_val);
+	}
+	    
+	printk("reg[0x%x] = 0x%x \n", reg, de_read_reg(reg));
+
+	return len;
+}
+
+static const struct owl_de_hwops de_atm7059_ops = {
+	/* global operations */
+	.irq_status_get		= de_irq_status_get,
+	.irq_status_set		= de_irq_status_set,
+
+	.irq_enable_get		= de_irq_enable_get,
+	.irq_enable_set		= de_irq_enable_set,
+	.irq_to_mask		= de_irq_to_mask,
+	.irq_mask_to_enable	= de_irq_mask_to_enable,
+	.irq_mask_to_vb_mask	= de_irq_mask_to_vb_mask,
+
+	.mmu_config		= de_mmu_config,
+	.mmu_enable		= de_mmu_enable,
+
+	.special_init		= de_special_init,
+
+	.suspend		= de_suspend,
+	.resume			= de_resume,
+
+	/* path operations */
+	.path_enable		= de_path_enable,
+	.path_is_enabled	= de_path_is_enabled,
+
+	.path_size_set		= de_path_size_set,
+
+	.display_type_set	= de_display_type_set,
+
+	.video_enable		= de_video_enable,
+	.video_is_enabled	= de_video_is_enabled,
+	.fcr_set		= de_path_fcr_set,
+	.fcr_get		= de_path_fcr_get,
+
+	.set_gamma_table	= de_gamma_table_set,
+	.get_gamma_table	= de_gamma_table_get,
+	.enable_gamma_table	= de_gamma_table_enable,
+
+	.dither_set		= de_dither_set,
+	.dither_enable		= de_dither_enable,
+
+	/* video layer operations */
+	.format_set		= de_video_format_set,
+	.bypass_enable		= de_video_bypass_enable,
+
+	.fb_addr_set		= de_video_fb_addr_set,
+
+	.isize_set		= de_video_isize_set,
+	.osize_set		= de_video_osize_set,
+	.position_set		= de_video_position_set,
+
+	.scaling_set		= de_video_scaling_set,
+	.rotation_set		= de_video_rotation_set,
+	.alpha_set		= de_video_alpha_set,
+	.str_set		= de_video_str_set,
+	.critical_set		= de_critical_set,
+	.lightness_set  =  de_video_lightness_set,
+	.saturation_set  =  de_video_saturation_set,
+	.contrast_set  =  de_video_contrast_set,
+	
+	/*hardware  cursor*/
+	.curosr_enable = de_curosr_enable,
+	.curosr_set_position = de_curosr_set_position,	
+	.curosr_set_addr = de_curosr_set_addr,	
+	.curosr_set_str = de_curosr_set_str,
+	
+	/* debug oprations */
+	.dump_regs		= de_dump_regs,
+	.write_regs		= de_write_regs,
+};
+
+struct owl_de_pdata owl_de_atm7059 = {
+	.num_paths		= 2,
+	.num_videos		= 4,
+
+	.path_pdata		= de_atm7059_paths,
+	.video_pdata		= de_atm7059_videos,
+
+	.hwops			= &de_atm7059_ops,
+};
+EXPORT_SYMBOL(owl_de_atm7059);
diff --git a/drivers/video/fbdev/owl/dss/de_atm7059.h b/drivers/video/fbdev/owl/dss/de_atm7059.h
new file mode 100755
index 0000000..2e89a6e
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/de_atm7059.h
@@ -0,0 +1,154 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/de_atm7059.h
+ *
+ * NOTE: SHOULD only be included by de_atm7059.c
+ *
+ * Copyright (C) 2014 Actions
+ * Author: lipeng<lipeng at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef _DE_ATM7059_H_
+#define _DE_ATM7059_H_
+
+#include "de.h"
+
+/*================================================================
+ *           Definition of registers and bit position
+ *==============================================================*/
+
+
+/* please fixme */
+#define DE_SIZE_BIT_WIDTH			12
+
+/*
+ * DE common registers
+ */
+#define DE_IRQSTATUS				0x0004
+#define DE_IRQENABLE				0x0000
+#define DE_IF_CON				0x000c
+
+#define DE_MMU_EN				0x0010
+#define DE_MMU_BASE				0x0014
+
+#define DE_OUTPUT_CON				0x1000
+#define DE_OUTPUT_STAT				0x100c
+#define DE_WB_CON				0x1004
+#define DE_WB_ADDR				0x1008
+
+/* dither for path0, only for ATM7059A */
+#define DE_PATH_DITHER				0x150
+
+/*
+ * dehw manager/channel specific registers
+ */
+#define DE_PATH_BASE				0x0100
+#define DE_PATH_CTL(n)				(DE_PATH_BASE + (n) * 0x100  +  0x0000)
+
+#define DE_PATH_EN(n)				DE_PATH_CTL(n)
+#define DE_PATH_ENABLE_BIT			28
+
+#define DE_PATH_FCR(n)				DE_PATH_CTL(n)
+#define DE_PATH_BK(n)				(DE_PATH_BASE + (n) * 0x100  +  0x0020)
+#define DE_PATH_SIZE(n)				(DE_PATH_BASE + (n) * 0x100  +  0x0024)
+#define DE_PATH_E_COOR(n)			(DE_PATH_BASE + (n) * 0x100  +  0x0028)
+
+#define DE_PATH_GAMMA_IDX(n)			(DE_PATH_BASE + (n) * 0x100  +  0x002C)
+#define DE_PATH_GAMMA_IDX_BUSY_BIT		(14)
+#define DE_PATH_GAMMA_IDX_OP_SEL_BEGIN_BIT	(12)
+#define DE_PATH_GAMMA_IDX_OP_SEL_END_BIT	(13)
+#define DE_PATH_GAMMA_IDX_INDEX_BEGIN_BIT	(0)
+#define DE_PATH_GAMMA_IDX_INDEX_END_BIT		(7)
+
+#define DE_PATH_GAMMA_RAM(n)			(DE_PATH_BASE + (n) * 0x100  +  0x0030)
+
+#define DE_PATH_CURSOR_FB(n)			(DE_PATH_BASE + (n) * 0x100  +  0x0034)
+#define DE_PATH_CURSOR_STR(n)			(DE_PATH_BASE + (n) * 0x100  +  0x0038)
+
+/* DE overlay registers */
+#define DE_OVL_BASE				0x0400
+#define DE_OVL_CFG(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0000)
+#define DE_OVL_ISIZE(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0004)
+#define DE_OVL_OSIZE(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0008)
+#define DE_OVL_SR(n)				(DE_OVL_BASE + (n) * 0x100  +  0x000c)
+#define DE_OVL_SCOEF0(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0010)
+#define DE_OVL_SCOEF1(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0014)
+#define DE_OVL_SCOEF2(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0018)
+#define DE_OVL_SCOEF3(n)			(DE_OVL_BASE + (n) * 0x100  +  0x001c)
+#define DE_OVL_SCOEF4(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0020)
+#define DE_OVL_SCOEF5(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0024)
+#define DE_OVL_SCOEF6(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0028)
+#define DE_OVL_SCOEF7(n)			(DE_OVL_BASE + (n) * 0x100  +  0x002c)
+#define DE_OVL_BA0(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0030)
+#define DE_OVL_BA1UV(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0034)
+#define DE_OVL_BA2V(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0038)
+#define DE_OVL_3D_RIGHT_BA0(n)			(DE_OVL_BASE + (n) * 0x100  +  0x003C)
+#define DE_OVL_3D_RIGHT_BA1UV(n)		(DE_OVL_BASE + (n) * 0x100  +  0x0040)
+#define DE_OVL_3D_RIGHT_BA2V(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0044)
+#define DE_OVL_STR(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0048)
+#define DE_OVL_CRITICAL_CFG(n)			(DE_OVL_BASE + (n) * 0x100  +  0x004c)
+#define DE_OVL_REMAPPING(n)			(DE_OVL_BASE + (n) * 0x100  +  0x0050)
+#define DE_OVL_CKMAX(n)				(DE_OVL_BASE + (n) * 0x100  +  0x005c)
+#define DE_OVL_CKMIN(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0060)
+#define DE_OVL_BLEND(n)				(DE_OVL_BASE + (n) * 0x100  +  0x0064)
+
+#define DE_OVL_COOR(m, n)			(DE_OVL_BASE + (n) * 0x100  +  0x0054)
+#define DE_OVL_ALPHA_CFG(m, n)			(DE_OVL_BASE + (n) * 0x100  +  0x0058)
+#define DE_OVL_ALPHA_ENABLE(m, n)		DE_OVL_BLEND(n)
+#define DE_PATH_GAMMA_ENABLE(n)			DE_PATH_CTL(n)
+#define DE_PATH_GAMMA_ENABLE_BIT		(9)
+
+#define DE_OVL_CSC(n)				DE_OVL_CFG(n)
+#define DE_OVL_CSC_CON_BEGIN_BIT		4
+#define DE_OVL_CSC_CON_END_BIT			7
+#define DE_OVL_CSC_STA_BEGIN_BIT		8
+#define DE_OVL_CSC_STA_END_BIT			11
+#define DE_OVL_CSC_BRI_BEGIN_BIT		12
+#define DE_OVL_CSC_BRI_END_BIT			19
+#define DE_OVL_CSC_BYPASS_BIT			0
+
+#define DE_OVL_CFG_FLIP_BIT			20
+#define DE_OVL_CFG_FMT_BEGIN_BIT		0
+#define DE_OVL_CFG_FMT_END_BIT			2
+#define DE_OVL_CFG_BYPASS_BIT			3
+#define DE_OVL_CFG_CONTRAST_BEGIN_BIT       4
+#define DE_OVL_CFG_CONTRAST_END_BIT         7
+#define DE_OVL_CFG_SATURATION_BEGIN_BIT     8
+#define DE_OVL_CFG_SATURATION_END_BIT       11
+#define DE_OVL_CFG_LIGHTNESS_BEGIN_BIT      12
+#define DE_OVL_CFG_LIGHTNESS_END_BIT        19
+#define DE_OVL_CFG_CRITICAL_CTL_BEGIN_BIT	26
+#define DE_OVL_CFG_CRITICAL_CTL_END_BIT		27
+
+#define DE_OVL_ALPHA_CFG_PRE_MUTI_BIT		8
+#define DE_OVL_ALPHA_CFG_VALUE_BEGIN_BIT	0
+#define DE_OVL_ALPHA_CFG_VALUE_END_BIT		7
+#define DE_OVL_ALPHA_CFG_ENABLE_BEGIN_BIT	0
+#define DE_OVL_ALPHA_CFG_ENABLE_END_BIT		0
+
+#define DE_OUTPUT_PATH1_DEVICE_BEGIN_BIT	0
+#define DE_OUTPUT_PATH1_DEVICE_END_BIT		2
+#define DE_OUTPUT_PATH2_DEVICE_BEGIN_BIT	4
+#define DE_OUTPUT_PATH2_DEVICE_END_BIT		6
+
+#define DE_PATH_CTL_IYUV_QEN_BIT		16
+#define DE_PATH_CTL_YUV_FMT_BIT			15
+#define DE_PATH_CTL_ILACE_BIT			11
+#define DE_PATH_CTL_GAMMA_ENABLE_BIT		9
+
+#define DE_PANEL_ENABLE_BIT			20
+#define DE_PANEL_CURSOR_ENABLE_BIT	24
+#define DE_PATH_FCR_BIT				29
+
+#endif
diff --git a/drivers/video/fbdev/owl/dss/display.c b/drivers/video/fbdev/owl/dss/display.c
new file mode 100755
index 0000000..bd765f4
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/display.c
@@ -0,0 +1,417 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/display.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "DISPLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+static ssize_t display_enabled_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+	bool enabled = dssdev->state != OWL_DSS_DISPLAY_DISABLED;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", enabled);
+}
+
+static ssize_t display_enabled_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t size)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+	int r;
+	bool enabled;
+
+	r = strtobool(buf, &enabled);
+	if (r)
+		return r;
+
+	if (enabled != (dssdev->state != OWL_DSS_DISPLAY_DISABLED)) {
+		if (enabled) {
+			r = dssdev->driver->enable(dssdev);
+			if (r)
+				return r;
+		} else {
+			dssdev->driver->disable(dssdev);
+		}
+	}
+
+	return size;
+}
+
+static ssize_t display_timings_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+	struct owl_video_timings t;
+
+	if (!dssdev->driver->get_timings)
+		return -ENOENT;
+
+	dssdev->driver->get_timings(dssdev, &t);
+
+	return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
+			t.pixel_clock,
+			t.x_res, t.hfp, t.hbp, t.hsw,
+			t.y_res, t.vfp, t.vbp, t.vsw);
+}
+
+static ssize_t display_timings_store(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t size)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+	struct owl_video_timings t;
+	int r, found;
+
+	if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
+		return -ENOENT;
+
+	found = 0;
+
+	if (!found && sscanf(buf, "%u,%hu/%hu/%hu/%hu,%hu/%hu/%hu/%hu",
+				&t.pixel_clock,
+				&t.x_res, &t.hfp, &t.hbp, &t.hsw,
+				&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
+		return -EINVAL;
+
+	r = dssdev->driver->check_timings(dssdev, &t);
+	if (r)
+		return r;
+
+	dssdev->driver->set_timings(dssdev, &t);
+
+	return size;
+}
+
+static DEVICE_ATTR(enabled, S_IRUGO|S_IWUSR,
+		display_enabled_show, display_enabled_store);
+static DEVICE_ATTR(timings, S_IRUGO|S_IWUSR,
+		display_timings_show, display_timings_store);
+
+static struct device_attribute *display_sysfs_attrs[] = {
+	&dev_attr_enabled,
+	&dev_attr_timings,
+	NULL
+};
+
+void owl_default_get_resolution(struct owl_dss_device *dssdev,
+			u16 *xres, u16 *yres)
+{
+	*xres = dssdev->timings.x_res;
+	*yres = dssdev->timings.y_res;
+}
+EXPORT_SYMBOL(owl_default_get_resolution);
+
+int owl_default_get_recommended_bpp(struct owl_dss_device *dssdev)
+{
+	switch (dssdev->type) {
+	case OWL_DISPLAY_TYPE_LCD:
+	case OWL_DISPLAY_TYPE_DSI:
+	case OWL_DISPLAY_TYPE_EDP:
+		if (dssdev->data_lines == 24)
+			return 24;
+		else
+			return 16;
+	case OWL_DISPLAY_TYPE_CVBS:
+	case OWL_DISPLAY_TYPE_YPBPR:
+	case OWL_DISPLAY_TYPE_HDMI:
+		if (dssdev->data_lines == 24)
+			return 24;
+		else
+			return 24;
+	default:
+		BUG();
+	}
+}
+EXPORT_SYMBOL(owl_default_get_recommended_bpp);
+
+/* Checks if replication logic should be used. Only use for active matrix,
+ * when overlay is in RGB12U or RGB16 mode, and LCD interface is
+ * 18bpp or 24bpp */
+bool dss_use_replication(struct owl_dss_device *dssdev,
+		enum owl_color_mode mode)
+{
+	int bpp;
+	switch (dssdev->type) {
+	case OWL_DISPLAY_TYPE_LCD:
+	case OWL_DISPLAY_TYPE_DSI:
+	case OWL_DISPLAY_TYPE_EDP:
+		bpp = dssdev->data_lines;
+		break;
+	case OWL_DISPLAY_TYPE_HDMI:
+	case OWL_DISPLAY_TYPE_CVBS:
+	case OWL_DISPLAY_TYPE_YPBPR:
+		bpp = dssdev->data_lines;
+		break;
+	default:
+		BUG();
+	}
+
+	return bpp > 16;
+}
+
+void dss_init_device(struct platform_device *pdev,
+		struct owl_dss_device *dssdev)
+{
+	struct device_attribute *attr;
+	int i = 0;
+	int r = 0;
+
+	/* create device sysfs files */
+	while ((attr = display_sysfs_attrs[i++]) != NULL) {
+		r = device_create_file(&dssdev->dev, attr);
+		if (r)
+			DSSERR("failed to create sysfs file\n");
+	}
+
+	/* create display? sysfs links */
+	r = sysfs_create_link(&pdev->dev.kobj, &dssdev->dev.kobj,
+			dev_name(&dssdev->dev));
+	if (r)
+		DSSERR("failed to create sysfs display link\n");
+}
+
+void dss_uninit_device(struct platform_device *pdev,
+		struct owl_dss_device *dssdev)
+{
+	struct device_attribute *attr;
+	int i = 0;
+
+	sysfs_remove_link(&pdev->dev.kobj, dev_name(&dssdev->dev));
+
+	while ((attr = display_sysfs_attrs[i++]) != NULL)
+		device_remove_file(&dssdev->dev, attr);
+
+	if (dssdev->manager)
+		dssdev->manager->unset_device(dssdev->manager);
+}
+atomic_t devices_suspended = ATOMIC_INIT(false);
+int dss_suspend_all_devices(void)
+{
+    struct owl_dss_device *dssdev = NULL;
+    
+	atomic_set(&devices_suspended,true);
+	
+    for_each_dss_dev(dssdev) {
+        if (!dssdev->driver)
+            continue;
+			
+        if (dssdev->state == OWL_DSS_DISPLAY_ACTIVE) {
+            if (dssdev->driver->disable) {
+                dssdev->driver->disable(dssdev);
+            }
+            dssdev->activate_after_resume = true;
+        } else {
+            dssdev->activate_after_resume = false;
+        }		
+	
+		if (dssdev->driver->suspend) {
+			dssdev->driver->suspend(dssdev);
+		}
+
+    }
+
+	return 0;
+}
+
+int dss_resume_all_devices(void)
+{
+    struct owl_dss_device *dssdev = NULL;
+	
+    for_each_dss_dev(dssdev) {
+        if (!dssdev->driver)
+            continue;
+			
+		if (dssdev->driver->resume) {
+			dssdev->driver->resume(dssdev);
+		}
+		
+        if (dssdev->activate_after_resume) {
+            if (dssdev->driver->enable) {
+                dssdev->driver->enable(dssdev);
+            }
+            dssdev->activate_after_resume = false;
+        }
+    }
+	atomic_set(&devices_suspended,false);
+	
+    return 0;
+}
+
+static int dss_disable_device(struct device *dev, void *data)
+{
+	struct owl_dss_device *dssdev = to_dss_device(dev);
+
+	if (dssdev->state != OWL_DSS_DISPLAY_DISABLED)
+		dssdev->driver->disable(dssdev);
+
+	return 0;
+}
+
+void dss_disable_all_devices(void)
+{
+	struct bus_type *bus = dss_get_bus();
+	bus_for_each_dev(bus, NULL, NULL, dss_disable_device);
+}
+
+#define max_display_cnt 3
+char lcd_node_compatible[max_display_cnt][32]={
+	"actions,owl-lcd",
+	"actions,owl-dsi",
+	"actions,owl-edp",
+};
+
+enum owl_display_type get_current_display_type(void)
+{
+	int i;
+	const char              *portname;
+	struct device_node *np=NULL;
+	enum owl_display_type display_type;
+	
+	display_type = OWL_DISPLAY_TYPE_NONE;
+	
+	for(i=0; i<max_display_cnt; i++) {
+		np = of_find_compatible_node(NULL, NULL, lcd_node_compatible[i]);
+		if (!np) {
+			//DSSERR("failed to find %s node\n", lcd_node_compatible[i]);
+			continue ;
+		} else {
+			if (!of_property_read_string(np, "port_type", &portname)) {
+				printk(" %d portname = %s\n", i, portname);
+				if(!strcmp("rgb", portname)){
+					display_type = OWL_DISPLAY_TYPE_LCD;	
+				}else if(!strcmp("lvds", portname)){
+					display_type = OWL_DISPLAY_TYPE_LCD;	
+				}else if(!strcmp("dsi", portname)){
+					display_type = OWL_DISPLAY_TYPE_DSI;		
+				}else if(!strcmp("edp", portname)){
+					display_type = OWL_DISPLAY_TYPE_EDP;	
+				}
+				break;
+			}		
+		}
+	}
+	
+	return display_type;
+}
+EXPORT_SYMBOL(get_current_display_type);
+
+void owl_dss_get_device(struct owl_dss_device *dssdev)
+{
+	get_device(&dssdev->dev);
+}
+EXPORT_SYMBOL(owl_dss_get_device);
+
+void owl_dss_put_device(struct owl_dss_device *dssdev)
+{
+	put_device(&dssdev->dev);
+}
+EXPORT_SYMBOL(owl_dss_put_device);
+
+/* ref count of the found device is incremented. ref count
+ * of from-device is decremented. */
+struct owl_dss_device *owl_dss_get_next_device(struct owl_dss_device *from)
+{
+	struct device *dev;
+	struct device *dev_start = NULL;
+	struct owl_dss_device *dssdev = NULL;
+
+	int match(struct device *dev, void *data)
+	{
+		return 1;
+	}
+
+	if (from)
+		dev_start = &from->dev;
+	dev = bus_find_device(dss_get_bus(), dev_start, NULL, match);
+	if (dev)
+		dssdev = to_dss_device(dev);
+	if (from)
+		put_device(&from->dev);
+
+	return dssdev;
+}
+EXPORT_SYMBOL(owl_dss_get_next_device);
+
+struct owl_dss_device *owl_dss_find_device(void *data,
+		int (*match)(struct owl_dss_device *dssdev, void *data))
+{
+	struct owl_dss_device *dssdev = NULL;
+
+	while ((dssdev = owl_dss_get_next_device(dssdev)) != NULL) {
+		if (match(dssdev, data))
+			return dssdev;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(owl_dss_find_device);
+
+
+struct owl_dss_device *owl_dss_find_device_by_type(enum owl_display_type type)
+{
+	struct owl_dss_device *dssdev = NULL;
+
+	while ((dssdev = owl_dss_get_next_device(dssdev)) != NULL) {
+		if (dssdev->type == type)
+			return dssdev;
+	}
+	return NULL;
+}
+EXPORT_SYMBOL(owl_dss_find_device_by_type);
+
+int owl_dss_start_device(struct owl_dss_device *dssdev)
+{
+	if (!dssdev->driver) {
+		DSSDBG("no driver\n");
+		return -ENODEV;
+	}
+
+	if (!try_module_get(dssdev->dev.driver->owner)) {
+		return -ENODEV;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(owl_dss_start_device);
+
+void owl_dss_stop_device(struct owl_dss_device *dssdev)
+{
+	module_put(dssdev->dev.driver->owner);
+}
+EXPORT_SYMBOL(owl_dss_stop_device);
+
+bool owl_dss_is_devices_suspended(void)
+{
+	return atomic_read(&devices_suspended);
+}
+EXPORT_SYMBOL(owl_dss_is_devices_suspended);
+
diff --git a/drivers/video/fbdev/owl/dss/dss.h b/drivers/video/fbdev/owl/dss/dss.h
new file mode 100755
index 0000000..a8786a4
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/dss.h
@@ -0,0 +1,161 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/dss.h
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __OWL_DSS_H
+#define __OWL_DSS_H
+
+#include <video/owldss.h>
+#include <linux/platform_device.h>
+
+
+/*{====================debug macro==========================*/
+#ifdef CONFIG_OWL_DSS_DEBUG_SUPPORT
+	#define DSS_DEBUG_ENABLE
+#endif
+
+#define DSS_DEBUG_ENABLE
+
+#ifndef DSS_SUBSYS_NAME
+	#define SUBSYS_NAME		"owl_dss: "
+#else
+	#define SUBSYS_NAME		"owl_dss " DSS_SUBSYS_NAME ": "
+#endif
+
+#ifdef DSS_DEBUG_ENABLE
+	extern int owl_dss_debug;
+	#define DSSDBG(format, ...) \
+		do { \
+			if (owl_dss_debug > 1) \
+				printk(KERN_DEBUG SUBSYS_NAME format, ## __VA_ARGS__); \
+	        } while (0)
+
+	#define DSSDBGF(format, ...) \
+		do { \
+			if (owl_dss_debug > 1) \
+				printk(KERN_DEBUG SUBSYS_NAME "%s," format,\
+					 __func__, ## __VA_ARGS__); \
+	        } while (0)
+
+	#define DSSINFO(format, ...) \
+		do { \
+			if (owl_dss_debug > 0) \
+				printk(KERN_INFO SUBSYS_NAME format, ## __VA_ARGS__); \
+	        } while (0)
+
+#else
+	#define DSSDBG(format, ...)
+	#define DSSDBGF(format, ...)
+	#define DSSINFO(format, ...)
+#endif
+
+#define DSSERR(format, ...) \
+	printk(KERN_ERR SUBSYS_NAME "error!" format, ## __VA_ARGS__);
+/*====================debug macro end==========================}*/
+
+
+/* core */
+struct bus_type *dss_get_bus(void);
+
+int dss_mgr_wait_for_go(struct owl_overlay_manager *mgr);
+
+int dss_mgr_enable(struct owl_overlay_manager *mgr);
+void dss_mgr_disable(struct owl_overlay_manager *mgr);
+int dss_mgr_set_info(struct owl_overlay_manager *mgr,
+		struct owl_overlay_manager_info *info);
+void dss_mgr_get_info(struct owl_overlay_manager *mgr,
+		struct owl_overlay_manager_info *info);
+int dss_mgr_set_device(struct owl_overlay_manager *mgr,
+		struct owl_dss_device *dssdev);
+int dss_mgr_unset_device(struct owl_overlay_manager *mgr);
+
+bool dss_ovl_is_enabled(struct owl_overlay *ovl);
+int dss_ovl_enable(struct owl_overlay *ovl);
+int dss_ovl_disable(struct owl_overlay *ovl);
+int dss_ovl_set_info(struct owl_overlay *ovl,
+		struct owl_overlay_info *info);
+void dss_ovl_get_info(struct owl_overlay *ovl,
+		struct owl_overlay_info *info);
+int dss_ovl_set_manager(struct owl_overlay *ovl,
+		struct owl_overlay_manager *mgr);
+int dss_ovl_unset_manager(struct owl_overlay *ovl);
+
+/* display */
+int dss_suspend_all_devices(void);
+int dss_resume_all_devices(void);
+void dss_disable_all_devices(void);
+
+void dss_init_device(struct platform_device *pdev,
+		struct owl_dss_device *dssdev);
+void dss_uninit_device(struct platform_device *pdev,
+		struct owl_dss_device *dssdev);
+bool dss_use_replication(struct owl_dss_device *dssdev,
+		enum owl_color_mode mode);
+void default_get_overlay_fifo_thresholds(enum owl_plane plane,
+		u32 fifo_size, u32 burst_size,
+		u32 *fifo_low, u32 *fifo_high);
+
+/* manager */
+int dss_init_overlay_managers(struct platform_device *pdev);
+void dss_uninit_overlay_managers(struct platform_device *pdev);
+int dss_mgr_simple_check(struct owl_overlay_manager *mgr,
+		const struct owl_overlay_manager_info *info);
+int dss_mgr_check(struct owl_overlay_manager *mgr,
+		struct owl_dss_device *dssdev,
+		struct owl_overlay_manager_info *info,
+		struct owl_overlay_info **overlay_infos);
+
+/* overlay */
+void dss_init_overlays(struct platform_device *pdev);
+void dss_uninit_overlays(struct platform_device *pdev);
+void dss_recheck_connections(struct owl_dss_device *dssdev, bool force);
+int dss_ovl_simple_check(struct owl_overlay *ovl,const struct owl_overlay_info *info);
+int dss_ovl_check(struct owl_overlay *ovl,	struct owl_overlay_info *info, struct owl_dss_device *dssdev);
+
+/* DSS */
+int dss_init_platform_device(void)__init;
+void dss_uninit_platform_device(void);
+
+int dss_init_platform_driver(void)__init;
+void dss_uninit_platform_driver(void);
+
+int dss_runtime_get(void);
+void dss_runtime_put(void);
+
+void owl_de_suspend(void);
+void owl_de_resume(void);
+
+#ifdef CONFIG_VIDEO_OWL_MMU_SUPPORT
+int mmu_init(void);
+
+/* map virtual address to device address */
+int mmu_va_to_da(u64 va, u32 length, u32 *da);
+
+/* map ION fd to device address */
+int mmu_fd_to_da(u64 buffer_id, u32 *da);
+
+#else
+static inline int mmu_init(void) { return -1; }
+static inline int mmu_va_to_da(u64 va, u32 length, u32 *da) { return -1; }
+static inline int mmu_fd_to_da(u64 buffer_id, u32 *da) { return -1; }
+#endif
+
+#endif
diff --git a/drivers/video/fbdev/owl/dss/dss_features.c b/drivers/video/fbdev/owl/dss/dss_features.c
new file mode 100755
index 0000000..d5266fa
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/dss_features.c
@@ -0,0 +1,228 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/dss_features.c
+ *
+ * Copyright (C) 2010 Actions
+ * Author: Hui Wang <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+
+/* Defines a generic owl register field */
+struct dss_reg_field {
+	u8 start, end;
+};
+
+struct dss_param_range {
+	int min, max;
+};
+
+struct owl_dss_features {
+	const struct dss_reg_field *reg_fields;
+	const int num_reg_fields;
+
+	const u32 has_feature;
+
+	const int num_mgrs;
+	const int num_ovls;
+	const enum owl_display_type *supported_displays;
+	const enum owl_color_mode *supported_color_modes;
+	const enum owl_overlay_caps *overlay_caps;
+	const char * const *clksrc_names;
+	const struct dss_param_range *dss_params;
+
+	const u32 buffer_size_unit;
+	const u32 burst_size_unit;
+};
+
+/* This struct is assigned to one of the below during initialization */
+static const struct owl_dss_features *owl_current_dss_features;
+
+
+static const enum owl_display_type owl_dss_supported_displays[] = {	
+	/* OWL_DSS_CHANNEL_LCD */
+	OWL_DISPLAY_TYPE_LCD | OWL_DISPLAY_TYPE_DSI | OWL_DISPLAY_TYPE_EDP | OWL_DISPLAY_TYPE_CVBS |
+	OWL_DISPLAY_TYPE_HDMI ,	
+	
+	/* OWL_DSS_CHANNEL_DIGIT */
+	OWL_DISPLAY_TYPE_HDMI | OWL_DISPLAY_TYPE_LCD | OWL_DISPLAY_TYPE_DSI | OWL_DISPLAY_TYPE_CVBS ,	
+
+};
+
+
+static const enum owl_color_mode owl_dss_supported_color_modes[] = {
+	/* OWL_DSS_VIDEO1 */
+	OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16 |
+	OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32 |
+	OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32 |
+	OWL_DSS_COLOR_RGBX32 | OWL_DSS_COLOR_XBGR32 | OWL_DSS_COLOR_XRGB32 |
+	OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21 |
+	OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16 |
+	OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16 ,
+
+	/* OWL_DSS_VIDEO2 */
+	OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16 |
+	OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32 |
+	OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32 |
+	OWL_DSS_COLOR_RGBX32 | OWL_DSS_COLOR_XBGR32 | OWL_DSS_COLOR_XRGB32 |
+	OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21 |
+	OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16 |
+	OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16 ,
+
+    /* OWL_DSS_VIDEO3 */
+	OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16 |
+	OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32 |
+	OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32 |
+	OWL_DSS_COLOR_RGBX32 | OWL_DSS_COLOR_XBGR32 | OWL_DSS_COLOR_XRGB32 |
+	OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21 |
+	OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16 |
+	OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16 ,
+	/* OWL_DSS_VIDEO4 */
+	OWL_DSS_COLOR_RGB16 | OWL_DSS_COLOR_BGR16 |
+	OWL_DSS_COLOR_ARGB32 | OWL_DSS_COLOR_ABGR32 |
+	OWL_DSS_COLOR_RGBA32 | OWL_DSS_COLOR_BGRA32 |
+	OWL_DSS_COLOR_RGBX32 | OWL_DSS_COLOR_XBGR32 | OWL_DSS_COLOR_XRGB32 |
+	OWL_DSS_COLOR_YU12 | OWL_DSS_COLOR_NV12 | OWL_DSS_COLOR_NV21 |
+	OWL_DSS_COLOR_ARGB16 | OWL_DSS_COLOR_ABGR16 |
+	OWL_DSS_COLOR_RGBA16 | OWL_DSS_COLOR_BGRA16 ,
+	
+};
+static const enum owl_overlay_caps owl_dss_overlay_caps[] = {
+	/* OWL_DSS_VIDEO0 */
+	OWL_DSS_OVL_CAP_SCALE | OWL_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OWL_DSS_OVL_CAP_PRE_MULT_ALPHA | OWL_DSS_OVL_CAP_ZORDER,
+
+	/* OWL_DSS_VIDEO1 */
+	OWL_DSS_OVL_CAP_SCALE | OWL_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OWL_DSS_OVL_CAP_PRE_MULT_ALPHA | OWL_DSS_OVL_CAP_ZORDER,
+
+	/* OWL_DSS_VIDEO2 */
+	OWL_DSS_OVL_CAP_SCALE | OWL_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OWL_DSS_OVL_CAP_PRE_MULT_ALPHA | OWL_DSS_OVL_CAP_ZORDER,
+
+	/* OWL_DSS_VIDEO3 */
+	OWL_DSS_OVL_CAP_SCALE | OWL_DSS_OVL_CAP_GLOBAL_ALPHA |
+		OWL_DSS_OVL_CAP_PRE_MULT_ALPHA | OWL_DSS_OVL_CAP_ZORDER,
+};
+
+/* OWL4 DSS Features */
+/* For all the other OWL4 versions */
+static const struct owl_dss_features owl_dss_features = {
+
+	.has_feature	=
+		FEAT_MGR_LCD2 |
+		FEAT_CORE_CLK_DIV | FEAT_LCD_CLK_SRC |
+		FEAT_DSI_DCS_CMD_CONFIG_VC | FEAT_DSI_VC_OCP_WIDTH |
+		FEAT_DSI_GNQ | FEAT_HDMI_CTS_SWMODE |
+		FEAT_HANDLE_UV_SEPARATE | FEAT_ATTR2 | FEAT_CPR |
+		FEAT_PRELOAD | FEAT_FIR_COEF_V | FEAT_ALPHA_FREE_ZORDER,
+
+	.num_mgrs = 2,
+	.num_ovls = 4,
+	.supported_displays = owl_dss_supported_displays,
+	.supported_color_modes = owl_dss_supported_color_modes,
+	.overlay_caps = owl_dss_overlay_caps,
+	.buffer_size_unit = 16,
+	.burst_size_unit = 16,
+};
+
+/* Functions returning values related to a DSS feature */
+int dss_feat_get_num_mgrs(void)
+{
+	return owl_current_dss_features->num_mgrs;
+}
+
+int dss_feat_get_num_ovls(void)
+{
+	return owl_current_dss_features->num_ovls;
+}
+
+unsigned long dss_feat_get_param_min(enum dss_range_param param)
+{
+	return owl_current_dss_features->dss_params[param].min;
+}
+
+unsigned long dss_feat_get_param_max(enum dss_range_param param)
+{
+	return owl_current_dss_features->dss_params[param].max;
+}
+
+enum owl_display_type dss_feat_get_supported_displays(enum owl_de_path_id channel)
+{
+	return owl_current_dss_features->supported_displays[channel];
+}
+
+enum owl_color_mode dss_feat_get_supported_color_modes(enum owl_plane plane)
+{
+	return owl_current_dss_features->supported_color_modes[plane];
+}
+
+enum owl_overlay_caps dss_feat_get_overlay_caps(enum owl_plane plane)
+{
+	return owl_current_dss_features->overlay_caps[plane];
+}
+
+bool dss_feat_color_mode_supported(enum owl_plane plane,
+		enum owl_color_mode color_mode)
+{
+	if(color_mode == OWL_DSS_COLOR_RGB16){
+		return true;
+	}
+	return owl_current_dss_features->supported_color_modes[plane] &
+			color_mode;
+}
+
+const char *dss_feat_get_clk_source_name(enum owl_dss_clk_source id)
+{
+	return owl_current_dss_features->clksrc_names[id];
+}
+
+u32 dss_feat_get_buffer_size_unit(void)
+{
+	return owl_current_dss_features->buffer_size_unit;
+}
+
+u32 dss_feat_get_burst_size_unit(void)
+{
+	return owl_current_dss_features->burst_size_unit;
+}
+
+/* DSS has_feature check */
+bool dss_has_feature(enum dss_feat_id id)
+{
+	return owl_current_dss_features->has_feature & id;
+}
+
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end)
+{
+	if (id >= owl_current_dss_features->num_reg_fields)
+		BUG();
+
+	*start = owl_current_dss_features->reg_fields[id].start;
+	*end = owl_current_dss_features->reg_fields[id].end;
+}
+
+void dss_features_init(void)
+{
+    /* should asigned feature accrording to ARCH, TODO */
+    owl_current_dss_features = &owl_dss_features;
+}
diff --git a/drivers/video/fbdev/owl/dss/dss_features.h b/drivers/video/fbdev/owl/dss/dss_features.h
new file mode 100755
index 0000000..4d5bcd9
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/dss_features.h
@@ -0,0 +1,111 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/dss_features.h
+ *
+ * Copyright (C) 2010 Actions
+ * Author: Hui Wang <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __OWL_DSS_FEATURES_H
+#define __OWL_DSS_FEATURES_H
+
+#include <video/owldss.h>
+
+#define MAX_DSS_MANAGERS	2
+#define MAX_DSS_OVERLAYS	4
+#define MAX_DSS_LCD_MANAGERS	1
+#define MAX_NUM_LCD		1
+
+/* DSS has feature id */
+enum dss_feat_id {
+	FEAT_LCDENABLEPOL		= 1 << 3,
+	FEAT_LCDENABLESIGNAL		= 1 << 4,
+	FEAT_PCKFREEENABLE		= 1 << 5,
+	FEAT_FUNCGATED			= 1 << 6,
+	FEAT_MGR_LCD2			= 1 << 7,
+	FEAT_LINEBUFFERSPLIT		= 1 << 8,
+	FEAT_ROWREPEATENABLE		= 1 << 9,
+	FEAT_RESIZECONF			= 1 << 10,
+	/* Independent core clk divider */
+	FEAT_CORE_CLK_DIV		= 1 << 11,
+	FEAT_LCD_CLK_SRC		= 1 << 12,
+	/* DSI-PLL power command 0x3 is not working */
+	FEAT_DSI_PLL_PWR_BUG		= 1 << 13,
+	FEAT_DSI_PLL_FREQSEL		= 1 << 14,
+	FEAT_DSI_DCS_CMD_CONFIG_VC	= 1 << 15,
+	FEAT_DSI_VC_OCP_WIDTH		= 1 << 16,
+	FEAT_DSI_REVERSE_TXCLKESC	= 1 << 17,
+	FEAT_DSI_GNQ			= 1 << 18,
+	FEAT_HDMI_CTS_SWMODE		= 1 << 19,
+	FEAT_HANDLE_UV_SEPARATE         = 1 << 20,
+	FEAT_ATTR2                      = 1 << 21,
+	FEAT_VENC_REQUIRES_TV_DAC_CLK	= 1 << 22,
+	FEAT_CPR			= 1 << 23,
+	FEAT_PRELOAD			= 1 << 24,
+	FEAT_FIR_COEF_V			= 1 << 25,
+	FEAT_ALPHA_FIXED_ZORDER		= 1 << 26,
+	FEAT_ALPHA_FREE_ZORDER		= 1 << 27,
+};
+
+/* DSS register field id */
+enum dss_feat_reg_field {
+	FEAT_REG_FIRHINC,
+	FEAT_REG_FIRVINC,
+	FEAT_REG_FIFOHIGHTHRESHOLD,
+	FEAT_REG_FIFOLOWTHRESHOLD,
+	FEAT_REG_FIFOSIZE,
+	FEAT_REG_HORIZONTALACCU,
+	FEAT_REG_VERTICALACCU,
+	FEAT_REG_DISPC_CLK_SWITCH,
+	FEAT_REG_DSIPLL_REGN,
+	FEAT_REG_DSIPLL_REGM,
+	FEAT_REG_DSIPLL_REGM_DISPC,
+	FEAT_REG_DSIPLL_REGM_DSI,
+};
+
+enum dss_range_param {
+	FEAT_PARAM_DSS_FCK,
+	FEAT_PARAM_DSS_PCD,
+	FEAT_PARAM_DSIPLL_REGN,
+	FEAT_PARAM_DSIPLL_REGM,
+	FEAT_PARAM_DSIPLL_REGM_DISPC,
+	FEAT_PARAM_DSIPLL_REGM_DSI,
+	FEAT_PARAM_DSIPLL_FINT,
+	FEAT_PARAM_DSIPLL_LPDIV,
+	FEAT_PARAM_DOWNSCALE,
+	FEAT_PARAM_LINEWIDTH,
+};
+
+/* DSS Feature Functions */
+int dss_feat_get_num_mgrs(void);
+int dss_feat_get_num_ovls(void);
+unsigned long dss_feat_get_param_min(enum dss_range_param param);
+unsigned long dss_feat_get_param_max(enum dss_range_param param);
+enum owl_display_type dss_feat_get_supported_displays(enum owl_de_path_id channel);
+enum owl_color_mode dss_feat_get_supported_color_modes(enum owl_plane plane);
+enum owl_overlay_caps dss_feat_get_overlay_caps(enum owl_plane plane);
+bool dss_feat_color_mode_supported(enum owl_plane plane,
+		enum owl_color_mode color_mode);
+const char *dss_feat_get_clk_source_name(enum owl_dss_clk_source id);
+
+u32 dss_feat_get_buffer_size_unit(void);	/* in bytes */
+u32 dss_feat_get_burst_size_unit(void);		/* in bytes */
+
+bool dss_has_feature(enum dss_feat_id id);
+void dss_feat_get_reg_field(enum dss_feat_reg_field id, u8 *start, u8 *end);
+void dss_features_init(void);
+#if defined(CONFIG_OWL4_DSS_HDMI)
+void dss_init_hdmi_ip_ops(struct hdmi_ip_data *ip_data);
+#endif
+#endif
diff --git a/drivers/video/fbdev/owl/dss/manager.c b/drivers/video/fbdev/owl/dss/manager.c
new file mode 100755
index 0000000..b85a613
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/manager.c
@@ -0,0 +1,1184 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/manager.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "MANAGER"
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/kthread.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "de.h"
+#include "dss_features.h"
+
+static int num_managers;
+static struct owl_overlay_manager *managers;
+
+/* protects dss_data */
+//static spinlock_t data_lock;
+
+/* lock for blocking functions */
+static DEFINE_MUTEX(apply_lock);
+
+static ssize_t manager_name_show(struct owl_overlay_manager *mgr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", mgr->name);
+}
+
+static ssize_t manager_display_show(struct owl_overlay_manager *mgr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			mgr->device ? mgr->device->name : "<none>");
+}
+
+static ssize_t manager_display_store(struct owl_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	int r = 0;
+	size_t len = size;
+	struct owl_dss_device *dssdev = NULL;
+
+	int match(struct owl_dss_device *dssdev, void *data)
+	{
+		const char *str = data;
+		return sysfs_streq(dssdev->name, str);
+	}
+
+	if (buf[size-1] == '\n')
+		--len;
+
+	if (len > 0)
+		dssdev = owl_dss_find_device((void *)buf, match);
+
+	if (len > 0 && dssdev == NULL)
+		return -EINVAL;
+
+	if (dssdev)
+		DSSDBG("display %s found\n", dssdev->name);
+
+	if (mgr->device) {
+		r = mgr->unset_device(mgr);
+		if (r) {
+			DSSERR("failed to unset display\n");
+			goto put_device;
+		}
+	}
+
+	if (dssdev) {
+		r = mgr->set_device(mgr, dssdev);
+		if (r) {
+			DSSERR("failed to set manager\n");
+			goto put_device;
+		}
+
+		r = mgr->apply(mgr);
+		if (r) {
+			DSSERR("failed to apply dispc config\n");
+			goto put_device;
+		}
+	}
+
+put_device:
+	if (dssdev)
+		owl_dss_put_device(dssdev);
+
+	return r ? r : size;
+}
+
+static ssize_t manager_default_color_show(struct owl_overlay_manager *mgr,
+					  char *buf)
+{
+	struct owl_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.default_color);
+}
+
+static ssize_t manager_default_color_store(struct owl_overlay_manager *mgr,
+					   const char *buf, size_t size)
+{
+	struct owl_overlay_manager_info info;
+	u32 color;
+	int r;
+
+	r = kstrtouint(buf, 0, &color);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.default_color = color;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static const char *trans_key_type_str[] = {
+	"gfx-destination",
+	"video-source",
+};
+
+static ssize_t manager_trans_key_type_show(struct owl_overlay_manager *mgr,
+					   char *buf)
+{
+	enum owl_dss_trans_key_type key_type;
+	struct owl_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	key_type = info.trans_key_type;
+	BUG_ON(key_type >= ARRAY_SIZE(trans_key_type_str));
+
+	return snprintf(buf, PAGE_SIZE, "%s\n", trans_key_type_str[key_type]);
+}
+
+static ssize_t manager_trans_key_type_store(struct owl_overlay_manager *mgr,
+					    const char *buf, size_t size)
+{
+	enum owl_dss_trans_key_type key_type;
+	struct owl_overlay_manager_info info;
+	int r;
+
+	for (key_type = OWL_DSS_COLOR_KEY_GFX_DST;
+			key_type < ARRAY_SIZE(trans_key_type_str); key_type++) {
+		if (sysfs_streq(buf, trans_key_type_str[key_type]))
+			break;
+	}
+
+	if (key_type == ARRAY_SIZE(trans_key_type_str))
+		return -EINVAL;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_key_type = key_type;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_trans_key_value_show(struct owl_overlay_manager *mgr,
+					    char *buf)
+{
+	struct owl_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%#x\n", info.trans_key);
+}
+
+static ssize_t manager_trans_key_value_store(struct owl_overlay_manager *mgr,
+					     const char *buf, size_t size)
+{
+	struct owl_overlay_manager_info info;
+	u32 key_value;
+	int r;
+
+	r = kstrtouint(buf, 0, &key_value);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_key = key_value;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_trans_key_enabled_show(struct owl_overlay_manager *mgr,
+					      char *buf)
+{
+	struct owl_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.trans_enabled);
+}
+
+static ssize_t manager_trans_key_enabled_store(struct owl_overlay_manager *mgr,
+					       const char *buf, size_t size)
+{
+	struct owl_overlay_manager_info info;
+	bool enable;
+	int r;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.trans_enabled = enable;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t manager_alpha_blending_enabled_show(
+		struct owl_overlay_manager *mgr, char *buf)
+{
+	struct owl_overlay_manager_info info;
+
+	mgr->get_manager_info(mgr, &info);
+
+	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+		info.partial_alpha_enabled);
+}
+
+static ssize_t manager_alpha_blending_enabled_store(
+		struct owl_overlay_manager *mgr,
+		const char *buf, size_t size)
+{
+	struct owl_overlay_manager_info info;
+	bool enable;
+	int r;
+
+	WARN_ON(!dss_has_feature(FEAT_ALPHA_FIXED_ZORDER));
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	mgr->get_manager_info(mgr, &info);
+
+	info.partial_alpha_enabled = enable;
+
+	r = mgr->set_manager_info(mgr, &info);
+	if (r)
+		return r;
+
+	r = mgr->apply(mgr);
+	if (r)
+		return r;
+
+	return size;
+}
+
+struct manager_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct owl_overlay_manager *, char *);
+	ssize_t	(*store)(struct owl_overlay_manager *, const char *, size_t);
+};
+
+#define MANAGER_ATTR(_name, _mode, _show, _store) \
+	struct manager_attribute manager_attr_##_name = \
+	__ATTR(_name, _mode, _show, _store)
+
+static MANAGER_ATTR(name, S_IRUGO, manager_name_show, NULL);
+static MANAGER_ATTR(display, S_IRUGO|S_IWUSR,
+		manager_display_show, manager_display_store);
+static MANAGER_ATTR(default_color, S_IRUGO|S_IWUSR,
+		manager_default_color_show, manager_default_color_store);
+static MANAGER_ATTR(trans_key_type, S_IRUGO|S_IWUSR,
+		manager_trans_key_type_show, manager_trans_key_type_store);
+static MANAGER_ATTR(trans_key_value, S_IRUGO|S_IWUSR,
+		manager_trans_key_value_show, manager_trans_key_value_store);
+static MANAGER_ATTR(trans_key_enabled, S_IRUGO|S_IWUSR,
+		manager_trans_key_enabled_show,
+		manager_trans_key_enabled_store);
+static MANAGER_ATTR(alpha_blending_enabled, S_IRUGO|S_IWUSR,
+		manager_alpha_blending_enabled_show,
+		manager_alpha_blending_enabled_store);
+
+
+static struct attribute *manager_sysfs_attrs[] = {
+	&manager_attr_name.attr,
+	&manager_attr_display.attr,
+	&manager_attr_default_color.attr,
+	&manager_attr_trans_key_type.attr,
+	&manager_attr_trans_key_value.attr,
+	&manager_attr_trans_key_enabled.attr,
+	&manager_attr_alpha_blending_enabled.attr,
+	NULL
+};
+
+static ssize_t manager_attr_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct owl_overlay_manager *manager;
+	struct manager_attribute *manager_attr;
+
+	manager = container_of(kobj, struct owl_overlay_manager, kobj);
+	manager_attr = container_of(attr, struct manager_attribute, attr);
+
+	if (!manager_attr->show)
+		return -ENOENT;
+
+	return manager_attr->show(manager, buf);
+}
+
+static ssize_t manager_attr_store(struct kobject *kobj, struct attribute *attr,
+		const char *buf, size_t size)
+{
+	struct owl_overlay_manager *manager;
+	struct manager_attribute *manager_attr;
+
+	manager = container_of(kobj, struct owl_overlay_manager, kobj);
+	manager_attr = container_of(attr, struct manager_attribute, attr);
+
+	if (!manager_attr->store)
+		return -ENOENT;
+
+	return manager_attr->store(manager, buf, size);
+}
+
+static const struct sysfs_ops manager_sysfs_ops = {
+	.show = manager_attr_show,
+	.store = manager_attr_store,
+};
+
+static struct kobj_type manager_ktype = {
+	.sysfs_ops = &manager_sysfs_ops,
+	.default_attrs = manager_sysfs_attrs,
+};
+
+int dss_mgr_wait_for_go(struct owl_overlay_manager *mgr)
+{
+	unsigned long timeout = msecs_to_jiffies(500);
+	struct mgr_priv_data * mp = NULL;
+	enum de_irq_type irq;
+	int rc = 0;
+	
+	if(!mgr){
+		DSSERR("dss_mgr_wait_for_vsync but mgr is null mgr->name = %s\n",mgr->name);
+		return -ENOENT;
+	}	
+	mp = get_mgr_priv(mgr);
+	
+	if(!mp->enabled ||!mgr->device){
+		return 0;
+	}
+	
+	switch(mgr->device->type){
+		case OWL_DISPLAY_TYPE_LCD:
+			irq = DE_IRQ_LCD_PRE;
+			break;
+		case OWL_DISPLAY_TYPE_DSI:
+			irq = DE_IRQ_DSI_PRE;
+			break;
+		case OWL_DISPLAY_TYPE_CVBS:
+			irq = DE_IRQ_CVBS_PRE;
+			break;
+		case OWL_DISPLAY_TYPE_HDMI:
+			irq = DE_IRQ_HDMI_PRE;
+			break;	
+		case OWL_DISPLAY_TYPE_EDP:
+		case OWL_DISPLAY_TYPE_YPBPR:
+		default:
+			DSSERR("display type ( %d )is not support \n",mgr->device->type);
+		    return -ENOENT;						
+	}
+	rc = de_wait_for_irq_interruptible_timeout(irq, mgr->de_path_id,timeout);
+	return rc ;
+}
+
+static int dss_mgr_wait_for_vsync(struct owl_overlay_manager *mgr,long long i64TimeStamp)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	const int wait_timeout = msecs_to_jiffies(500);	/* 16ms, TODO */
+	
+	int rc;
+	
+	if (mp->hw_sync_enable) {
+		atomic_set(&mp->vsync_avail, 0);
+		rc = wait_event_timeout(mp->wait_vsync,
+				atomic_read(&mp->vsync_avail), wait_timeout);
+		if (!rc)
+			DSSDBG("%s timeout\n", __func__);
+	}
+
+	return 0 ;
+}
+
+int dss_mgr_set_device(struct owl_overlay_manager *mgr,
+		struct owl_dss_device *dssdev)
+{
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (dssdev->manager) {
+		DSSERR("display '%s' already has a manager '%s'\n",
+			       dssdev->name, dssdev->manager->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	if ((mgr->supported_displays & dssdev->type) == 0) {
+		DSSERR("display '%s' does not support manager '%s'\n",
+			       dssdev->name, mgr->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	dssdev->manager = mgr;
+	mgr->device = dssdev;
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+int dss_mgr_unset_device(struct owl_overlay_manager *mgr)
+{
+	int r;
+
+	mutex_lock(&apply_lock);
+
+	if (!mgr->device) {
+		DSSERR("failed to unset display, display not set.\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	/*
+	 * Don't allow currently enabled displays to have the overlay manager
+	 * pulled out from underneath them
+	 */
+	if (mgr->device->state != OWL_DSS_DISPLAY_DISABLED) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	mgr->device->manager = NULL;
+	mgr->device = NULL;
+
+	mutex_unlock(&apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(&apply_lock);
+	return r;
+}
+
+int dss_mgr_set_info(struct owl_overlay_manager *mgr,
+		struct owl_overlay_manager_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	int r;
+
+	r = dss_mgr_simple_check(mgr, info);
+	if (r)
+		return r;
+
+	mp->user_info = *info;
+	mp->user_info_dirty = true;
+
+	return 0;
+}
+
+void dss_mgr_get_info(struct owl_overlay_manager *mgr,
+		struct owl_overlay_manager_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	*info = mp->user_info;
+}
+
+int dss_cursor_set_info(struct owl_overlay_manager *mgr, struct owl_cursor_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+
+	mp->user_cursor = *info;
+	mp->user_cursor_dirty = true;
+
+	return 0;
+}
+
+void dss_cursor_get_info(struct owl_overlay_manager *mgr,struct owl_cursor_info *info)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	*info = mp->cursor;	
+}
+
+static void dss_mgr_write_regs(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	struct owl_overlay *ovl;
+	struct owl_dss_device * dssdev = mgr->device;
+	
+	DSSDBG("dss_mgr_write_regs %d mp->enabled %d dssdev->type %d\n",
+		mgr->id, mp->enabled, dssdev->type);
+
+	if (!mp->enabled)
+		return;
+
+	WARN_ON(mp->busy);
+
+	/* Commit overlay settings */
+	DSSDBG("Commit overlay settings \n");
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		ovl->write_hw_regs(ovl);
+	}
+	
+	/* commit cursor info*/
+	if (mp->cursor_dirty) {
+		de_mgr_cursor_setup(mgr->de_path_id, &mp->cursor);
+	}
+	
+	de_mgr_set_path_size(mgr->de_path_id, mp->info.out_width, mp->info.out_height);
+	
+	if (dssdev){
+		de_mgr_set_device_type(mgr->de_path_id,dssdev->type);
+	}	
+	
+	if (mp->info_dirty) {
+		DSSDBG("de_mgr_setup mgr->id %d mp->info %p\n",
+			mgr->id, &mp->info);
+
+		de_mgr_setup(mgr->de_path_id, &mp->info);
+
+		mp->info_dirty = false;
+	}
+	DSSDBG("dss_mgr_write_regs end \n");
+}
+static int dss_check_settings_low(struct owl_overlay_manager *mgr, struct owl_dss_device *dssdev, bool applying)
+{
+	struct owl_overlay_info *oi;
+	struct owl_overlay_manager_info *mi;
+	struct owl_overlay *ovl;
+	struct owl_overlay_info *ois[MAX_DSS_OVERLAYS];
+	struct ovl_priv_data *op;
+	struct mgr_priv_data *mp;
+
+	mp = get_mgr_priv(mgr);
+
+	if (applying && mp->user_info_dirty)
+		mi = &mp->user_info;
+	else
+		mi = &mp->info;
+
+	/* collect the infos to be tested into the array */
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		op = get_ovl_priv(ovl);
+
+		if (!op->enabled && !op->enabling)
+			oi = NULL;
+		else if (applying && op->user_info_dirty)
+			oi = &op->user_info;
+		else
+			oi = &op->info;
+
+		ois[ovl->id] = oi;
+	}
+
+	return dss_mgr_check(mgr, dssdev, mi, ois);
+}
+static void dss_write_regs(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp;
+	int r;		
+	mp = get_mgr_priv(mgr);
+
+	DSSDBG("mp->enabled  %d mp->busy %d mgr->device %p\n",
+		mp->enabled, mp->busy, mgr->device);
+	if (!mp || !mp->enabled || mp->busy)
+		return;
+		
+	DSSDBG("dss_check_settings %d \n", mgr->id);
+	r = dss_check_settings_low(mgr, mgr->device, false);
+	if (r) {
+		DSSERR("cannot write registers for manager %s: "
+				"illegal configuration\n", mgr->name);
+		return;
+	}
+	DSSDBG("dss_mgr_write_regs %d \n", mgr->id);
+	dss_mgr_write_regs(mgr);
+
+	DSSDBG("dss_write_regs ok \n");
+}
+
+static bool is_fb_reserved_memory_freed = false;
+extern void free_fb_reserved_memory(void);
+static int dss_mgr_check_and_enable_mmu(struct owl_overlay_manager *mgr)
+{
+	const int num_ovls = owl_dss_get_num_overlays();
+	int i = 0;
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+    if(!de_is_vb_valid(mgr->id, mgr->device->type))
+    {
+        return 0;
+    }
+	
+    if(!mp->enabled || mp->mmu_state != MMU_STATE_PRE_ENABLE || !mp->shadow_info_dirty)
+    {
+    	return 0;
+    }
+    
+    de_mgr_go(mgr->de_path_id);
+    //if we enable mmu, we set all overlay mmu enable acquiescently!
+	for (i = 0; i < num_ovls; i++) {
+		struct owl_overlay *ovl = owl_dss_get_overlay(i);
+		ovl->enable_overlay_mmu(ovl,true);			
+	}
+	mp->shadow_info_dirty = false;	
+	mp->mmu_state = MMU_STATE_ENABLED;
+	if (unlikely(!is_fb_reserved_memory_freed)) {
+		free_fb_reserved_memory();
+		is_fb_reserved_memory_freed = true;
+		//printk("%s, fb reserved memory is freed.\n", __func__);
+	}
+	return 0;
+}
+
+static void dss_mgr_send_vsync_work(struct work_struct *work)
+{
+	struct mgr_priv_data *mp;
+	struct owl_overlay_manager *mgr;
+    
+	mp = container_of(work, struct mgr_priv_data, vsync_work);
+	mgr= container_of(mp, struct owl_overlay_manager, priv_data);
+	
+    	
+	/* 
+	 * update gamma info if need,
+	 * no need care about synchronization problem,
+	 * every thing will be okay in the next vsync.
+	 *
+	 * NOTE: should check VB status before set gamma table,
+	 * if now is not in VB, skip this setting, or will blur the screen
+	 */
+	
+	if (mgr->gamma_info_dirty && de_is_vb_valid(mgr->id, mgr->device->type)) {
+		if (mgr->gamma_info.enabled) {
+			de_set_gamma_table(mgr->de_path_id, (u32 *)mgr->gamma_info.value);
+		}
+		de_enable_gamma_table(mgr->de_path_id, mgr->gamma_info.enabled);
+		mgr->gamma_info_dirty = false;
+	} else if (mgr->gamma_info_dirty) {
+		//DSSINFO("gamma lost because of VB invalid\n");
+	}
+}
+
+static void dss_mgr_vsync_irq_handler(enum de_irq_type irq, void *data)
+{
+	struct owl_overlay_manager *mgr = (struct owl_overlay_manager *)data;
+	
+	struct mgr_priv_data * mp = get_mgr_priv(mgr);
+	
+	dss_mgr_check_and_enable_mmu(mgr);
+	
+	mp->timestamp = ktime_get();
+
+	atomic_set(&mp->vsync_avail, 1);
+	wake_up(&mp->wait_vsync);
+	
+	trace_vsync_point(0, ktime_to_ns(mp->timestamp));
+	
+	schedule_work(&mp->vsync_work);
+}
+
+
+static void dss_mgr_register_vsync_isr(struct owl_overlay_manager *mgr)
+{
+	enum de_irq_type irq;
+	
+	int r;
+	
+	if(mgr->device){
+		irq = de_mgr_get_vsync_irq(mgr->device->type);
+	}else{
+		DSSERR("dss_mgr_register_vsync_isr  mgr->device  is NULL\n");
+		irq = DE_IRQ_LCD_PRE;
+	}
+	r = owl_de_register_isr(irq, dss_mgr_vsync_irq_handler, mgr);
+	
+	WARN_ON(r);
+}
+
+static void dss_mgr_unregister_vsync_isr(struct owl_overlay_manager *mgr)
+{
+	enum de_irq_type irq;
+	
+	int r;
+
+	if(mgr->device){
+		irq = de_mgr_get_vsync_irq(mgr->device->type); 
+	}else{
+		DSSERR("dss_mgr_unregister_vsync_isr  mgr->device  is NULL\n");
+		irq = DE_IRQ_LCD_PRE;
+	}
+	r = owl_de_unregister_isr(irq, dss_mgr_vsync_irq_handler, mgr);
+	
+	WARN_ON(r);
+}
+
+int dss_mgr_enable_hw_vsync(struct owl_overlay_manager *mgr, bool enable, struct device *dev)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	
+	if (!mp)
+		return -1;
+	
+	if (mp->hw_sync_enable == enable)
+		return 0;
+	
+	mp->dev = dev;
+	
+	if (enable) {
+		dss_mgr_register_vsync_isr(mgr);
+		mp->hw_sync_enable = enable;
+	} else {
+		dss_mgr_unregister_vsync_isr(mgr);
+		mp->hw_sync_enable = enable;
+
+		atomic_set(&mp->vsync_avail, 1);
+		wake_up(&mp->wait_vsync);
+	}
+
+	return 0;
+}
+
+static int dss_mgr_set_mmu_state(struct owl_overlay_manager *mgr, int state)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	
+	if (!mp)
+		return -1;
+	
+	if(mp->mmu_state < state)
+	{
+		mp->mmu_state = state;
+	}
+	
+	return 0;
+}
+
+static void dss_set_go_bits(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp;
+	mp = get_mgr_priv(mgr);
+	DSSDBG("dss_set_go_bits ~~~ %d mp->enabled %d mp->busy %d \n ",
+		mgr->id, mp->enabled, mp->busy);
+	if (!mp->enabled || mp->busy)
+		return;
+
+	mp->busy = true;
+	
+    // if will enable mmu, we need set fcr when mmu enable ,make sure in on vb single.
+    if(mp->mmu_state != MMU_STATE_PRE_ENABLE)
+    {
+        de_mgr_go(mgr->id);
+        mp->shadow_info_dirty = false;
+    }
+    else
+    {
+    	mp->shadow_info_dirty = true;
+    }
+						
+	mp->busy = false;
+
+}
+
+
+static int dss_mgr_apply_mgr_info(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp;
+    
+	mp = get_mgr_priv(mgr);
+	DSSDBG("owl_dss_mgr_apply_mgr(%s),mp->user_info_dirty %d mp->user_cursor_dirty %d\n", mgr->name,mp->user_info_dirty,mp->user_cursor_dirty);
+	
+	if(mp->user_cursor_dirty)
+	{
+		mp->user_cursor_dirty = false;
+		mp->cursor_dirty = true;
+		mp->cursor = mp->user_cursor;
+	}
+	
+	if (!mp->user_info_dirty)
+		return 0;
+
+	mp->user_info_dirty = false;
+	mp->info_dirty = true;
+	mp->info = mp->user_info;
+	
+	
+
+    return 0;
+}
+
+static int owl_dss_mgr_apply(struct owl_overlay_manager *mgr)
+{
+	//unsigned long flags;
+	struct owl_overlay *ovl;
+	struct mgr_priv_data *mp;
+	int r;
+	
+	DSSDBG("owl_dss_mgr_apply(%s)\n", mgr->name);
+	mp = get_mgr_priv(mgr);
+	
+	if(!mp->enabled)
+	{
+		return 0;
+	}
+	mutex_lock(&mgr->apply_lock);
+
+	r = dss_check_settings_low(mgr,  mgr->device, true);
+	
+	if (r) {
+		mutex_unlock(&mgr->apply_lock);
+		DSSDBG("failed to apply settings: illegal configuration.\n");
+		return r;
+	}
+
+	/* Configure overlays */
+	list_for_each_entry(ovl, &mgr->overlays, list)
+		ovl->apply_overlay_info(ovl);
+
+	/* Configure manager */
+	mgr->apply_manager_info(mgr);
+
+	dss_write_regs(mgr);
+	DSSDBG("dss_write_regs ok  \n");
+	dss_set_go_bits(mgr);	
+	DSSDBG("dss_set_go_bits 0k \n");
+	mutex_unlock(&mgr->apply_lock);
+	return 0;
+}
+
+
+int dss_init_overlay_managers(struct platform_device *pdev)
+{
+	int i, r;
+
+	num_managers = dss_feat_get_num_mgrs();
+
+	managers = kzalloc(sizeof(struct owl_overlay_manager) * num_managers,
+			GFP_KERNEL);
+
+	BUG_ON(managers == NULL);
+
+	for (i = 0; i < num_managers; ++i) {
+		struct owl_overlay_manager *mgr = &managers[i];
+		struct mgr_priv_data *mp = get_mgr_priv(mgr);
+		switch (i) {
+		case 0:
+			mgr->name = "primary";
+			mgr->id = OWL_DSS_OVL_MGR_PRIMARY;
+			mgr->de_path_id = OWL_DSS_PATH1_ID;
+			break;
+		case 1:
+			mgr->name = "external";
+			mgr->id = OWL_DSS_OVL_MGR_EXTERNAL;
+			mgr->de_path_id = OWL_DSS_PATH2_ID;
+			break;
+		}		
+		mgr->set_device = &dss_mgr_set_device;
+		mgr->unset_device = &dss_mgr_unset_device;
+		mgr->apply = &owl_dss_mgr_apply;
+		mgr->set_manager_info = &dss_mgr_set_info;
+		mgr->get_manager_info = &dss_mgr_get_info;
+		mgr->apply_manager_info = &dss_mgr_apply_mgr_info;
+		
+		mgr->set_cursor_info = &dss_cursor_set_info;
+		mgr->get_cursor_info = &dss_cursor_get_info;
+		
+		mgr->enable_hw_vsync = &dss_mgr_enable_hw_vsync;
+		mgr->set_mmu_state = &dss_mgr_set_mmu_state;
+
+		mgr->wait_for_go = &dss_mgr_wait_for_go;
+		mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
+
+		mgr->caps = 0;
+		mgr->supported_displays =
+			dss_feat_get_supported_displays(mgr->id);
+			
+		mutex_init(&mgr->apply_lock);
+		
+		mp->hw_sync_enable =false;
+		
+		mp->mmu_state = MMU_STATE_NO_ENABLE;
+		
+		mp->shadow_info_dirty = false;
+		
+		atomic_set(&mp->vsync_avail, 0);
+		init_waitqueue_head(&mp->wait_vsync);
+		
+		INIT_WORK(&mp->vsync_work,dss_mgr_send_vsync_work);
+		
+		INIT_LIST_HEAD(&mgr->overlays);
+
+		r = kobject_init_and_add(&mgr->kobj, &manager_ktype,
+				&pdev->dev.kobj, "manager%d", i);
+
+		if (r)
+			DSSERR("failed to create sysfs file\n");
+	}
+
+	return 0;
+}
+
+void dss_uninit_overlay_managers(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < num_managers; ++i) {
+		struct owl_overlay_manager *mgr = &managers[i];
+
+		kobject_del(&mgr->kobj);
+		kobject_put(&mgr->kobj);
+	}
+
+	kfree(managers);
+	managers = NULL;
+	num_managers = 0;
+}
+
+int owl_dss_get_num_overlay_managers(void)
+{
+	return num_managers;
+}
+EXPORT_SYMBOL(owl_dss_get_num_overlay_managers);
+
+struct owl_overlay_manager *owl_dss_get_overlay_manager(int num)
+{
+	if (num >= num_managers)
+		return NULL;
+
+	return &managers[num];
+}
+EXPORT_SYMBOL(owl_dss_get_overlay_manager);
+
+int dss_mgr_simple_check(struct owl_overlay_manager *mgr,
+		const struct owl_overlay_manager_info *info)
+{
+	if (dss_has_feature(FEAT_ALPHA_FIXED_ZORDER)) {
+		/*
+		 * OWL3 supports only graphics source transparency color key
+		 * and alpha blending simultaneously. See TRM 15.4.2.4.2.2
+		 * Alpha Mode.
+		 */
+		if (info->partial_alpha_enabled && info->trans_enabled
+			&& info->trans_key_type != OWL_DSS_COLOR_KEY_GFX_DST) {
+			DSSERR("check_manager: illegal transparency key\n");
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int dss_mgr_check_zorder(struct owl_overlay_manager *mgr,
+		struct owl_overlay_info **overlay_infos)
+{
+	struct owl_overlay *ovl1, *ovl2;
+	struct owl_overlay_info *info1, *info2;
+
+	list_for_each_entry(ovl1, &mgr->overlays, list) {
+		info1 = overlay_infos[ovl1->id];
+
+		if (info1 == NULL)
+			continue;
+
+		list_for_each_entry(ovl2, &mgr->overlays, list) {
+			if (ovl1 == ovl2)
+				continue;
+
+			info2 = overlay_infos[ovl2->id];
+
+			if (info2 == NULL)
+				continue;
+
+			if (info1->zorder == info2->zorder) {
+				DSSERR("overlays %d and %d have the same "
+						"zorder %d\n",
+					ovl1->id, ovl2->id, info1->zorder);
+				return -EINVAL;
+			}
+		}
+	}
+
+	return 0;
+}
+static int dss_mgr_check_display_size(struct owl_overlay_manager_info *info ,struct owl_dss_device *dssdev)
+{
+	u16 dw, dh;
+	
+	if(dssdev == NULL)
+		return  0;
+		
+	dssdev->driver->get_resolution(dssdev, &dw, &dh);
+	
+	//there need check the dw and dh 
+	info->out_width = dw;
+	info->out_height = dh;
+	return 0;
+}
+
+int dss_mgr_check(struct owl_overlay_manager *mgr,
+		struct owl_dss_device *dssdev,
+		struct owl_overlay_manager_info *info,
+		struct owl_overlay_info **overlay_infos)
+{
+	struct owl_overlay *ovl;
+	int r;
+
+	if (dss_has_feature(FEAT_ALPHA_FREE_ZORDER)) {
+		r = dss_mgr_check_zorder(mgr, overlay_infos);
+		if (r)
+			return r;
+	}
+
+	list_for_each_entry(ovl, &mgr->overlays, list) {
+		struct owl_overlay_info *oi;
+		int r;
+
+		oi = overlay_infos[ovl->id];
+
+		if (oi == NULL)
+			continue;
+
+		r = dss_ovl_check(ovl, oi, dssdev);
+		if (r)
+			return r;
+	}
+	
+	r = dss_mgr_check_display_size(info,dssdev);
+	
+	if (r)
+		return r;
+
+	return 0;
+}
+
+int dss_mgr_enable(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	//unsigned long flags;
+	u16 dw = 0 ;
+	u16 dh = 0 ;
+
+	mutex_lock(&apply_lock);
+
+	if (mp->enabled)
+		goto out;
+	
+	//spin_lock_irqsave(&data_lock, flags);
+
+	mp->enabled = true;
+	
+	if(dss_check_channel_boot_inited(mgr->de_path_id))
+	{
+		goto out;
+	}
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+	if(mgr->device != NULL && mgr->device->driver != NULL){
+		mgr->device->driver->get_resolution(mgr->device, &dw, &dh);
+	}
+	de_mgr_set_path_size(mgr->de_path_id,dw,dh);		
+	de_mgr_enable(mgr->de_path_id, true);
+	dss_set_go_bits(mgr);
+out:
+	mutex_unlock(&apply_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(dss_mgr_enable);
+void dss_mgr_disable(struct owl_overlay_manager *mgr)
+{
+	struct mgr_priv_data *mp = get_mgr_priv(mgr);
+	//unsigned long flags;
+	mutex_lock(&apply_lock);
+
+	if (!mp->enabled)
+		goto out;
+
+	de_mgr_enable(mgr->de_path_id, false);
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	mp->enabled = false;
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+
+out:
+	mutex_unlock(&apply_lock);
+}
+EXPORT_SYMBOL(dss_mgr_disable);
+
+
+void dss_mgr_set_gamma_table(enum owl_de_path_id channel,
+				struct owl_gamma_info *gamma_info)
+{
+	struct owl_overlay_manager *mgr = owl_dss_get_overlay_manager(channel);		
+
+	mgr->gamma_info = *gamma_info;
+	mgr->gamma_info_dirty = true;
+}
+EXPORT_SYMBOL(dss_mgr_set_gamma_table);
+
+/* just return the backup, do not read from register */
+void dss_mgr_get_gamma_table(enum owl_de_path_id channel,
+				struct owl_gamma_info *gamma_info)
+{
+	struct owl_overlay_manager *mgr = owl_dss_get_overlay_manager(channel);		
+
+	*gamma_info = mgr->gamma_info;
+}
+EXPORT_SYMBOL(dss_mgr_get_gamma_table);
+
+
+bool dss_check_channel_boot_inited(enum owl_de_path_id channel)
+{
+	return de_channel_check_boot_inited(channel);
+}
+EXPORT_SYMBOL(dss_check_channel_boot_inited);
diff --git a/drivers/video/fbdev/owl/dss/mmu.c b/drivers/video/fbdev/owl/dss/mmu.c
new file mode 100755
index 0000000..49c352c
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/mmu.c
@@ -0,0 +1,675 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/de_atm7059.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: lipeng<lipeng at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "MMU"
+
+#include <linux/types.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/hugetlb.h> 
+#include <linux/vmalloc.h>
+
+#include <asm/page.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "de.h"
+static DEFINE_MUTEX(MMU_lock);
+#define MMU_TABLE_SIZE		(4 * 1024 * 1024)
+
+/*
+ * MMU entry used to convert virtaul address or ION fd
+ * to DE device address.
+ * 
+ * --va, virtual address
+ * --vsize, virtual address size
+ * --num_pages_mapped, the number of mapped pages,
+ *	which have valid physical memory
+ * --page_offset, the offset in page
+ *
+ * --buffer_id, ion_handle ID
+ *
+ * --da, device address used by DE MMU
+ * --dsize, device memory size
+ * --num_pages, the number of pages coverted by this MMU entry
+ *
+ * --pages, a page array used to get physcal memory address
+ *
+ * --addr, virtual address in MMU table, which stores physical
+ *	address used by DE(DA-->PA)
+ *
+ * --time_stamp, a time stamp to record MMU operate counters
+ */
+/* system physical address */
+#define OWL_ADDRSPACE_PHYSADDR_BITS 32
+
+typedef struct _OWL_SYS_PHYADDR
+{
+	/* variable sized type (32,64) */
+#if OWL_ADDRSPACE_PHYSADDR_BITS == 32
+	/* variable sized type (32,64) */
+	u32 uiAddr;
+#else
+	u64 uiAddr;
+#endif
+} OWL_SYS_PHYADDR;
+
+typedef struct _mmu_entry_ {
+	/* only used by VA-->DA mapping */
+	u64			va;
+	u64			vsize;
+	u32			num_pages_mapped;
+	u32			page_offset;
+
+#ifdef CONFIG_VIDEO_OWL_MMU_ION_SUPPORT
+	/* only used by ION-->DA mapping */
+	u64         buffer_id;
+#endif
+	
+	u32			da;
+	u32			dsize;	
+	
+	u32			num_pages;
+	
+	/* only used by VA-->DA mapping */
+	struct page		**pages;
+
+	u32			*addr;
+	
+	u64			time_stamp;
+	
+	struct _mmu_entry_	*next;	
+	
+} mmu_entry_t;
+
+
+/* 
+ * free space in MMU table, which maybe discontinuous.
+ * --addr, virtual address of this free space
+ * --size, free space's size
+ */
+typedef struct _mmu_free_info_ {
+	void __iomem		*addr;
+	u32			size;
+	struct _mmu_free_info_	*next;		
+} mmu_free_info_t;
+
+
+/* 
+ * DE MMU table.
+ * --base, base virtual address
+ * --base_phys, base physical address
+ * --remain_size, remain size in byte
+ * --free_list, free memory list in table
+ * --entry_list, a list to hold all allocated MMU entried
+ * --time_stamp, a time stamp to record MMU operate counters
+ */
+struct mmu_table {
+	void __iomem		*base;
+	u64			base_phys;
+	u32			remain_size;
+	
+	mmu_free_info_t		*free_list;	
+	mmu_entry_t		*entry_list;
+
+	u64			time_stamp;
+};
+
+static struct mmu_table 	mmu;
+
+
+/* allocate memory from MMU's free list */
+static int mmu_alloc_memory(int size, u64 **addr){
+	void __iomem *addr_tmp = NULL;
+	mmu_free_info_t *free_info = mmu.free_list;
+
+	DSSDBG("%s, size = %d\n", __func__, size);
+
+	do {
+		if (free_info == NULL || mmu.remain_size < size)
+			break;
+
+		if (free_info->size >= size) {
+			addr_tmp = free_info->addr;
+			free_info->addr += size;
+			free_info->size -= size;
+			mmu.remain_size -= size;
+			DSSDBG("MMU Alloc: ADDR 0x%p size 0x%x HeapFree 0x%x \n",addr_tmp, size,mmu.remain_size);
+			break;			
+		}
+								
+		free_info = free_info->next;
+			
+	} while (free_info != NULL);
+	
+	if (addr_tmp == NULL) {
+		DSSERR("fail to allocate de memory \n");
+		return -1;
+	}
+
+
+	*addr = addr_tmp;
+	return 0;
+}
+
+static int mmu_free_memroy(void __iomem *addr, int size)
+{
+	bool is_combination = false;
+	
+	mmu_free_info_t *free_info = mmu.free_list;
+	mmu_free_info_t *last_free_info  = NULL;
+
+	do {
+		if (free_info == NULL)
+			break;
+
+		last_free_info = free_info;
+		if (free_info->addr + free_info->size == addr) {
+			free_info->size += size;
+			is_combination = true;
+			break;			
+		}
+		
+		if(addr + size == free_info->addr) {
+			free_info->addr = addr;
+			free_info->size += size;
+			is_combination = true;
+			break;	
+		}		
+		free_info = free_info->next;	
+	} while(free_info != NULL);
+	
+	/* insert new entry for free mem Info */
+	if (!is_combination) {
+		free_info = kmalloc(sizeof(mmu_free_info_t), GFP_KERNEL);
+		free_info->addr = addr;
+		free_info->size = size;
+		free_info->next = NULL;
+		last_free_info->next = free_info;		
+	}
+	mmu.remain_size += size;
+		
+	if (addr == 0) {
+		DSSERR("fail to allocate de memory \n");
+	}
+	DSSDBG("MMU Free: 0x%p size 0x%x HeapFree 0x%x \n",addr, size,mmu.remain_size);
+	return 0;
+}
+/* find MMU entry in device memory using vitrual address and its size */
+static bool mmu_find_entry_by_vaddr(mmu_entry_t **found, u64 va, u32 length)
+{
+	bool is_found = false;
+	mmu_entry_t *entry = mmu.entry_list;
+
+	do {
+		if (entry == NULL)
+			break;
+
+		if (entry->va == va && entry->vsize == length) {
+			*found = entry;
+			is_found = true;
+			break;
+		}	
+		entry = entry->next;
+	} while (entry != NULL);
+	
+	return is_found;
+}
+
+#ifdef CONFIG_VIDEO_OWL_MMU_ION_SUPPORT
+/* find MMU entry in device memory using ion handle id */
+static bool mmu_find_entry_by_id_firstone(mmu_entry_t **found, u64 id)
+{
+	bool is_found = false;
+	mmu_entry_t *entry = mmu.entry_list;
+
+	do {
+		if (entry == NULL)
+			break;
+
+		if (entry->buffer_id == id) {
+			if(*found != NULL){
+				if((*found)->time_stamp > entry->time_stamp){
+					*found = entry;
+				}
+			}else{
+				*found = entry;
+			}
+			is_found = true;
+			//break;
+		}
+		entry = entry->next;
+	} while (entry != NULL);
+	
+	return is_found;
+}
+/* find MMU entry in device memory using ion handle id */
+static bool mmu_find_entry_by_fd_lastone(mmu_entry_t **found, u64 fd)
+{
+	bool is_found = false;
+	mmu_entry_t *entry = mmu.entry_list;
+
+	do {
+		if (entry == NULL)
+			break;
+
+		if (entry->buffer_id == fd) {
+			if(*found != NULL){
+				if((*found)->time_stamp < entry->time_stamp){
+					*found = entry;
+				}
+			}else{
+				*found = entry;
+			}
+			is_found = true;
+			//break;
+		}
+		entry = entry->next;
+	} while (entry != NULL);
+	
+	return is_found;
+}
+#endif
+
+static int mmu_add_entry(mmu_entry_t *new_entry)
+{
+	int ret = 0;
+	mmu_entry_t *entry = mmu.entry_list;
+	mmu_entry_t *last_entry = NULL;
+	
+	do {
+		if (entry == NULL)
+			break;
+
+		last_entry = entry;		
+		entry = entry->next;			
+	} while(entry != NULL);
+	
+	if (last_entry == NULL) {
+		mmu.entry_list = new_entry;
+		new_entry->next = NULL;
+	} else {
+		last_entry->next = new_entry;
+		new_entry->next = NULL;
+	}
+
+	return ret;
+}
+
+static int mmu_delete_entry(mmu_entry_t * target_entry)
+{
+	int ret = 0;
+	bool found = false;
+	mmu_entry_t *entry = mmu.entry_list;
+	mmu_entry_t *pre_entry =  mmu.entry_list;	
+	do {
+		if (entry == NULL)
+			break;
+		if(target_entry->buffer_id == entry->buffer_id){
+			if (pre_entry->buffer_id == target_entry->buffer_id) {
+				mmu.entry_list = pre_entry->next;
+			} else {
+				pre_entry->next =  target_entry->next;				
+			}
+			kfree(target_entry);
+			found = true;
+			break;
+		}
+		pre_entry = entry;
+		entry = entry->next;			
+	} while(entry != NULL);
+	
+	if(!found){
+		DSSERR("fail to delete entry id is %llu )\n",target_entry->buffer_id);
+		return -ENOMEM;
+	}
+	return ret;
+}
+
+/*=======================================================================
+ *			APIs to others
+ *=====================================================================*/
+int mmu_init(void)
+{
+	void __iomem *vaddr;
+	u64 paddr;
+	mmu_free_info_t *free_info;
+	
+	vaddr = dma_alloc_coherent(NULL, MMU_TABLE_SIZE,
+					(dma_addr_t *)&paddr, GFP_KERNEL);
+	
+	if (!vaddr) {
+		DSSERR("fail to allocate mmu table mem (size: %dK))\n",
+			MMU_TABLE_SIZE / 1024);
+		return -ENOMEM;
+	}
+
+	//SetPageReserved(pfn_to_page((paddr) >> PAGE_SHIFT));
+	
+	mmu.base = vaddr;
+	mmu.base_phys = paddr;
+	mmu.remain_size = MMU_TABLE_SIZE;
+	memset(vaddr,0,MMU_TABLE_SIZE);
+
+	free_info = kmalloc(sizeof(mmu_free_info_t), GFP_KERNEL);
+	free_info->addr = mmu.base ;
+	free_info->size = MMU_TABLE_SIZE ;
+	free_info->next = NULL;
+		
+	mmu.free_list = free_info;
+	mmu.entry_list = NULL;
+	
+	DSSINFO("%s: base 0x%p base_phys 0x%llx free_info->addr 0x%p\n",
+		__func__, mmu.base, mmu.base_phys, free_info->addr);
+
+	owl_de_mmu_config(mmu.base_phys);
+
+	return 0;
+}
+int mmu_va_to_da(u64 va, u32 length, u32 *da)
+{
+	u64 start_addr_orig = va;
+	u32 addr_range_orig = length;
+
+	u64 beyond_end_addr_orig = start_addr_orig + addr_range_orig;
+	
+	u64 start_addr = start_addr_orig & PAGE_MASK;
+	u64 beyond_end_addr = PAGE_ALIGN(beyond_end_addr_orig);
+	u32 addr_range = beyond_end_addr - start_addr;
+
+	mmu_entry_t *entry = NULL;
+
+	u64 *device_addr;
+	int i = 0;
+	int ret = 0;
+	
+	DSSDBG("mmu_va_to_da: va 0x%llx length 0x%x\n", va, length);
+	
+	if (va == 0)
+		goto error_exit1;
+	
+	if (beyond_end_addr <= start_addr)
+		goto error_exit1;
+	
+	DSSDBG("%s: va 0x%llx length 0x%x\n", __func__, va, length);
+	if (mmu_find_entry_by_vaddr(&entry, va, length))
+		goto ok_exit; 
+	else
+		entry = NULL;
+	
+	mmu.time_stamp++;
+	
+	DSSDBG("alloc MMU entry for mem record\n");
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (entry == NULL) {
+		DSSERR("Failed to alloc memory for MMU entry\n");
+		goto error_exit1;
+	}
+	memset(entry, 0, sizeof(*entry));
+	
+	entry->num_pages = (u32)(addr_range >> PAGE_SHIFT);
+	entry->page_offset = (u32)(start_addr_orig & ~PAGE_MASK);
+	
+	DSSDBG("alloc device addr from de mmu heap entry->num_pages 0x%x,\
+		entry->page_offset 0x%x\n",
+		entry->num_pages, entry->page_offset);
+	ret = mmu_alloc_memory(entry->num_pages * sizeof(u32), &device_addr);
+	
+	if (ret) {
+		DSSERR("Failed to alloc memory for devices\n");
+		ret = -2;	
+		goto error_exit2;
+	}
+	entry->da = (u32)(device_addr - (u64 *)mmu.base);
+	entry->dsize = entry->num_pages * sizeof(u32);
+	entry->addr = (u32 *)device_addr;
+	DSSDBG(" entry->da 0x%x, entry->dsize 0x%x,\
+		entry->addr 0x%p\n", entry->da,
+		entry->dsize, entry->addr);
+	memset(entry->addr, 0, entry->dsize);
+	
+	DSSDBG("Allocate page array \n");
+	entry->pages = kmalloc((size_t)entry->num_pages
+					* sizeof(*entry->pages), GFP_KERNEL);
+	if (entry->pages == NULL) {
+		DSSERR("mmu_va_to_da: Couldn't allocate page array");		
+		ret = -3;	
+		goto error_exit3;
+	}
+	memset(entry->pages, 0, (size_t)entry->num_pages
+					* sizeof(*entry->pages));
+	
+	/* Lock down user memory */
+	DSSDBG("Lock down user memory \n");
+	down_read(&current->mm->mmap_sem);
+	
+	DSSDBG("start_addr 0x%llx, entry->pages 0x%p \n",
+		start_addr, entry->pages);
+	entry->num_pages_mapped = get_user_pages(current, current->mm, start_addr,
+				entry->num_pages, 1, 0, entry->pages, NULL);
+	DSSDBG("mmu_va_to_da: map all the pages needed\
+		(wanted: %d, got %d) entry->addr %p \n",
+		entry->num_pages, entry->num_pages_mapped,entry->addr);
+	if (entry->num_pages_mapped >= 0) {
+		/* See if we got all the pages we wanted */
+		if (entry->num_pages_mapped != entry->num_pages) {
+			printk("mmu_va_to_da: Couldn't map all\
+				the pages needed (wanted: %d, got %d) \n",
+				entry->num_pages, entry->num_pages_mapped);
+				ret = -4;	
+			goto error_exit4;
+		}
+		
+		/* Build list of physical page addresses */
+		for (i = 0; i < entry->num_pages; i++) {
+			u32 ui32PFN = page_to_pfn(entry->pages[i]);
+			
+			entry->addr[i] = ui32PFN << PAGE_SHIFT;
+			
+			if ((entry->addr[i] >> PAGE_SHIFT) != ui32PFN) {
+				DSSERR( "mmu_va_to_da: PFN out of range(%x)\n",
+					ui32PFN);
+				ret = -4;	
+				goto error_exit4;
+			}
+			DSSDBG("entry->addr[%d] 0x%x \n",
+				i, entry->addr[i]);
+		}
+
+	}
+
+	entry->va = va;
+	entry->vsize = length;
+	
+	DSSDBG("mmu_add_entry \n");
+	ret = mmu_add_entry(entry);
+	if (ret) {
+		DSSERR( "mmu_add_entry failed \n");
+		ret = -4;	
+		goto error_exit4;
+	}
+	
+	/* Lock up user memory */
+	DSSDBG("Lock up user memory \n");
+	up_read(&current->mm->mmap_sem);
+	
+	goto ok_exit;
+		
+error_exit4:
+	kfree(entry->pages);	
+	up_read(&current->mm->mmap_sem);
+error_exit3:
+	mmu_free_memroy(entry->addr, entry->num_pages * sizeof(u32));
+error_exit2:
+	kfree(entry);	
+error_exit1:
+ok_exit:
+	if(entry != NULL) {
+		int i = 0;
+		u32 *mmu_table = (u32 *)mmu.base;
+		*da = ((entry->da / 4) << PAGE_SHIFT)
+				| entry->page_offset;
+		DSSDBG("mmu_va_to_da va 0x%llx length 0x%x \
+			da 0x%x  entry->da 0x%x \
+			entry->page_offset 0x%x \n",
+			va, length, *da,
+			entry->da, entry->page_offset);
+		entry->time_stamp = mmu.time_stamp;
+		DSSDBG("mmu 0x%p \n", entry->addr);
+		
+		for (i = 0; i < (MMU_TABLE_SIZE - mmu.remain_size) / 4 + 5;
+			i++) {
+			DSSDBG("0x%x  ", *(mmu_table + i));
+		}
+		DSSDBG(" \n");
+		DSSDBG("mmu_va_to_da va 0x%llx length 0x%x \
+			da 0x%x  entry->da 0x%x  \
+			entry->page_offset 0x%x \n",
+			va, length, *da,
+			entry->da, entry->page_offset);
+	}
+
+	return ret;
+}
+
+#ifdef CONFIG_VIDEO_OWL_MMU_ION_SUPPORT
+int mmu_fd_to_da(u64 buffer_id, u32 *da)
+{
+	int ret = 0;
+    mmu_entry_t *entry;
+    
+	mutex_lock(&MMU_lock);
+	entry = NULL;
+
+	if (!mmu_find_entry_by_fd_lastone(&entry, buffer_id)) {		
+		entry = NULL;
+	} 
+		
+	if(entry != NULL){
+		*da = ((entry->da / 4) << PAGE_SHIFT);
+	}else{
+		*da = 0;
+		ret = -1;
+	}
+	mutex_unlock(&MMU_lock);
+	if(ret != 0)
+		printk("mmu_fd_to_da (buffer_id %llu  da 0x%x) ret %d \n",buffer_id,*da,ret);
+		
+	return ret;
+}
+int owl_mmu_import_buffer_on_dc(u64 buffer_id , OWL_SYS_PHYADDR * psSysPhysAddr, u32 page_count,u32 page_offset)
+{
+	int i = 0;
+	int ret = 0;
+	u64 * device_addr;
+	mmu_entry_t *entry;
+	
+	mutex_lock(&MMU_lock);
+	entry = NULL;
+	
+	if (mmu_find_entry_by_id_firstone(&entry, buffer_id)) {
+		DSSDBG("entry is already here  %lld \n", buffer_id);
+		entry = NULL;
+		//goto  error_exit1;
+	} else {
+		entry = NULL;
+	}
+	
+	mmu.time_stamp++;
+
+	entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+	if (entry == NULL) {
+		DSSERR("Failed to alloc MMU entry\n");
+		goto error_exit1;
+	}
+	memset(entry, 0, sizeof(*entry));
+	
+	entry->num_pages = page_count;
+
+	ret = mmu_alloc_memory(entry->num_pages * sizeof(u32), &device_addr);
+	
+	if (ret) {
+		DSSERR("Failed to alloc memory for devices \n");
+		ret = -2;	
+		goto error_exit2;
+	}
+	entry->da = (u32)((void *)device_addr - (void *)mmu.base);
+	entry->dsize = entry->num_pages * sizeof(u32);
+
+	entry->addr = (u32*)device_addr;
+	memset(entry->addr, 0, entry->dsize);
+
+	/* Build list of physical page addresses */
+	for(i = 0 ; i < page_count; i++) {
+		entry->addr[i] = psSysPhysAddr[i].uiAddr;
+	}	
+	
+	entry->buffer_id = buffer_id;
+
+	ret = mmu_add_entry(entry);
+	
+	if (ret) {
+		DSSERR( "mmu_add_entry failed \n");
+		ret = -4;	
+		goto error_exit3;
+	}
+	DSSDBG("MMU Import: %lld  page_count %d entry->da 0x%x \n",buffer_id,page_count,entry->da);	
+	goto ok_exit;
+		
+error_exit3:
+	mmu_free_memroy(entry->addr, entry->num_pages * sizeof(u32));
+error_exit2:
+	kfree(entry);	
+error_exit1:
+ok_exit:
+	if (entry != NULL) {
+		entry->time_stamp = mmu.time_stamp;
+		DSSDBG("mmu 0x%p \n", entry->addr);
+	}
+	mutex_unlock(&MMU_lock);
+	return ret;
+}
+EXPORT_SYMBOL(owl_mmu_import_buffer_on_dc);
+int owl_mmu_unimport_buffer_on_dc(u64 buffer_id)
+{
+	int ret = 0;
+	mmu_entry_t *entry;
+	
+	mutex_lock(&MMU_lock);
+	entry = NULL;
+	DSSDBG("MMU UnImport: buffer_id %lld \n",buffer_id);		
+	if (mmu_find_entry_by_id_firstone(&entry, buffer_id)) {
+		mmu_free_memroy(entry->addr,entry->num_pages * sizeof(u32));
+		
+		ret = mmu_delete_entry(entry);
+	} 
+	mutex_unlock(&MMU_lock);
+	return ret;
+}
+EXPORT_SYMBOL(owl_mmu_unimport_buffer_on_dc);
+#else
+int mmu_fd_to_da(u64 buffer_id, u32 *da)
+{
+	return -1;
+}
+#endif
+
diff --git a/drivers/video/fbdev/owl/dss/overlay.c b/drivers/video/fbdev/owl/dss/overlay.c
new file mode 100755
index 0000000..338c97b
--- /dev/null
+++ b/drivers/video/fbdev/owl/dss/overlay.c
@@ -0,0 +1,935 @@
+/*
+ * linux/drivers/video/fbdev/owl/dss/overlay.c
+ *
+ * Copyright (C) 2009 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#define DSS_SUBSYS_NAME "OVERLAY"
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/sysfs.h>
+#include <linux/kobject.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+
+#include <video/owldss.h>
+
+#include "dss.h"
+#include "dss_features.h"
+#include "de.h"
+
+static int num_overlays;
+static struct owl_overlay *overlays;
+
+static ssize_t overlay_name_show(struct owl_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", ovl->name);
+}
+
+static ssize_t overlay_manager_show(struct owl_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			ovl->manager ? ovl->manager->name : "<none>");
+}
+
+static ssize_t overlay_manager_store(struct owl_overlay *ovl, const char *buf,
+		size_t size)
+{
+	int i, r;
+	struct owl_overlay_manager *mgr = NULL;
+	struct owl_overlay_manager *old_mgr;
+	int len = size;
+
+	if (buf[size-1] == '\n')
+		--len;
+
+	if (len > 0) {
+		for (i = 0; i < owl_dss_get_num_overlay_managers(); ++i) {
+			mgr = owl_dss_get_overlay_manager(i);
+
+			if (sysfs_streq(buf, mgr->name))
+				break;
+
+			mgr = NULL;
+		}
+	}
+
+	if (len > 0 && mgr == NULL)
+		return -EINVAL;
+
+	if (mgr)
+		DSSDBG("manager %s found\n", mgr->name);
+
+	if (mgr == ovl->manager)
+		return size;
+
+	old_mgr = ovl->manager;
+
+	/* detach old manager */
+	if (old_mgr) {
+		r = ovl->unset_manager(ovl);
+		if (r) {
+			DSSERR("detach failed\n");
+			goto err;
+		}
+
+		r = old_mgr->apply(old_mgr);
+		if (r)
+			goto err;
+	}
+
+	if (mgr) {
+		r = ovl->set_manager(ovl, mgr);
+		if (r) {
+			DSSERR("Failed to attach overlay\n");
+			goto err;
+		}
+
+		r = mgr->apply(mgr);
+		if (r)
+			goto err;
+	}
+
+	return size;
+
+err:
+	return r;
+}
+
+static ssize_t overlay_input_size_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.width, info.height);
+}
+
+static ssize_t overlay_screen_width_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.screen_width);
+}
+
+static ssize_t overlay_position_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.pos_x, info.pos_y);
+}
+
+static ssize_t overlay_position_store(struct owl_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	char *last;
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.pos_x = simple_strtoul(buf, &last, 10);
+	++last;
+	if (last - buf >= size)
+		return -EINVAL;
+
+	info.pos_y = simple_strtoul(last, &last, 10);
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_output_size_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d,%d\n",
+			info.out_width, info.out_height);
+}
+
+static ssize_t overlay_output_size_store(struct owl_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	char *last;
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.out_width = simple_strtoul(buf, &last, 10);
+	++last;
+	if (last - buf >= size)
+		return -EINVAL;
+
+	info.out_height = simple_strtoul(last, &last, 10);
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_enabled_show(struct owl_overlay *ovl, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", ovl->is_enabled(ovl));
+}
+
+static ssize_t overlay_enabled_store(struct owl_overlay *ovl, const char *buf,
+		size_t size)
+{
+	int r;
+	bool enable;
+
+	r = strtobool(buf, &enable);
+	if (r)
+		return r;
+
+	if (enable)
+		r = ovl->enable(ovl);
+	else
+		r = ovl->disable(ovl);
+
+	if (r)
+		return r;
+
+	return size;
+}
+
+static ssize_t overlay_global_alpha_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			info.global_alpha);
+}
+
+static ssize_t overlay_global_alpha_store(struct owl_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 alpha;
+	struct owl_overlay_info info;
+
+	if ((ovl->caps & OWL_DSS_OVL_CAP_GLOBAL_ALPHA) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &alpha);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.global_alpha = alpha;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_pre_mult_alpha_en_show(struct owl_overlay *ovl,
+		char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			info.pre_mult_alpha_en);
+}
+
+static ssize_t overlay_pre_mult_alpha_en_store(struct owl_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 alpha;
+	struct owl_overlay_info info;
+
+	if ((ovl->caps & OWL_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &alpha);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.pre_mult_alpha_en = alpha;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+static ssize_t overlay_zorder_show(struct owl_overlay *ovl, char *buf)
+{
+	struct owl_overlay_info info;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", info.zorder);
+}
+
+static ssize_t overlay_zorder_store(struct owl_overlay *ovl,
+		const char *buf, size_t size)
+{
+	int r;
+	u8 zorder;
+	struct owl_overlay_info info;
+
+	if ((ovl->caps & OWL_DSS_OVL_CAP_ZORDER) == 0)
+		return -ENODEV;
+
+	r = kstrtou8(buf, 0, &zorder);
+	if (r)
+		return r;
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.zorder = zorder;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r)
+		return r;
+
+	if (ovl->manager) {
+		r = ovl->manager->apply(ovl->manager);
+		if (r)
+			return r;
+	}
+
+	return size;
+}
+
+struct overlay_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct owl_overlay *, char *);
+	ssize_t	(*store)(struct owl_overlay *, const char *, size_t);
+};
+
+#define OVERLAY_ATTR(_name, _mode, _show, _store) \
+	struct overlay_attribute overlay_attr_##_name = \
+	__ATTR(_name, _mode, _show, _store)
+
+static OVERLAY_ATTR(name, S_IRUGO, overlay_name_show, NULL);
+static OVERLAY_ATTR(manager, S_IRUGO|S_IWUSR,
+		overlay_manager_show, overlay_manager_store);
+static OVERLAY_ATTR(input_size, S_IRUGO, overlay_input_size_show, NULL);
+static OVERLAY_ATTR(screen_width, S_IRUGO, overlay_screen_width_show, NULL);
+static OVERLAY_ATTR(position, S_IRUGO|S_IWUSR,
+		overlay_position_show, overlay_position_store);
+static OVERLAY_ATTR(output_size, S_IRUGO|S_IWUSR,
+		overlay_output_size_show, overlay_output_size_store);
+static OVERLAY_ATTR(enabled, S_IRUGO|S_IWUSR,
+		overlay_enabled_show, overlay_enabled_store);
+static OVERLAY_ATTR(global_alpha, S_IRUGO|S_IWUSR,
+		overlay_global_alpha_show, overlay_global_alpha_store);
+static OVERLAY_ATTR(pre_mult_alpha_en, S_IRUGO|S_IWUSR,
+		overlay_pre_mult_alpha_en_show,
+		overlay_pre_mult_alpha_en_store);
+static OVERLAY_ATTR(zorder, S_IRUGO|S_IWUSR,
+		overlay_zorder_show, overlay_zorder_store);
+
+static struct attribute *overlay_sysfs_attrs[] = {
+	&overlay_attr_name.attr,
+	&overlay_attr_manager.attr,
+	&overlay_attr_input_size.attr,
+	&overlay_attr_screen_width.attr,
+	&overlay_attr_position.attr,
+	&overlay_attr_output_size.attr,
+	&overlay_attr_enabled.attr,
+	&overlay_attr_global_alpha.attr,
+	&overlay_attr_pre_mult_alpha_en.attr,
+	&overlay_attr_zorder.attr,
+	NULL
+};
+
+static ssize_t overlay_attr_show(struct kobject *kobj, struct attribute *attr,
+		char *buf)
+{
+	struct owl_overlay *overlay;
+	struct overlay_attribute *overlay_attr;
+
+	overlay = container_of(kobj, struct owl_overlay, kobj);
+	overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+	if (!overlay_attr->show)
+		return -ENOENT;
+
+	return overlay_attr->show(overlay, buf);
+}
+
+static ssize_t overlay_attr_store(struct kobject *kobj, struct attribute *attr,
+		const char *buf, size_t size)
+{
+	struct owl_overlay *overlay;
+	struct overlay_attribute *overlay_attr;
+
+	overlay = container_of(kobj, struct owl_overlay, kobj);
+	overlay_attr = container_of(attr, struct overlay_attribute, attr);
+
+	if (!overlay_attr->store)
+		return -ENOENT;
+
+	return overlay_attr->store(overlay, buf, size);
+}
+
+static const struct sysfs_ops overlay_sysfs_ops = {
+	.show = overlay_attr_show,
+	.store = overlay_attr_store,
+};
+
+static struct kobj_type overlay_ktype = {
+	.sysfs_ops = &overlay_sysfs_ops,
+	.default_attrs = overlay_sysfs_attrs,
+};
+
+int owl_dss_get_num_overlays(void)
+{
+	return num_overlays;
+}
+EXPORT_SYMBOL(owl_dss_get_num_overlays);
+
+struct owl_overlay *owl_dss_get_overlay(int num)
+{
+	if (num >= num_overlays)
+		return NULL;
+
+	return &overlays[num];
+}
+EXPORT_SYMBOL(owl_dss_get_overlay);
+
+
+
+bool dss_ovl_is_enabled(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	//unsigned long flags;
+	bool e;
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	e = op->enabled;
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+
+	return e;
+}
+
+static void dss_apply_ovl_enable(struct owl_overlay *ovl, bool enable)
+{
+	struct ovl_priv_data *op;
+
+	op = get_ovl_priv(ovl);
+
+	if (op->enabled == enable)
+		return;
+
+	op->enabled = enable;
+	op->extra_info_dirty = true;
+}
+
+
+
+int dss_ovl_enable(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+
+	int r;
+
+	if (op->enabled) {
+		r = 0;
+		goto err1;
+	}
+
+	if (ovl->manager == NULL || ovl->manager->device == NULL) {
+		r = -EINVAL;
+		DSSERR("dss_ovl_enable %d ovl->manager %p \n", ovl->id,ovl->manager);
+		goto err1;
+	}
+	
+	dss_apply_ovl_enable(ovl, true);
+
+	return 0;
+err1:
+
+	return r;
+}
+
+int dss_ovl_disable(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	//unsigned long flags;
+	int r;
+
+	//mutex_lock(&apply_lock);
+	//printk("dss_ovl_disable (%s) op->enabled %d\n",ovl->name,op->enabled);
+	if (!op->enabled) {
+		r = 0;
+		goto err;
+	}
+
+	if (ovl->manager == NULL || ovl->manager->device == NULL) {
+		r = -EINVAL;
+		goto err;
+	}
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	dss_apply_ovl_enable(ovl, false);
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+
+	//mutex_unlock(&apply_lock);
+	//printk("dss_ovl_disable (%s) op->enabled %d ok\n",ovl->name,op->enabled);
+	return 0;
+
+err:
+	//mutex_unlock(&apply_lock);
+	return r;
+}
+int  dss_ovl_set_manager(struct owl_overlay *ovl,
+		struct owl_overlay_manager *mgr)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	//unsigned long flags;
+	int r;
+
+	if (!mgr)
+		return -EINVAL;
+
+	mutex_lock(&mgr->apply_lock);
+
+	if (ovl->manager) {
+		DSSERR("overlay '%s' already has a manager '%s'\n",
+				ovl->name, ovl->manager->name);
+		r = -EINVAL;
+		goto err;
+	}
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	if (op->enabled) {
+		//spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("overlay has to be disabled to change the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
+
+	op->channel = mgr->de_path_id;
+	op->extra_info_dirty = true;
+
+	ovl->manager = mgr;
+	
+	list_add_tail(&ovl->list, &mgr->overlays);
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+
+	/* XXX: When there is an overlay on a DSI manual update display, and
+	 * the overlay is first disabled, then moved to tv, and enabled, we
+	 * seem to get SYNC_LOST_DIGIT error.
+	 *
+	 * Waiting doesn't seem to help, but updating the manual update display
+	 * after disabling the overlay seems to fix this. This hints that the
+	 * overlay is perhaps somehow tied to the LCD output until the output
+	 * is updated.
+	 *
+	 * Userspace workaround for this is to update the LCD after disabling
+	 * the overlay, but before moving the overlay to TV.
+	 */
+
+	mutex_unlock(&mgr->apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(&mgr->apply_lock);
+	return r;
+}
+
+int dss_ovl_unset_manager(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct mutex * apply_lock = NULL;
+	int r;
+
+	if (!ovl->manager) {
+		DSSERR("failed to detach overlay: manager not set\n");
+		r = -EINVAL;
+		return r;
+	}
+	
+	apply_lock = &ovl->manager->apply_lock;
+	
+	mutex_lock(apply_lock);
+
+	if (op->enabled) {
+		//spin_unlock_irqrestore(&data_lock, flags);
+		DSSERR("overlay has to be disabled to unset the manager\n");
+		r = -EINVAL;
+		goto err;
+	}
+	
+	de_ovl_enable(op->channel,ovl->id, false);
+	
+	op->channel = -1;
+
+	ovl->manager = NULL;
+	
+	list_del(&ovl->list);
+
+	mutex_unlock(apply_lock);
+
+	return 0;
+err:
+	mutex_unlock(apply_lock);
+	return r;
+}
+int dss_ovl_set_info(struct owl_overlay *ovl,
+		struct owl_overlay_info *info)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	//unsigned long flags;
+	int r;
+
+	r = dss_ovl_simple_check(ovl, info);
+	if (r)
+		return r;
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	op->user_info = *info;
+	op->user_info_dirty = true;
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+
+	return 0;
+}
+
+void dss_ovl_get_info(struct owl_overlay *ovl,
+		struct owl_overlay_info *info)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	//unsigned long flags;
+
+	//spin_lock_irqsave(&data_lock, flags);
+
+	*info = op->user_info;
+
+	//spin_unlock_irqrestore(&data_lock, flags);
+}
+
+static int dss_ovl_apply_info(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op;
+
+	op = get_ovl_priv(ovl);
+	DSSDBG("owl_dss_mgr_apply_ovl(%s),op->user_info_dirty %d\n", ovl->name,op->user_info_dirty);
+	if (!op->user_info_dirty)
+		return 0;
+
+	op->user_info_dirty = false;
+	op->info_dirty = true;
+	op->info = op->user_info;
+
+    return 0;
+}
+
+static int dss_ovl_write_regs(struct owl_overlay *ovl)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct owl_overlay_info *oi;
+	bool ilace = false;
+	int r;
+
+	DSSDBG("dss_ovl_write_regs %d op->enabled %d op->info_dirty %d \n", ovl->id,op->enabled,op->info_dirty);
+
+	if (!op->enabled || !op->info_dirty)
+		goto dss_ovl_write_regs_extra;
+
+	oi = &op->info;
+
+	//ilace = ovl->manager->device->type == OWL_DISPLAY_TYPE_VENC;
+
+	r = de_ovl_setup(op->channel,ovl->id, oi, ilace);
+	
+	if (r) {
+		/*
+		 * We can't do much here, as this function can be called from
+		 * vsync interrupt.
+		 */
+		DSSERR("dispc_ovl_setup failed for ovl %d\n", ovl->id);
+
+		/* This will leave fifo configurations in a nonoptimal state */
+		op->enabled = false;
+		de_ovl_enable(op->channel,ovl->id, false);
+		return r;
+	}
+	
+	op->info_dirty = false;
+	
+dss_ovl_write_regs_extra:
+			
+	if (!op->extra_info_dirty)
+		return 0;
+
+	/* note: write also when op->enabled == false, so that the ovl gets
+	 * disabled */
+	
+	de_ovl_enable(op->channel,ovl->id, op->enabled);
+
+	op->extra_info_dirty = false;
+	
+	return 0;
+	
+}
+
+static int dss_ovl_enable_mmu(struct owl_overlay *ovl,bool enable)
+{
+	struct ovl_priv_data *op = get_ovl_priv(ovl);
+	struct owl_overlay_info *oi;
+	
+	oi = &op->info;
+	
+	if(oi->enable_mmu == enable)
+	{
+		return 0;
+	}
+	oi->enable_mmu = enable;
+	
+	owl_de_mmu_enable(ovl->id, oi->enable_mmu);		
+	
+	return 0;
+	
+}
+void dss_init_overlays(struct platform_device *pdev)
+{
+	int i, r;
+
+	num_overlays = dss_feat_get_num_ovls();
+
+	overlays = kzalloc(sizeof(struct owl_overlay) * num_overlays,
+			GFP_KERNEL);
+
+	BUG_ON(overlays == NULL);
+
+	for (i = 0; i < num_overlays; ++i) {
+		struct owl_overlay *ovl = &overlays[i];
+		struct ovl_priv_data * op = get_ovl_priv(ovl);
+		op->info.global_alpha = 255;
+		switch (i) {
+		case 0:
+			ovl->name = "vid1";
+			ovl->id = OWL_DSS_VIDEO1;
+			op->info.zorder = 0;
+			break;
+		case 1:
+			ovl->name = "vid2";
+			ovl->id = OWL_DSS_VIDEO2;
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 3 : 0;
+			break;
+		case 2:
+			ovl->name = "vid3";
+			ovl->id = OWL_DSS_VIDEO3;
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 2 : 0;
+			break;
+		case 3:
+			ovl->name = "vid4";
+			ovl->id = OWL_DSS_VIDEO4;
+			op->info.zorder =
+				dss_has_feature(FEAT_ALPHA_FREE_ZORDER) ? 1 : 0;
+			break;
+		}
+		op->user_info = op->info;
+		ovl->is_enabled = &dss_ovl_is_enabled;
+		ovl->enable = &dss_ovl_enable;
+		ovl->disable = &dss_ovl_disable;
+		ovl->set_manager = &dss_ovl_set_manager;
+		ovl->unset_manager = &dss_ovl_unset_manager;
+		ovl->set_overlay_info = &dss_ovl_set_info;
+		ovl->get_overlay_info = &dss_ovl_get_info;
+		ovl->apply_overlay_info = &dss_ovl_apply_info;
+		ovl->write_hw_regs = &dss_ovl_write_regs;
+		ovl->enable_overlay_mmu = &dss_ovl_enable_mmu;
+
+		ovl->caps = dss_feat_get_overlay_caps(ovl->id);
+		ovl->supported_modes = 
+			dss_feat_get_supported_color_modes(ovl->id);
+
+		r = kobject_init_and_add(&ovl->kobj, &overlay_ktype,
+				&pdev->dev.kobj, "overlay%d", i);
+
+		if (r)
+			DSSERR("failed to create sysfs file\n");
+	}
+}
+void dss_uninit_overlays(struct platform_device *pdev)
+{
+	int i;
+
+	for (i = 0; i < num_overlays; ++i) {
+		struct owl_overlay *ovl = &overlays[i];
+
+		kobject_del(&ovl->kobj);
+		kobject_put(&ovl->kobj);
+	}
+
+	kfree(overlays);
+	overlays = NULL;
+	num_overlays = 0;
+}
+
+int dss_ovl_simple_check(struct owl_overlay *ovl,
+		const struct owl_overlay_info *info)
+{
+	if (info->paddr == 0 && info->vaddr == 0 && info->buffer_id == 0) {
+		DSSERR("check_overlay: paddr/vaddr/fd cannot be 0\n");
+		return -EINVAL;
+	}
+
+	if ((ovl->caps & OWL_DSS_OVL_CAP_SCALE) == 0) {
+		if (info->out_width != 0 && info->width != info->out_width) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+
+		if (info->out_height != 0 && info->height != info->out_height) {
+			DSSERR("check_overlay: overlay %d doesn't support "
+					"scaling\n", ovl->id);
+			return -EINVAL;
+		}
+	}
+
+	if ((ovl->supported_modes & info->color_mode) == 0 && info->color_mode != 0) {
+		DSSERR("check_overlay: overlay %d doesn't support mode %d\n",
+				ovl->id, info->color_mode);
+		return -EINVAL;
+	}
+
+	if (info->zorder >= owl_dss_get_num_overlays()) {
+		DSSERR("check_overlay: zorder %d too high\n", info->zorder);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int dss_ovl_check(struct owl_overlay *ovl,
+		struct owl_overlay_info *info, struct owl_dss_device *dssdev)
+{
+	u16 outw, outh;
+	u16 dw, dh;
+
+	if (dssdev == NULL || dssdev->driver == NULL)
+		return 0;
+
+	dssdev->driver->get_resolution(dssdev, &dw, &dh);
+	
+	if(info->img_width == 0 || info->img_height == 0){
+		info->img_width = info->width;
+		info->img_height = info->height;
+	}
+
+	if ((ovl->caps & OWL_DSS_OVL_CAP_SCALE) == 0) {
+		outw = info->width;
+		outh = info->height;
+	} else {
+		if (info->out_width == 0)
+			outw = info->width;
+		else
+			outw = info->out_width;
+
+		if (info->out_height == 0)
+			outh = info->height;
+		else
+			outh = info->out_height;
+	}
+
+	if (dw < info->pos_x + outw) {
+		DSSDBG("overlay %d horizontally not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_x, outw, dw);
+		return -EINVAL;
+	}
+
+	if (dh < info->pos_y + outh) {
+		DSSDBG("overlay %d vertically not inside the display area "
+				"(%d + %d >= %d)\n",
+				ovl->id, info->pos_y, outh, dh);
+		return -EINVAL;
+	}
+	
+	if(dssdev->driver->get_effect_parameter){
+		info->lightness = dssdev->driver->get_effect_parameter(dssdev,OWL_DSS_VIDEO_LIGHTNESS);
+		info->saturation = dssdev->driver->get_effect_parameter(dssdev,OWL_DSS_VIDEO_SATURATION);
+		info->contrast = dssdev->driver->get_effect_parameter(dssdev,OWL_DSS_VIDEO_CONSTRAST);
+		DSSDBG("get_effect_parameter lightness %d saturation %d contrast %d\n",info->lightness,info->saturation,info->contrast);
+	}else{
+		info->lightness = DEF_LIGHTNESS;
+		info->saturation = DEF_SATURATION;
+		info->contrast = DEF_CONTRAST;			
+	}
+	return 0;
+}
diff --git a/drivers/video/fbdev/owl/fb/Kconfig b/drivers/video/fbdev/owl/fb/Kconfig
new file mode 100755
index 0000000..77854e5
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/Kconfig
@@ -0,0 +1,21 @@
+config FB_COLOR_MODE_XRGB32
+	bool "use xrgb32 color mode, default is xbgr32"
+
+config FB_MAP_TO_DE
+	bool "map fb to de"
+	
+config FB_DEFAULT_MIRROR_TO_HDMI
+	bool "mirror fb to hdmi as default"
+
+config VIDEO_OWL_FB
+	tristate "OWL framebuffer support"
+	select FB_CFB_FILLRECT
+	select FB_CFB_COPYAREA
+	select FB_CFB_IMAGEBLIT
+	---help---
+	  Actions OWL Soc framebuffer support.
+
+	  Say Y here if you need it in your system.
+	  If unsure, say Y.
+
+	  To compile this driver as a module, choose M here.
diff --git a/drivers/video/fbdev/owl/fb/Makefile b/drivers/video/fbdev/owl/fb/Makefile
new file mode 100755
index 0000000..625c63b
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIDEO_OWL_FB) += owlfb.o
+owlfb-y := owlfb-main.o owlfb-dc.o owlfb-sysfs.o owlfb-ioctl.o owlfb-dc-debug.o owl-ddr-debug.o
diff --git a/drivers/video/fbdev/owl/fb/owl-ddr-debug-readme.txt b/drivers/video/fbdev/owl/fb/owl-ddr-debug-readme.txt
new file mode 100755
index 0000000..b42109e
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owl-ddr-debug-readme.txt
@@ -0,0 +1,99 @@
+\D4\DAdebug fs \B4򿪵\C4\C7\E9\BF\F6\CF£\AC\D4\DAϵͳ\CF\C2\C3\E6\D3и\F6Ŀ¼ dmm
+/sys/kernel/debug/dmm/
+  	enable
+	master0
+	   id 
+	   mode
+	master1
+	   id 
+	   mode
+	max_statistic_cnt
+	result
+	sampling_rate
+	statistic_cnt
+	
+enable: \BF\AAʼ\BB\F2\D5\DF\CA\C7ֹͣͳ\BC\C6 
+      \BF\AAʼͳ\BC\C6 echo 1 > enable 
+      ֹͣͳ\BC\C6 echo 0 > enable 
+      
+master0 \BA\CD master1 \B7ֱ\F0\CA\C7\D0\E8Ҫͳ\BCƵ\C4\C1\BD\B8\F6master \D0\C5Ϣ
+
+id \A3\BA\D4\DAѡ\D4\F1ID \B5\C4ʱ\BA\F2 \D0\E8Ҫ\B8\F9\BEݴ\CBֵ\BD\F8\D0\D0\C9\E8\D6\C3
+	MASTER_ID_CPU = 0,
+	MASTER_ID_USB3,
+	MASTER_ID_VCE,
+	MASTER_ID_ENTHERNET,
+	MASTER_ID_USB2,
+	MASTER_ID_DE,
+	MASTER_ID_GPU3D,
+	MASTER_ID_SI,
+	MASTER_ID_DMA,
+	MASTER_ID_DAP,
+	MASTER_ID_ALL,
+	MASTER_ID_IDLE,
+	
+mode \A3\BA\D4\DAѡ\D4\F1MODE  \B5\C4ʱ\BA\F2 \D0\E8Ҫ\B8\F9\BEݴ\CBֵ\BD\F8\D0\D0\C9\E8\D6\C3
+	MASTER_MODE_READ = 0,   // ͳ\BCƶ\C1
+	MASTER_MODE_WRITE, //ͳ\BC\C6д
+	MASTER_MODE_ALL, //ͳ\BCƶ\C1д
+
+\BF\C9\D2\D4ͨ\B9\FD\C9\E8\D6\C3\C0\B4\D0޸\C4\D0\E8Ҫͳ\BCƵ\C4master \BA\CDͳ\BCƵ\C4ģʽ
+
+max_statistic_cnt\A3\BA \D7\EE\B4\F3\C4ܹ\BBͳ\BCƵĴ\CE\CA\FD\A3\ACֻҪ\CA\C7\C4ڴ\E6\CF\DE\D6ơ\A3Ĭ\C8\CF\CA\C71000\B4Σ\AC\BF\C9\D2\D4ͨ\B9\FDecho 2000 > max_statistic_cnt \C0\B4\D0޸\C4
+
+sampling_rate\A3\BA\B2\C9\D1\F9\B5ļ\E4\B8\F4ʱ\BC䣬 Ĭ\C8\CF\CA\C71s ͳ\BC\C6һ\B4Σ\ACҲ\BF\C9\D2\D4ͨ\B9\FDecho 2000 > sampling_rate \D0޸ġ\A3
+
+statistic_cnt\A3\BA\B5\B1ǰͳ\BC\C6\C1˶\E0\C9ٴΣ\ACֻ\B6\C1\A1\A3ͨ\B9\FDcat statistic_cnt \B6\C1ȡ
+
+result:ͳ\BCƵĽ\E1\B9\FB\A3\ACֻ\B6\C1 ͨ\B9\FDcat result \BB\F1ȡ
+\BD\E1\B9\FB˵\C3\F7\A3\BA
+       master id:   mode   bandwidth(M byte)     percent of total(%)        master id:   mode   bandwidth(M byte)    percent of total(%)
+             ALL:    RW               400                         13            IDLE:    RW               433                         85 
+             ALL:    RW               612                         21            IDLE:    RW              1178                         60 
+             ALL:    RW               714                         24            IDLE:    RW               989                         66 
+             ALL:    RW               616                         21            IDLE:    RW              1165                         60 
+             ALL:    RW               635                         22            IDLE:    RW              1128                         61 
+             ALL:    RW               667                         23            IDLE:    RW              1067                         63 
+             ALL:    RW               625                         21            IDLE:    RW              1145                         61 
+             ALL:    RW               655                         22            IDLE:    RW              1096                         62 
+             ALL:    RW               649                         22            IDLE:    RW              1110                         62 
+master id : ָͳ\BCƵ\C4\CA\C7\C4Ǹ\F6master \C8磺 all \B1\ED\C3\F7\CB\F9\D3е\C4master \A3\ACIDLE \B1\EAʾͳ\BC\C6DDR IDEL \B5\C4ʱ\BC\E4
+MODE \A3\BA ָ\CA\C7ͳ\BCƵ\C4ģʽ\A3\AC R \A3\ACW \A3\AC RW \B5\C83\D6\D0ģʽ
+bandwidth\A3\BAͳ\BCƵ\C4master\D4\DAָ\B6\A8ʱ\BC\E4\C4ڵĴ\F8\BF\ED\A3\ACM Ϊ\B5\A5λ 400M byte
+percent of total\A3\BA ͳ\BCƵİٷֱȣ\AC\CAǵ\B1ǰmaster \B5Ĵ\F8\BF\ED\BA\CDϵͳ\C0\ED\C2\DB\D7ܴ\F8\BF\ED\B5ıȣ\AC IDLE \CAǸ\F6\C0\FD\CD⣬\B5\B1ͳ\BC\C6IDLE\B5\C4ʱ\BA򣬴\CBʱ\B5İٷֱȻ\BB\CB\E3Ϊ\C1˷\C7IDLE\B5\C4cycle \BA\CDϵͳDDR\D7ܵ\C4cycle ֮\BC\E4\B5ı\C8\C0\FD
+
+ʹ\D3\C3\C1\F7\B3̣\BA
+1.\C9\E8\D6\C3\CF\E0\B9ز\CE\CA\FD
+2.\BF\AAʼͳ\BC\C6 
+3.ֹͣͳ\BC\C6
+4.\B2鿴\BD\E1\B9\FB
+  
+  
+\C8磺\D0\E8Ҫͳ\BC\C6DE \B5Ĵ\F8\BF\ED\BA\CDGPU\B5Ĵ\F8\BF\ED\A3\AC\B2\C9\D1\F9\C2\CA\CA\C72s\B2\C9\D1\F9һ\B4Σ\AC\D7\EE\B4\F3ͳ\BCƴ\CE\CA\FDΪ 500\B4\CE
+echo 5 > /sys/kernel/debug/dmm/master0/id 
+echo 0 > /sys/kernel/debug/dmm/master0/mode 
+echo 6 > /sys/kernel/debug/dmm/master1/id
+echo 2 > /sys/kernel/debug/dmm/master1/mode
+
+echo 2000 > /sys/kernel/debug/dmm/sampling_rate
+echo 500 > /sys/kernel/debug/dmm/max_statistic_cnt
+
+echo 1 > /sys/kernel/debug/dmm/enable
+\B2\D9\D7\F7UI һ\B6\CEʱ\BC\E4\BA\F3
+\A1\A3\A1\A3\A1\A3\A1\A3\A1\A3\A1\A3
+echo 0 > /sys/kernel/debug/dmm/enable
+
+cat /sys/kernel/debug/dmm/result > /data/result.txt
+\B2鿴\BD\E1\B9\FB
+
+
+
+Ĭ\C8\CF\C7\E9\BF\F6\CF\C2ͳ\BCƵ\C4\CA\C7 \CB\F9\D3\D0master \B5Ĵ\F8\BF\ED\BA\CD IDLE \B5\C4\C7\E9\BF\F6\A3\AC\B2\C9\D1\F9\C2\CA\CA\C71s \A3\AC\D7\EE\B4\F3ͳ\BCƴ\CE\CA\FD\CA\C71000\B4\CE
+
+\C8磺 
+echo 1 > /sys/kernel/debug/dmm/enable
+\B2\D9\D7\F7UI һ\B6\CEʱ\BC\E4\BA\F3
+\A1\A3\A1\A3\A1\A3\A1\A3\A1\A3\A1\A3
+echo 0 > /sys/kernel/debug/dmm/enable
+
+cat /sys/kernel/debug/dmm/result > /data/result.txt  \BE\CD\CAǰ\B4\D5\D5\C9\CF\C3\E6\B5\C4Ĭ\C8\CF\C9\E8\D6ý\F8\D0\D0ͳ\BCơ\A3
diff --git a/drivers/video/fbdev/owl/fb/owl-ddr-debug.c b/drivers/video/fbdev/owl/fb/owl-ddr-debug.c
new file mode 100755
index 0000000..d89e924
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owl-ddr-debug.c
@@ -0,0 +1,461 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-main.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+ 
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <video/owldss.h>
+#include <video/owlfb.h>
+#include <video/owldisplay.h>
+#include <linux/hrtimer.h>
+#include <linux/debugfs.h>
+#include <linux/uaccess.h>
+#include "owlfb.h"
+
+#define DCU_BASE_ADDR  0xb0290000
+#define CMU_DDRPLL_REG 0xb0160008
+#define DEFAULT_SIMPLE_RATE 1000 //ms
+#define DEFAULT_MAX_STATISTIC_CNT 1000 //times
+#define MAX_MASTER_NUMBER 2 
+#define MS_TO_NS(x) (x * 1000000)
+
+enum master_id {
+	MASTER_ID_CPU = 0,
+	MASTER_ID_USB3,
+	MASTER_ID_VCE,
+	MASTER_ID_ENTHERNET,
+	MASTER_ID_USB2,
+	MASTER_ID_DE,
+	MASTER_ID_GPU3D,
+	MASTER_ID_SI,
+	MASTER_ID_DMA,
+	MASTER_ID_DAP,
+	MASTER_ID_ALL,
+	MASTER_ID_IDLE,
+};
+const char * name_of_master[MASTER_ID_IDLE + 1] = {
+	"CPU",
+	"USB3",
+	"VCE",
+	"ENTHERNET",
+	"USB2",
+	"DE",
+	"GPU3D",
+	"SI",
+	"DMA",
+	"DAP",
+	"ALL",
+	"IDLE",
+};
+enum master_mode {
+	MASTER_MODE_READ = 0,
+	MASTER_MODE_WRITE = 1,
+	MASTER_MODE_ALL = 2,
+};
+const char * name_of_mode[MASTER_MODE_ALL + 1] = {
+	"R",
+	"W",
+	"RW",	
+};
+struct master_info{
+	int id;
+	int mode;
+};
+
+struct staticstic_result{
+	int pc[MAX_MASTER_NUMBER];
+};
+
+struct dmm_statistic_info{
+	struct dentry *fs_rootdir;
+	struct dentry *fs_enable;
+	struct dentry *fs_statistic_cnt;
+	struct dentry *fs_sampling_rate;
+	struct dentry *fs_max_statistic_cnt;
+	struct dentry *fs_master_root[MAX_MASTER_NUMBER];
+	struct dentry *master_id[MAX_MASTER_NUMBER];
+	struct dentry *master_mode[MAX_MASTER_NUMBER];
+	struct dentry *fs_result;
+	
+	u32 debug_enable;
+	bool actived;
+	u32 statistic_cnt;
+	u32 max_statistic_cnt;
+	struct hrtimer timer;	
+    u32 sampling_rate;
+	int ddr_clk; // MHZ
+	void __iomem * DMM_PM_CTRL0;
+	void __iomem * DMM_PC0;
+	void __iomem * DMM_PC1;
+    void __iomem * CMU_DDRPLL;
+	struct master_info master[MAX_MASTER_NUMBER];
+	struct staticstic_result * result;
+};
+
+static struct dmm_statistic_info dmm;
+
+void dmm_start_statistic(struct dmm_statistic_info * info) 
+{
+	int i = 0;
+	int temp_dmm_ctrl = 0;
+	
+    writel(0,info->DMM_PM_CTRL0); //WRITE 0 TO CLEAR PC0 AND PC1
+    
+    for(i = 0; i < MAX_MASTER_NUMBER; i++)
+    {
+    	int temp = 0;
+    	struct master_info * master = &info->master[i];
+    	temp |=  master->mode << 4;
+    	switch(master->id){
+    		case MASTER_ID_ALL:
+    		  temp |= (1 << 8);
+    		  break;
+    		case MASTER_ID_IDLE:
+    		  temp |= (2 << 8);
+    		  break;
+    	    default:
+    	      temp |= (0 << 8);
+    	      temp |= master->id;
+    	      break;
+    	}
+    	temp |= (1 << 15);
+    	temp_dmm_ctrl |= (temp << ( i * 16));
+    	
+    }
+    
+    writel(temp_dmm_ctrl,info->DMM_PM_CTRL0); //WRITE 0 TO CLEAR PC0 AND PC1 
+}
+
+void dmm_get_statistic_result(struct dmm_statistic_info * info) 
+{
+	struct staticstic_result * result = NULL;
+	if(info->statistic_cnt >=  info->max_statistic_cnt){
+		printk(" out of memory ,you set max_statistic cnt is %d \n",info->max_statistic_cnt);
+		return ;
+	}
+    result = &info->result[info->statistic_cnt];
+    result->pc[0] = readl(info->DMM_PC0);
+    result->pc[1] = readl(info->DMM_PC1);
+    
+    if((readl(info->DMM_PM_CTRL0) & ( (1<< 22) | (1 << 6) )) != 0){
+    	printk("DMM_PM_CTRL0 overlflow 0x%x \n",readl(info->DMM_PM_CTRL0));
+    }
+
+}
+
+static enum hrtimer_restart hr_timer_func(struct hrtimer *timer)    
+{
+	unsigned long missed;
+	if(dmm.statistic_cnt != 0){
+		dmm_get_statistic_result(&dmm);		
+	}
+		
+	dmm_start_statistic(&dmm);
+	
+	missed = hrtimer_forward_now(timer, ktime_set(0, MS_TO_NS(dmm.sampling_rate)));
+	
+	if (missed > 1)
+		printk("Missed ticks %ld\n", missed - 1);
+	dmm.statistic_cnt ++;	
+ 	return HRTIMER_RESTART;
+}
+
+static ssize_t dmm_debug_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buf[3];	
+
+	u32 *val = filp->private_data;
+
+	if (*val)
+	{
+		buf[0] = 'Y';
+	}
+	else
+	{
+		buf[0] = 'N';
+	}
+	buf[1] = '\n';
+	buf[2] = 0x00;
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
+}
+static ssize_t dmm_result_read(struct file *filp, char __user *user_buf, size_t count, loff_t *ppos)
+{
+	ssize_t out_count = PAGE_SIZE * 30, offset = 0;
+	char * buf;
+	int i = 0,r;
+	int j = 0;
+	long total_bandwidth = dmm.ddr_clk * 8 * dmm.sampling_rate / 1000;
+	
+	buf = kmalloc(out_count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;	
+		
+	offset += snprintf(buf + offset, out_count - offset, "%16s: ","master id");	
+	offset += snprintf(buf + offset, out_count - offset, "%6s","mode");
+	offset += snprintf(buf + offset, out_count - offset, "%20s","bandwidth(M byte)");
+	offset += snprintf(buf + offset, out_count - offset, "%24s ","percent of total(%)");	
+	offset += snprintf(buf + offset, out_count - offset, "%16s: ","master id");	
+	offset += snprintf(buf + offset, out_count - offset, "%6s","mode");
+	offset += snprintf(buf + offset, out_count - offset, "%20s","bandwidth(M byte)");
+	offset += snprintf(buf + offset, out_count - offset, "%24s ","percent of total(%)\n");	
+	
+	for(i = 0 ; i < dmm.statistic_cnt; i++)
+	{
+		struct staticstic_result * result = &dmm.result[i];		   
+		
+		for(j = 0 ; j < MAX_MASTER_NUMBER ; j++)
+		{
+			long bandwidth = result->pc[j] * 16 / (1024 * 1024);
+			offset += snprintf(buf + offset, out_count - offset, "%16s:",name_of_master[dmm.master[j].id]);
+			offset += snprintf(buf + offset, out_count - offset, "%6s",name_of_mode[dmm.master[j].mode]);
+			
+			offset += snprintf(buf + offset, out_count - offset, "%18ld   ",bandwidth);	
+			if(dmm.master[j].id == MASTER_ID_IDLE){			
+				offset += snprintf(buf + offset, out_count - offset, "%24ld", 100  - bandwidth * 100 / total_bandwidth);			
+			}else{
+				offset += snprintf(buf + offset, out_count - offset, "%24ld",bandwidth * 100 / total_bandwidth);			
+			}
+		}
+		offset += snprintf(buf + offset, out_count - offset, " \n");	
+	}
+	r =  simple_read_from_buffer(user_buf, count, ppos, buf, offset);
+	kfree(buf);	
+	return r;
+}
+
+static ssize_t dmm_debug_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char buf[32];
+	int buf_size;
+	
+	u32 *val = filp->private_data;
+	
+	buf_size = min(count, (sizeof(buf)-1));
+	
+	if (copy_from_user(buf, user_buf, buf_size))
+		return -EFAULT;
+	
+	switch (buf[0]) {
+		case 'y':
+		case 'Y':
+		case '1':
+			*val = 1;
+		break;
+		case 'n':
+		case 'N':
+		case '0':
+			*val = 0;
+		break;
+	}
+	
+	dmm.debug_enable = *val;
+	
+	if(dmm.debug_enable){
+		if(!dmm.actived){
+			dmm.statistic_cnt = 0;
+			if(dmm.result != NULL){
+				kfree(dmm.result);
+			}
+			dmm.result = kmalloc(sizeof(struct staticstic_result)* dmm.max_statistic_cnt, GFP_KERNEL);
+			hrtimer_start(&dmm.timer, ktime_set(0, MS_TO_NS(dmm.sampling_rate)),HRTIMER_MODE_REL);
+			dmm.actived = true;
+		}else{
+			printk("already actived debug\n");
+		}
+	}else{
+		if(dmm.actived){
+			hrtimer_cancel(&dmm.timer);
+			dmm.actived = false;			
+		}else{
+			printk("already stopped debug \n");
+		}
+	}	
+	pr_info("dmm debug enable %d \n",dmm.debug_enable);
+	return count;
+}
+static int dmm_debug_open(struct inode *inode, struct file *filp)
+{
+    filp->private_data = inode->i_private;
+    return 0;
+}
+
+static struct file_operations dmm_debug_fops = {
+	.open = dmm_debug_open,
+	.read = dmm_debug_read,
+	.write = dmm_debug_write,
+};
+
+static struct file_operations dmm_result_fops = {
+	.open = simple_open,
+	.read = dmm_result_read,
+	.llseek = default_llseek,
+};
+
+static int owl_dmm_create_debug_sysfs(void)
+{
+	int rc = 0;
+	int i;
+    
+    
+    dmm.fs_rootdir = debugfs_create_dir("dmm",NULL);
+    
+    
+    if (IS_ERR(dmm.fs_rootdir)) {
+		rc = PTR_ERR(dmm.fs_rootdir);
+		dmm.fs_rootdir = NULL;
+		goto out;
+	}
+	
+	dmm.fs_enable = debugfs_create_file("enable",S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, dmm.fs_rootdir, &dmm.debug_enable , &dmm_debug_fops); 
+	if (dmm.fs_enable == NULL){
+		rc = -EIO;
+		pr_err("debug file enable create failed \n");
+		goto out;
+	}
+	
+	dmm.fs_result = debugfs_create_file("result",S_IRUSR  | S_IRGRP , dmm.fs_rootdir, NULL , &dmm_result_fops); 
+	if (dmm.fs_enable == NULL){
+		rc = -EIO;
+		pr_err("debug file result create failed \n");
+		goto out;
+	}
+	
+	dmm.fs_max_statistic_cnt = debugfs_create_u32("max_statistic_cnt", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, dmm.fs_rootdir,&dmm.max_statistic_cnt);
+	if (dmm.fs_max_statistic_cnt == NULL){
+		rc = -EIO;
+		pr_err("debug file max_statistic_cnt create failed \n");
+		goto out;
+	}
+	
+	dmm.fs_sampling_rate = debugfs_create_u32("sampling_rate", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, dmm.fs_rootdir,&dmm.sampling_rate);
+	if (dmm.fs_sampling_rate == NULL){
+		rc = -EIO;
+		pr_err("debug file sampling_rate create failed \n");
+		goto out;
+	}
+	
+	dmm.fs_statistic_cnt = debugfs_create_u32("statistic_cnt", S_IRUSR  | S_IRGRP, dmm.fs_rootdir,&dmm.statistic_cnt);
+	if (dmm.fs_statistic_cnt == NULL){
+		rc = -EIO;
+		pr_err("debug file sampling_rate create failed \n");
+		goto out;
+	}
+		
+	for(i = 0 ; i < MAX_MASTER_NUMBER;i++){
+		
+		if(i == 0){ 
+			dmm.fs_master_root[i] = debugfs_create_dir("master0",dmm.fs_rootdir);    
+    	}else{
+    		dmm.fs_master_root[i] = debugfs_create_dir("master1",dmm.fs_rootdir);
+    	}
+    	
+	    if (IS_ERR(dmm.fs_master_root[i] )) {
+			rc = PTR_ERR(dmm.fs_rootdir);
+			dmm.fs_rootdir = NULL;
+			pr_err("debug file master create failed\n");
+			goto out;
+		}
+		
+		dmm.master_id[i] = debugfs_create_u32("id", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP, dmm.fs_master_root[i] , &dmm.master[i].id);
+		if (dmm.master_id[i] == NULL){
+			rc = -EIO;
+			pr_err("debug file id create failed \n");
+			goto out;
+		}
+		dmm.master_mode[i] = debugfs_create_u32("mode", S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP,dmm.fs_master_root[i] ,&dmm.master[i].mode);
+		if (dmm.master_mode[i] == NULL){
+			rc = -EIO;
+			pr_err("debug file mode create failed\n");
+			goto out;
+		}
+	}
+	pr_info("dmm debugfs support\n");
+
+out:
+	if (rc)
+		pr_warn("unable to init\n");   
+	
+	return rc;
+}
+
+static void owl_dmm_remove_debug_sysfs(void)
+{
+	int i;
+	for(i = 0 ; i < MAX_MASTER_NUMBER;i++){
+		debugfs_remove(dmm.master_mode[i]);
+		debugfs_remove(dmm.master_id[i]);
+		debugfs_remove(dmm.fs_master_root[i]);
+	}
+	debugfs_remove(dmm.fs_max_statistic_cnt);
+	debugfs_remove(dmm.fs_sampling_rate);
+	debugfs_remove(dmm.fs_statistic_cnt);
+	debugfs_remove(dmm.fs_enable);
+	debugfs_remove(dmm.fs_result);
+	debugfs_remove(dmm.fs_rootdir);	
+	
+	return;
+}
+
+int __init dmm_debug_init_function(void)
+{
+	
+	dmm.DMM_PM_CTRL0 = ioremap(DCU_BASE_ADDR + 0x48,4);
+	dmm.DMM_PC0 = ioremap(DCU_BASE_ADDR + 0x50,4);
+	dmm.DMM_PC1 = ioremap(DCU_BASE_ADDR + 0x54,4);
+	dmm.CMU_DDRPLL = ioremap(CMU_DDRPLL_REG,4);
+	
+	dmm.ddr_clk = (readl(dmm.CMU_DDRPLL)& 0xff) * 12;
+	
+	hrtimer_init(&(dmm.timer), CLOCK_MONOTONIC, HRTIMER_MODE_REL);   
+	dmm.timer.function = hr_timer_func;
+	dmm.sampling_rate = DEFAULT_SIMPLE_RATE;
+	
+	dmm.master[0].id = MASTER_ID_ALL;
+	dmm.master[0].mode = MASTER_MODE_ALL;
+
+	dmm.master[1].id = MASTER_ID_IDLE;
+	dmm.master[1].mode = MASTER_MODE_ALL;
+	dmm.max_statistic_cnt = DEFAULT_MAX_STATISTIC_CNT;
+	owl_dmm_create_debug_sysfs();
+	
+	return 0;
+		
+}
+
+void dmm_debug_uninit_function(void)
+{
+    iounmap(dmm.DMM_PM_CTRL0);
+	iounmap(dmm.DMM_PC0);
+	iounmap(dmm.DMM_PC1);
+	iounmap(dmm.CMU_DDRPLL);
+	hrtimer_cancel(&dmm.timer);
+	owl_dmm_remove_debug_sysfs();
+	
+	if(dmm.result != NULL){
+		kfree(dmm.result);
+	}
+}
+
+arch_initcall(dmm_debug_init_function);
+
+
diff --git a/drivers/video/fbdev/owl/fb/owlfb-dc-debug.c b/drivers/video/fbdev/owl/fb/owlfb-dc-debug.c
new file mode 100755
index 0000000..da2ba83
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb-dc-debug.c
@@ -0,0 +1,102 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-main.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+ 
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <video/owldss.h>
+#include <video/owlfb.h>
+#include <video/owldisplay.h>
+
+#include "owlfb.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/owlfb_trace_events.h>
+
+void trace_buffer_release(void * args)
+{
+	trace_owlfb_dc_out(args);
+}
+
+void trace_buffer_put_to_queue(void * args)
+{
+	trace_owlfb_dc_in(args);
+}
+
+void trace_buffer_put_to_dehw(void * args)
+{
+	trace_owlfb_dc_to_de(args);
+}
+
+void trace_vsync_point(int index, long long timestamp)
+{
+	trace_owlfb_vsync(index,timestamp);
+}
+
+
+static ssize_t show_dc_debug(struct device *dev,struct device_attribute *attr, char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%d\n", 0);
+}
+
+static ssize_t store_dc_debug(struct device *dev,struct device_attribute *attr, const char *buf, size_t count)
+{
+	int dc_debug_flags;
+	int r;
+
+
+	r = strtobool(buf, (bool *)&dc_debug_flags);
+		
+	if (r)
+		return r;		
+	
+	r = count;
+
+	return r;
+}
+
+static struct device_attribute owlfb_dc_attrs[] = {
+	__ATTR(dc_debug, S_IRUGO | S_IWUSR, show_dc_debug, store_dc_debug),
+};
+
+
+int owlfb_dc_create_debug_sysfs(struct owlfb_device *fbdev)
+{
+	int i;
+	int r;
+	DBG("create sysfs for fbs\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		int t;
+		for (t = 0; t < ARRAY_SIZE(owlfb_dc_attrs); t++) {
+			r = device_create_file(fbdev->fbs[i]->dev,&owlfb_dc_attrs[t]);
+
+			if (r) {
+				dev_err(fbdev->dev, "failed to create sysfs "
+						"file\n");
+				return r;
+			}
+		}
+	}
+
+	return 0;
+}
diff --git a/drivers/video/fbdev/owl/fb/owlfb-dc.c b/drivers/video/fbdev/owl/fb/owlfb-dc.c
new file mode 100755
index 0000000..bb9e283
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb-dc.c
@@ -0,0 +1,591 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-main.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+ 
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/kthread.h>
+#include <linux/of.h>
+#include <video/owldss.h>
+#include <video/owlfb.h>
+#include <video/owldisplay.h>
+
+#include "owlfb.h"
+
+#define OWLFB_DC_DISCARD_FRAME
+
+#ifdef OWLFB_DC_DISCARD_FRAME
+static atomic_t queue_cnt = ATOMIC_INIT(0);
+#endif
+struct owlfb_dc owl_dc;
+
+static struct owlfb_device * my_fbdev = NULL;
+static bool is_fb_memory_freed_after_dc = false;
+
+extern int dss_mgr_enable(struct owl_overlay_manager *mgr);
+
+extern int dss_mgr_disable(struct owl_overlay_manager *mgr);
+
+extern bool dss_check_channel_boot_inited(enum owl_de_path_id channel);
+
+enum disp_info_state {
+	STATUS_DISPINFO_NEEDS_INIT = 0,
+	STATUS_DISPINFO_PREPARED   = 1,
+	STATUS_DISPINFO_QUEUED     = 2,
+	STATUS_DISPINFO_ACTIVE     = 3,
+	STATUS_DISPINFO_DONE       = 4,
+	STATUS_DISPINFO_ERROR      = 5,
+	STATUS_DISPINFO_IDLE       = 6,
+};
+static int owlfb_dc_queue_buffer(struct owlfb_dc * dispc , setup_dispc_data_t * psDispcData, callback cb, callback_arg cba)
+{
+	int rc = 0;
+	int i = 0;
+	unsigned long flags;
+	
+	struct owl_disp_info * new_info = NULL;		
+	
+	for(i = 0; i < OWL_DCQ_DEPTH; i++){		
+		
+		struct owl_disp_info * disp_info  = &dispc->dc_queue[i];		
+		spin_lock_irqsave(&disp_info->info_lock,flags);		
+		if(disp_info->state == STATUS_DISPINFO_NEEDS_INIT){
+		   spin_unlock_irqrestore(&disp_info->info_lock,flags);		   
+		   new_info = disp_info;
+
+		   break;
+		}
+		spin_unlock_irqrestore(&disp_info->info_lock,flags);
+	}	
+	
+	if(new_info == NULL){		
+		printk("qeueu is full \n");
+		rc = -ENOMEM;		
+		goto q_err;
+	}
+	
+	memcpy(&(new_info->psDispcData), psDispcData,	sizeof(setup_dispc_data_t));	
+	
+	spin_lock_irqsave(&new_info->info_lock,flags);	
+	new_info->mCallBack = cb;
+		   
+	new_info->mCallBackArg = cba;		 
+    
+	new_info->state = STATUS_DISPINFO_QUEUED;
+	spin_unlock_irqrestore(&new_info->info_lock,flags);
+	mutex_lock(&dispc->dc_lock);
+	
+	/* Add it to the incoming queue */
+	list_add_tail(&(new_info->list), &dispc->q_list); 
+    
+	mutex_unlock(&dispc->dc_lock);
+
+	if(unlikely(!is_fb_memory_freed_after_dc) && my_fbdev != NULL){
+		
+		owlfb_free_all_fbmem_after_dc(my_fbdev);
+		
+		is_fb_memory_freed_after_dc = true;
+		
+	}
+	return rc;
+
+q_err:
+	mutex_unlock(&dispc->dc_lock);
+	return rc;
+}
+
+static int owlfb_dc_mark_buffer_done(struct owlfb_dc * dispc, int index)
+{
+	unsigned long flags;
+	int rc = 0;
+	
+	int i = 0;
+
+	for(i = 0 ; i < OWL_DCQ_DEPTH; i++){
+    	    		
+		struct owl_disp_info * disp_info  = &dispc->dc_queue[i];
+		
+		if(disp_info != NULL){			
+			if(disp_info->state == STATUS_DISPINFO_ACTIVE && index != i){
+				
+				if(disp_info->mCallBack != NULL){
+#ifdef DEBUG
+					trace_buffer_release(disp_info->mCallBackArg);
+#endif 
+					disp_info->mCallBack(disp_info->mCallBackArg,1);													
+				#ifdef OWLFB_DC_DISCARD_FRAME
+					atomic_dec(&queue_cnt);
+				#endif
+				}
+				spin_lock_irqsave(&disp_info->info_lock,flags);								
+				disp_info->state = STATUS_DISPINFO_NEEDS_INIT;
+				spin_unlock_irqrestore(&disp_info->info_lock,flags);
+			}
+		}
+	}	
+	return rc;
+}
+
+/*
+ * Dynamic assign overlayers according to the display information, the rules is:
+ * 	Put all primary layers from layer1 to layerN, and put all second layers
+ * 	from layerN to layer1, while N is the available overlay number.
+ * 	It is used to avoid that layers switch between two path frequently,
+ *	which will lead to blurred screen on LCD or HDMI.
+ */
+static bool external_manager_is_enable = false;
+static int boot_hdmi_enable = 0;
+static int boot_hdmi_status = 0;
+static int boot_hdmi_rotate = 0;
+#define HDMI_STATUS_NOT_INIT 0
+#define HDMI_STATUS_BOOT_INIT 1
+#define HDMI_STATUS_ANDROID_INIT 2
+static int boot_cvbs_rotate = 0;
+static int boot_cvbs_status = 0;
+static int boot_cvbs_enable = 0;
+#define CVBS_STATUS_BOOT_INIT 1
+#define CVBS_STATUS_NOT_INIT 0
+#define CVBS_STATUS_ANDROID_INIT 2
+atomic_t want_close_external_devices = ATOMIC_INIT(false);
+
+static int owlfb_dc_arrange_overlay(setup_dispc_data_t *psDispcData,
+					struct owl_overlay **used_ovl,struct owl_overlay **boot_external_used_ovl) {
+	const int num_ovls = owl_dss_get_num_overlays();
+	int primary_used_overlay = 0;
+	int external_used_overlay = 0;
+	int no_used_overlay = 0;
+	int used_overlay_num = 0;
+	int i = 0;
+
+	for (i = 0; i < num_ovls; i++) {
+		if (i < psDispcData->primary_display_layer_num) {
+			struct owl_overlay *ovl = owl_dss_get_overlay(primary_used_overlay);
+			if (ovl->manager != NULL
+				&& ovl->manager->id != owl_dc.primary_manager->id) {
+					  ovl->disable(ovl);
+			    	ovl->unset_manager(ovl);
+			    	ovl->set_manager(ovl,owl_dc.primary_manager); 
+			}
+			used_ovl[used_overlay_num++] = ovl;
+			primary_used_overlay ++;	
+		} else if (i < psDispcData->post2_layers) {
+			struct owl_overlay *ovl = owl_dss_get_overlay(num_ovls - external_used_overlay - 1);			
+			if (ovl->manager != NULL
+				&& ovl->manager->id != owl_dc.external_manager->id) {
+					  ovl->disable(ovl);
+			    	ovl->unset_manager(ovl);
+			    	ovl->set_manager(ovl,owl_dc.external_manager); 
+			}
+			used_ovl[used_overlay_num++] = ovl;
+			external_used_overlay ++;	
+		} else {
+			struct owl_overlay *ovl = owl_dss_get_overlay(primary_used_overlay
+									+ no_used_overlay);
+			if (ovl->is_enabled(ovl)) {
+					ovl->disable(ovl);
+			}
+			no_used_overlay ++;
+		}
+	}
+
+	if (primary_used_overlay != 0) {
+		 dss_mgr_enable(owl_dc.primary_manager);
+	}
+
+	if (external_used_overlay != 0) {
+		external_manager_is_enable = true;
+		dss_mgr_enable(owl_dc.external_manager);
+		boot_hdmi_status = HDMI_STATUS_ANDROID_INIT;
+		boot_cvbs_status=CVBS_STATUS_ANDROID_INIT;
+	
+	}else{
+		if(boot_hdmi_status == HDMI_STATUS_ANDROID_INIT||boot_cvbs_status==CVBS_STATUS_ANDROID_INIT){
+			if(external_manager_is_enable && atomic_read(&want_close_external_devices)){	
+				owl_dc.external_manager->apply(owl_dc.external_manager);
+				owl_dc.external_manager->wait_for_go(owl_dc.external_manager);	
+				owl_dc.external_manager->device->driver->disable(owl_dc.external_manager->device);
+				external_manager_is_enable = false;
+				atomic_set(&want_close_external_devices,false);
+			}
+		}else{
+			if(boot_hdmi_status == HDMI_STATUS_NOT_INIT 
+				&& dss_check_channel_boot_inited(OWL_DSS_OVL_MGR_EXTERNAL)
+				&& boot_hdmi_enable == 1)
+			{
+				boot_hdmi_status = HDMI_STATUS_BOOT_INIT;
+			}
+			if(boot_cvbs_status == CVBS_STATUS_NOT_INIT
+				&& dss_check_channel_boot_inited(OWL_DSS_OVL_MGR_EXTERNAL)
+				&& boot_cvbs_enable == 1)
+			{
+				boot_cvbs_status = CVBS_STATUS_BOOT_INIT;
+			}
+
+
+			
+			if(boot_hdmi_status == HDMI_STATUS_BOOT_INIT||boot_cvbs_status == CVBS_STATUS_BOOT_INIT){
+				for(i = 0 ; i < primary_used_overlay; i++)
+				{
+					struct owl_overlay *ovl = owl_dss_get_overlay(num_ovls - i - 1);
+					if (ovl->manager != NULL
+					&& ovl->manager->id != owl_dc.external_manager->id) {
+						  ovl->disable(ovl);
+				    	ovl->unset_manager(ovl);
+				    	ovl->set_manager(ovl,owl_dc.external_manager); 
+					}
+					boot_external_used_ovl[external_used_overlay++] = ovl;			
+				}
+				dss_mgr_enable(owl_dc.external_manager);
+			}	
+		}		
+	}
+	
+	return used_overlay_num;
+}
+
+static int hdmi_discard_frame = 0;
+
+static int owlfb_dc_update_overlay(struct owl_disp_info * disp_info)
+{
+	const int num_ovls = owl_dss_get_num_overlays();
+	int used_overlay = 0;
+	bool need_enable_mmu = false;
+	struct owl_overlay *used_ovl[num_ovls];
+	struct owl_overlay *boot_external_used_ovl[num_ovls];
+	int rc = 0;
+	int i = 0;
+	
+	setup_dispc_data_t *psDispcData = &disp_info->psDispcData;
+	
+	if (psDispcData == NULL){
+		printk("psDispcData  is NULL \n");
+		return -1;
+	}
+
+	used_overlay = owlfb_dc_arrange_overlay(psDispcData, used_ovl,boot_external_used_ovl);
+
+	for(i = 0 ;i < used_overlay ;i++){			
+		struct owl_overlay * ovl = used_ovl[i];	
+		__disp_layer_info_t * layer = &psDispcData->layer_info[i];	
+				
+		struct owl_overlay_info info;	
+
+		ovl->get_overlay_info(ovl, &info);
+
+		info.color_mode = layer->fb.format;
+		info.img_width = layer->fb.size.width;
+		info.img_height = layer->fb.size.height;
+		
+		info.xoff =  layer->src_win.x;
+	  	info.yoff =  layer->src_win.y;
+		info.width =  layer->src_win.width;
+		info.height =  layer->src_win.height;
+			
+		info.pos_x = layer->scn_win.x;
+		info.pos_y = layer->scn_win.y;
+		info.out_width = layer->scn_win.width;
+		info.out_height = layer->scn_win.height;	
+				
+		info.rotation =	layer->rotate;
+		if(layer->fb.buffer_id != -1){
+			info.buffer_id    =  layer->fb.buffer_id;
+			info.paddr = 0;
+			need_enable_mmu = true;
+		}else{
+			info.paddr =  layer->fb.addr[0];
+			need_enable_mmu = false;
+		}
+		info.global_alpha_en = layer->alpha_en;
+		info.global_alpha =  layer->alpha_val; 
+		info.pre_mult_alpha_en =  layer->fb.pre_multiply;  
+		  
+		ovl->set_overlay_info(ovl,&info);
+				    
+		ovl->enable(ovl);
+	}
+
+	if(boot_hdmi_status == HDMI_STATUS_BOOT_INIT||boot_cvbs_status == CVBS_STATUS_BOOT_INIT){
+		hdmi_discard_frame ++;
+		for(i = 0 ;i < used_overlay ;i++){	
+			struct owl_overlay * ovl = boot_external_used_ovl[i];	
+			__disp_layer_info_t * layer = &psDispcData->layer_info[i];	
+					
+			struct owl_overlay_info info;	
+	
+			ovl->get_overlay_info(ovl, &info);
+	
+			info.color_mode = layer->fb.format;
+			info.img_width = layer->fb.size.width;
+			info.img_height = layer->fb.size.height;
+			
+			info.xoff =  layer->src_win.x;
+		  	info.yoff =  layer->src_win.y;
+			info.width =  layer->src_win.width;
+			info.height =  layer->src_win.height;
+				
+			info.pos_x = layer->scn_win.x;
+			info.pos_y = layer->scn_win.y;
+			
+			ovl->manager->device->driver->get_resolution(
+			 ovl->manager->device, 
+			 &info.out_width, 
+			 &info.out_height);
+				
+			if(boot_hdmi_status == HDMI_STATUS_BOOT_INIT)
+			{
+				info.rotation =	boot_hdmi_rotate;
+			}
+			if(boot_cvbs_status == CVBS_STATUS_BOOT_INIT)
+			{
+				info.rotation =	boot_cvbs_rotate;
+			}
+			if(layer->fb.buffer_id != -1){
+				info.buffer_id    =  layer->fb.buffer_id;
+				info.paddr = 0;
+			}else{
+				info.paddr =  layer->fb.addr[0];
+			}
+			info.global_alpha_en = layer->alpha_en;
+			info.global_alpha =  layer->alpha_val; 
+			info.pre_mult_alpha_en =  layer->fb.pre_multiply;  
+			  
+			ovl->set_overlay_info(ovl,&info);
+			
+			if(hdmi_discard_frame < 2){
+				ovl->disable(ovl);
+				ovl->manager->apply(ovl->manager);
+				ovl->manager->wait_for_go(ovl->manager);
+			}else{
+				ovl->enable(ovl);
+			}
+		}
+		
+	}
+
+#ifdef DEBUG
+	trace_buffer_put_to_dehw(disp_info->mCallBackArg);
+#endif 
+
+	for(i = 0 ; i < 2 ; i++){
+		struct owl_overlay_manager *mgr;
+		mgr = owl_dss_get_overlay_manager(i);
+		if(need_enable_mmu && mgr->id == OWL_DSS_OVL_MGR_PRIMARY){
+			mgr->set_mmu_state(mgr,MMU_STATE_PRE_ENABLE);
+		}	
+		mgr->apply(mgr);
+	}
+
+	if(!owl_dss_is_devices_suspended())
+	{
+		for(i = 0 ; i < 2 ; i++){
+			struct owl_overlay_manager *mgr;
+			mgr = owl_dss_get_overlay_manager(i);
+			mgr->wait_for_go(mgr);	
+		}
+	}
+
+	return rc ;
+}
+
+static void owlfb_dc_perform_update(struct work_struct *work)
+{
+	struct owlfb_dc * dispc;
+	struct owl_disp_info * disp_info;
+	unsigned long flags;
+    
+	dispc = container_of(work, struct owlfb_dc, dc_work);
+	
+	if(dispc == NULL){
+		printk("dispc is null\n");
+		return ;
+	}
+	
+	while(true){
+		
+		dispc->working  = true;
+		
+		mutex_lock(&dispc->dc_lock);
+		
+		if(!list_empty(&dispc->q_list)){			
+			disp_info = list_entry(dispc->q_list.next, struct owl_disp_info, list); 
+        	list_del(&(disp_info->list));
+		}else{
+			mutex_unlock(&dispc->dc_lock);
+			dispc->working = false;	
+			return;
+		}		
+		mutex_unlock(&dispc->dc_lock);
+		
+		
+		spin_lock_irqsave(&disp_info->info_lock,flags);
+		
+		disp_info->state = STATUS_DISPINFO_ACTIVE;   
+		
+		spin_unlock_irqrestore(&disp_info->info_lock,flags);
+    	     				
+	#ifdef OWLFB_DC_DISCARD_FRAME
+		if (atomic_read(&queue_cnt) < OWL_DCQ_DEPTH - 1) {
+			owlfb_dc_update_overlay(disp_info);		
+		} else {
+			printk(KERN_INFO "%s: cnt %d, discard a frame!\n", 
+				__func__, atomic_read(&queue_cnt));
+		}
+	#else
+		owlfb_dc_update_overlay(disp_info);		
+	#endif
+
+		owlfb_dc_mark_buffer_done(dispc,disp_info->index);	
+		
+	}
+	
+	dispc->working = false;	
+	return;
+}
+
+void check_boot_hdmi_rotate_config(void)
+{
+	struct device_node *np = NULL;
+	struct device_node *cp = NULL;
+	
+	np = of_find_compatible_node(NULL, NULL, "actions,atm7059a-hdmi");
+	cp = of_find_compatible_node(NULL, NULL, "actions,atm7059a-cvbs");
+	
+	printk("np %p \n",np);
+	if(np != NULL){
+		if (of_property_read_u32(np, "bootrotate", &boot_hdmi_rotate)){
+			boot_hdmi_rotate = 0;
+		}
+		if (of_property_read_u32(np, "bootable", &boot_hdmi_enable)){
+			boot_hdmi_enable = 0;
+		}	
+		printk("boot_hdmi_rotate %d \n",boot_hdmi_rotate);	
+	}
+	
+	if(cp != NULL){
+		
+		if (of_property_read_u32(cp, "bootable", &boot_cvbs_enable)){
+				printk("of_property_read_u32 is error\n");
+			boot_cvbs_enable = 0;
+		}	
+		if (of_property_read_u32(cp, "bootrotate", &boot_cvbs_rotate)){
+				printk("of_property_read bootrotate is error\n");
+			boot_cvbs_rotate = 0;
+		}	
+		printk("boot_cvbs_enable %d \n",boot_cvbs_enable);	
+	}
+	
+	boot_cvbs_rotate =0;
+	
+	printk("boot_hdmi_rotate %d boot_cvbs_rotate=%d \n",boot_hdmi_rotate,boot_cvbs_rotate);
+	return;
+}
+
+int owlfb_dc_init(struct owlfb_device * fbdev)
+{
+
+	int rc = 0;	
+	int i = 0;
+	
+	my_fbdev = fbdev;
+	
+	owl_dc.dev = fbdev->dev;
+	
+	owl_dc.primary_manager = owl_dss_get_overlay_manager(OWL_DSS_OVL_MGR_PRIMARY);
+	owl_dc.external_manager = owl_dss_get_overlay_manager(OWL_DSS_OVL_MGR_EXTERNAL);
+	
+	/*we always used path1 connected to primary display */
+	owl_dc.primary_manager->de_path_id = OWL_DSS_PATH1_ID;	
+	owl_dc.external_manager->de_path_id = OWL_DSS_PATH2_ID;	
+	 
+	mutex_init(&owl_dc.dc_lock);
+	
+	INIT_LIST_HEAD(&owl_dc.q_list);	
+	
+	for(i = 0; i < OWL_DCQ_DEPTH; i++){
+		
+		struct owl_disp_info * disp_info  = &owl_dc.dc_queue[i];
+		
+		spin_lock_init(&disp_info->info_lock);
+		
+		disp_info->state = STATUS_DISPINFO_NEEDS_INIT;
+		
+		disp_info->index = i;
+	}
+	
+	owl_dc.working  = false;
+	
+		
+	owl_dc.dc_workqueue = create_singlethread_workqueue("owlfb");
+	
+	if (owl_dc.dc_workqueue == NULL){
+		rc = -ENOMEM;
+		goto failed;
+	}
+	
+#ifdef DEBUG	
+	//owlfb_dc_create_debug_sysfs(fbdev);
+#endif
+
+	INIT_WORK(&(owl_dc.dc_work), owlfb_dc_perform_update);	
+	
+	check_boot_hdmi_rotate_config();
+
+failed:	
+	return rc;
+}
+
+int owlfb_dc_uninit(struct owlfb_device * fbdev)
+{
+	flush_workqueue(owl_dc.dc_workqueue);
+	
+	destroy_workqueue(owl_dc.dc_workqueue);
+	
+	owl_dc.dc_workqueue = NULL;
+	
+	mutex_destroy(&owl_dc.dc_lock);
+	
+	return 0;
+}
+
+int dispc_gralloc_queue(setup_dispc_data_t *psDispcData, int ui32DispcDataLength, void (*cb_fn)(void *, int),void *cb_arg)
+{
+	
+	int rc = 0;
+	
+#ifdef OWLFB_DC_DISCARD_FRAME
+	atomic_inc(&queue_cnt);
+#endif
+
+#ifdef DEBUG
+	trace_buffer_put_to_queue(cb_arg);
+#endif
+	rc = owlfb_dc_queue_buffer(&owl_dc, psDispcData, cb_fn, cb_arg);
+		
+	if (rc)
+		return rc;
+
+	if(owl_dc.dc_workqueue != NULL){
+		queue_work(owl_dc.dc_workqueue, &(owl_dc.dc_work));
+	}	
+	return rc;
+}
+
+EXPORT_SYMBOL(dispc_gralloc_queue);
diff --git a/drivers/video/fbdev/owl/fb/owlfb-ioctl.c b/drivers/video/fbdev/owl/fb/owlfb-ioctl.c
new file mode 100755
index 0000000..7bf8913
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb-ioctl.c
@@ -0,0 +1,887 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-ioctl.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/fb.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/export.h>
+#include <linux/delay.h>
+
+#include <video/owldss.h>
+#include <video/owlfb.h>
+
+#include "owlfb.h"
+extern atomic_t want_close_external_devices;
+
+static int owlfb_request_overlay(struct fb_info *fbi, struct owlfb_overlay_args * request)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	int ovl_id = -1;
+	int i;	
+	
+	if(request->overlay_type == OWLFB_OVERLAY_VIDEO){
+		for (i = 1; i < ofbi->num_overlays; ++i) {
+			if((ofbi->used_overlay_mask & (1 << i)) == 0){
+				ovl_id = i;
+				ofbi->used_overlay_mask |= (1 << i);
+				break;
+			}		
+		}		
+		if(OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL <= ofbi->overlay_free_mem_size){
+			request->overlay_mem_base = ofbi->overlay_mem_base + OWLFB_MAX_CURSOR_MEM_RESERVE + ofbi->overlay_free_mem_off;
+			request->overlay_mem_size = OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL;
+			ofbi->overlay_free_mem_off += OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL;
+			ofbi->overlay_free_mem_size -= OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL;
+			request->overlay_id = ovl_id;	
+		}
+		else
+		{
+			ovl_id = -1;
+		}
+	}else if(request->overlay_type == OWLFB_OVERLAY_CURSOR){
+		request->overlay_id = OWLFB_CURSOR_OVL_ID;
+		ovl_id = OWLFB_CURSOR_OVL_ID;
+		ofbi->used_overlay_mask |= (1 << 3);
+		request->overlay_mem_base = ofbi->overlay_mem_base + ofbi->overlay_free_mem_off;
+		request->overlay_mem_size = OWLFB_MAX_CURSOR_MEM_RESERVE;
+	}
+	
+	DBG("owlfb_request_overlay ovl_id %d request->overlay_mem_base 0x%x,request->overlay_mem_size 0x%x\n",ovl_id,request->overlay_mem_base,request->overlay_mem_size);
+	return ovl_id;
+}
+
+static int owlfb_release_overlay(struct fb_info *fbi, int ovl_id)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	DBG("owlfb_release_overlay ovl_id %d \n",ovl_id);
+	if((ofbi->used_overlay_mask & (1 << ovl_id)) != 0)
+	{
+		ofbi->used_overlay_mask &= (~(1 << ovl_id));
+	}
+	return 0;
+}
+
+static int owlfb_set_overlay_enable(struct fb_info *fbi,int ovl_id ,bool enable)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owl_overlay *ovl = NULL;
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	int rc = -1;
+	
+	if(ovl_id == OWLFB_CURSOR_OVL_ID)
+	{
+		struct owl_cursor_info cursor;
+		
+		ofbi->manager->get_cursor_info(ofbi->manager,&cursor);
+		
+		cursor.enable = enable;
+		
+		ofbi->manager->set_cursor_info(ofbi->manager,&cursor);
+		
+		ofbi->manager->apply(ofbi->manager);
+		
+		if(fbdev->mirror_fb_id){
+			struct fb_info * link_fbi = fbdev->fbs[fbdev->mirror_fb_id];
+			struct owlfb_info *link_ofbi = FB2OFB(link_fbi);
+			link_ofbi->manager->get_cursor_info(link_ofbi->manager,&cursor);
+			cursor.enable = enable;		
+			link_ofbi->manager->set_cursor_info(link_ofbi->manager,&cursor);
+			link_ofbi->manager->apply(link_ofbi->manager);
+		}		
+	}else{
+		if(ovl_id > ofbi->num_overlays){
+			return -1;
+		}
+		
+		ovl = ofbi->overlays[ovl_id];
+		DBG("owlfb_set_overlay_enable ovl_id %d enable %d \n",ovl_id,enable);
+		if(enable){
+			if(!ovl->is_enabled(ovl)){
+				ovl->enable(ovl);
+				ovl->manager->apply(ovl->manager);
+				//ovl->manager->wait_for_go(ovl->manager);
+				rc = 0;
+			}
+		}else{
+			if(ovl->is_enabled(ovl)){
+				ovl->disable(ovl);
+				ovl->manager->apply(ovl->manager);
+				//ovl->manager->wait_for_go(ovl->manager);
+				rc = 0;
+			}
+		}
+	}	
+	return 0;
+}
+
+static int owlfb_get_overlay_info(struct fb_info *fbi,int ovl_id, struct owlfb_overlay_info * userinfo)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owl_overlay *ovl = NULL;
+	struct owl_overlay_info info;
+	
+	if(ovl_id == OWLFB_CURSOR_OVL_ID)
+	{
+		struct owl_cursor_info cursor;
+		
+		ofbi->manager->get_cursor_info(ofbi->manager,&cursor);
+
+		userinfo->pos_x = cursor.pos_x;
+		userinfo->pos_y = cursor.pos_y;
+		
+	}else{	
+		if(ovl_id > ofbi->num_overlays){
+			return -1;
+		}
+
+		ovl = ofbi->overlays[ovl_id];
+			
+		ovl->get_overlay_info(ovl, &info);
+		
+		userinfo->color_mode = info.color_mode;
+		userinfo->img_width = info.img_width;
+		userinfo->img_height = info.img_height;
+		
+		userinfo->xoff = info.xoff;
+		userinfo->yoff = info.yoff;
+		userinfo->width = info.width;
+		userinfo->height = info.height;
+			
+		userinfo->pos_x = info.pos_x;
+		userinfo->pos_y = info.pos_y;
+		userinfo->out_width = info.out_width;
+		userinfo->out_height = info.out_height;	
+					
+		userinfo->rotation = info.rotation;	
+		
+		userinfo->global_alpha_en = info.global_alpha_en;
+		userinfo->global_alpha = info.global_alpha; 	
+		userinfo->pre_mult_alpha_en = info.pre_mult_alpha_en;
+		DBG("owlfb_get_overlay_info  ovl_id %d info: color_mode 0x%x img_width 0x%x info.img_height 0x%x \n",ovl_id,info.color_mode,info.img_width,info.img_height);	
+		DBG(" info: xoff 0x%x yoff 0x%x width 0x%x height 0x%x \n",info.xoff,info.yoff,info.width,info.height);	
+		DBG(" info: pos_x 0x%x pos_y 0x%x out_width 0x%x out_height 0x%x \n",info.pos_x,info.pos_y,info.out_width,info.out_height);	
+		DBG(" info: global_alpha_en 0x%x global_alpha 0x%x pre_mult_alpha_en 0x%x \n",info.global_alpha_en,info.global_alpha,info.pre_mult_alpha_en);	
+	}
+	return 0;
+}
+
+static int owlfb_set_overlay_info(struct fb_info *fbi,int ovl_id , struct owlfb_overlay_info * userinfo)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owl_overlay *ovl = NULL;
+	struct owl_overlay_info info;
+	struct owl_dss_device * src_dssdev = ofbi->manager->device;
+	u16 src_out_w, src_out_h;
+	
+	if(ovl_id == OWLFB_CURSOR_OVL_ID)
+	{
+		struct owl_cursor_info cursor;
+		
+		ofbi->manager->get_cursor_info(ofbi->manager,&cursor);
+	
+		cursor.pos_x  = userinfo->pos_x;
+		cursor.pos_y  = userinfo->pos_y;
+		
+		if(src_dssdev != NULL && src_dssdev->driver != NULL){
+			u16 overscan_w, overscan_h;
+			src_dssdev->driver->get_resolution(src_dssdev, &src_out_w, &src_out_h);
+			if(src_dssdev->driver->get_over_scan)
+			{
+				src_dssdev->driver->get_over_scan(src_dssdev,&overscan_w,&overscan_h);
+				if(overscan_w != 0 || overscan_h != 0){
+					overscan_w = src_out_w - overscan_w * 2;
+					overscan_h = src_out_h - overscan_h * 2;
+					cursor.pos_x = src_out_w / 2 - overscan_w * (src_out_w / 2 - cursor.pos_x) / src_out_w ;
+					cursor.pos_y = src_out_h / 2 - overscan_h * (src_out_h / 2 - cursor.pos_y) / src_out_h ;
+					
+					if(cursor.pos_x > (src_out_w + overscan_w)/ 2){
+						cursor.pos_x = (src_out_w + overscan_w)/ 2;
+					}					
+					if(cursor.pos_y > (src_out_h + overscan_h)/ 2){
+						cursor.pos_y =  (src_out_h + overscan_h)/ 2;
+					}
+				}				
+			}
+		}
+		
+		if(cursor.pos_x > src_out_w - 64){
+			cursor.pos_x = src_out_w - 64;
+		}
+		
+		if(cursor.pos_y > src_out_h - 64){
+			cursor.pos_y = src_out_h - 64;
+		}
+		
+		if(src_dssdev->type == OWL_DISPLAY_TYPE_CVBS)
+		{
+			cursor.pos_y = (cursor.pos_y & (~0x01));					
+		}
+		
+		cursor.paddr = 	(void *)(userinfo->mem_off + ofbi->region->paddr);
+		cursor.stride = userinfo->img_width * 4 / 8;
+		
+		DBG("owlfb_set_overlay_info OWLFB_CURSOR_OVL_ID cursor.pos_x %d cursor.pos_y %d cursor.paddr 0x%x cursor.stride %d \n",cursor.pos_x,cursor.pos_y,cursor.paddr,cursor.stride);
+		
+		ofbi->manager->set_cursor_info(ofbi->manager,&cursor);
+		
+		ofbi->manager->apply(ofbi->manager);
+		
+		if(fbdev->mirror_fb_id){
+			u16 link_out_w, link_out_h;
+			u16 link_overscan_w, link_overscan_h;
+			struct fb_info * link_fbi = fbdev->fbs[fbdev->mirror_fb_id];
+			struct owlfb_info *link_ofbi = FB2OFB(link_fbi);
+			struct owl_cursor_info link_cursor;			
+			struct owl_dss_device * link_dssdev = link_ofbi->manager->device;
+			
+			link_ofbi->manager->get_cursor_info(link_ofbi->manager,&link_cursor);
+			
+			if(link_dssdev != NULL && link_dssdev->driver != NULL){				
+				link_dssdev->driver->get_resolution(link_dssdev, &link_out_w, &link_out_h);
+				if(link_dssdev->driver->get_over_scan != NULL){
+					link_dssdev->driver->get_over_scan(link_dssdev,&link_overscan_w,&link_overscan_h);
+					link_overscan_w = link_out_w - link_overscan_w * 2;
+					link_overscan_h = link_out_h - link_overscan_h * 2;
+				}else{
+					link_overscan_w = link_out_w;
+					link_overscan_h = link_out_h;
+				}
+			}	
+			
+			link_cursor.pos_x = userinfo->pos_x	* link_out_w / src_out_w ;			
+			link_cursor.pos_y = userinfo->pos_y * link_out_h / src_out_h ;	
+			
+			link_cursor.pos_x = link_out_w / 2 - link_overscan_w * (link_out_w / 2 - link_cursor.pos_x) / link_out_w ;
+			link_cursor.pos_y = link_out_h / 2 - link_overscan_h * (link_out_h / 2 - link_cursor.pos_y) / link_out_h ;
+			
+			
+			if(link_cursor.pos_x > (link_out_w + link_overscan_w) / 2 ){
+				link_cursor.pos_x = (link_out_w + link_overscan_w) / 2;				
+			}
+			
+			if(link_cursor.pos_y > (link_out_h + link_overscan_h) / 2 ){
+				link_cursor.pos_y = (link_out_h + link_overscan_h) / 2;
+			}
+			
+			
+			if(link_cursor.pos_x > link_out_w - 64 ){
+				link_cursor.pos_x = link_out_w - 64;
+			}					
+			if(link_cursor.pos_y > link_out_h - 64){
+				link_cursor.pos_y = link_out_h - 64;
+			}	
+			
+			if(link_dssdev->type == OWL_DISPLAY_TYPE_CVBS)
+			{
+				link_cursor.pos_y = (link_cursor.pos_y & (~0x01));					
+			}			
+			printk("link_cursor.pos_x %d  link_cursor.pos_y  %d\n",link_cursor.pos_x,link_cursor.pos_y);
+			link_cursor.paddr = cursor.paddr;
+			link_cursor.stride =  cursor.stride;
+			link_cursor.enable =  cursor.enable;		
+			link_ofbi->manager->set_cursor_info(link_ofbi->manager,&link_cursor);
+			link_ofbi->manager->apply(link_ofbi->manager);
+		}		
+	}else{
+		if(ovl_id > ofbi->num_overlays){
+			return -1;
+		}	
+		
+		ovl = ofbi->overlays[ovl_id];
+			
+		ovl->get_overlay_info(ovl, &info);
+		
+		info.paddr = (unsigned long)(userinfo->mem_off) + (unsigned long)(ofbi->region->paddr);
+		
+		info.color_mode = userinfo->color_mode;
+		info.img_width = userinfo->img_width;
+		info.img_height = userinfo->img_height;
+		
+		info.xoff =  userinfo->xoff;
+		info.yoff =  userinfo->yoff;
+		info.width =  userinfo->width;
+		info.height =  userinfo->height;
+			
+		info.pos_x = userinfo->pos_x;
+		info.pos_y = userinfo->pos_y;
+		info.out_width = userinfo->out_width;
+		info.out_height = userinfo->out_height;	
+					
+		info.rotation =	userinfo->rotation;	
+		
+		info.global_alpha_en = userinfo->global_alpha_en;
+		info.global_alpha =  userinfo->global_alpha; 
+		info.pre_mult_alpha_en =  userinfo->pre_mult_alpha_en;
+		
+		DBG(" owlfb_set_overlay_info ovl_id %d info: color_mode 0x%x img_width 0x%x info.img_height 0x%x \n",ovl_id,info.color_mode,info.img_width,info.img_height);	
+		DBG(" info: xoff 0x%x yoff 0x%x width 0x%x height 0x%x \n",info.xoff,info.yoff,info.width,info.height);	
+		DBG(" info: pos_x 0x%x pos_y 0x%x out_width 0x%x out_height 0x%x \n",info.pos_x,info.pos_y,info.out_width,info.out_height);	
+		DBG(" info: global_alpha_en 0x%x global_alpha 0x%x pre_mult_alpha_en 0x%x \n",info.global_alpha_en,info.global_alpha,info.pre_mult_alpha_en);	
+		
+		ovl->set_overlay_info(ovl, &info);
+		
+		if(!ovl->is_enabled(ovl)){
+			ovl->enable(ovl);
+		}		
+		ovl->manager->apply(ovl->manager);		
+		//ovl->manager->wait_for_go(ovl->manager);		
+	}	
+	return 0;
+}
+
+static int owlfb_wait_for_go(struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	int r = 0;
+	int i;
+
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		struct owl_overlay *ovl = ofbi->overlays[i];
+		r = ovl->wait_for_go(ovl);
+		if (r)
+			break;
+	}
+
+	return r;
+}
+
+extern int owl_de_get_ictype(void);
+int owlfb_get_effect_parameter(struct owlfb_disp_device * disp_info)
+{	
+	struct owl_dss_device * device = owl_dss_find_device_by_type(get_current_display_type()); 
+	struct display_private_info *new_private_info = (struct display_private_info *)&(disp_info->mPrivateInfo[0]);	
+	DBG("get_info~~\n");	
+	if(device 
+		&& device->driver
+		&& device->driver->get_effect_parameter){
+			disp_info->mIcType = owl_de_get_ictype();	
+			new_private_info->LCD_TYPE = device->type;			
+			new_private_info->LCD_LIGHTENESS = device->driver->get_effect_parameter(device ,OWL_DSS_VIDEO_LIGHTNESS);
+			new_private_info->LCD_SATURATION = device->driver->get_effect_parameter(device ,OWL_DSS_VIDEO_SATURATION);
+			new_private_info->LCD_CONSTRAST = device->driver->get_effect_parameter(device ,OWL_DSS_VIDEO_CONSTRAST);
+	}
+	return 0;
+}
+
+int owlfb_set_effect_parameter(struct owlfb_disp_device * disp_info)
+{	
+	struct owl_dss_device * device = owl_dss_find_device_by_type(get_current_display_type()); 	
+	struct display_private_info *new_private_info = (struct display_private_info *)&(disp_info->mPrivateInfo[0]);	
+	int 	lightness = new_private_info->LCD_LIGHTENESS;
+	int 	saturation = new_private_info->LCD_SATURATION;
+	int 	contrast = new_private_info->LCD_CONSTRAST;
+	DBG("set_info~~\n");
+	if(device 
+		&& device->driver
+		&& device->driver->set_effect_parameter){
+		switch(disp_info->mCmdMode){
+			case SET_LIGHTENESS:
+				  device->driver->set_effect_parameter(device ,OWL_DSS_VIDEO_LIGHTNESS, lightness);
+				  printk("set_info~~ new_private_info->LCD_LIGHTENESS  %d\n", new_private_info->LCD_LIGHTENESS);
+				  break;	
+			case SET_SATURATION:
+				  device->driver->set_effect_parameter(device ,OWL_DSS_VIDEO_SATURATION, saturation);
+				  printk("set_info~~ new_private_info->LCD_SATURATION  %d\n", new_private_info->LCD_SATURATION);
+				  break;	
+			case SET_CONSTRAST:
+				  device->driver->set_effect_parameter(device ,OWL_DSS_VIDEO_CONSTRAST, contrast);
+				  printk("set_info~~ new_private_info->LCD_CONSTRAST  %d\n", new_private_info->LCD_CONSTRAST);
+				  break;	
+			case SET_DEFAULT:
+				  device->driver->set_effect_parameter(device ,OWL_DSS_DEF_EFFECT, 0);
+				  printk("set_info~~ new_private_info->LCD_CONSTRAST  %d\n", new_private_info->LCD_CONSTRAST);
+				  break;			
+		}
+	}
+	return 0;
+}
+int owlfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owl_dss_device *display = fb2display(fbi);
+
+	union {
+		struct owlfb_overlay_args overlay_args;
+		struct owlfb_sync_info sync_info;
+		struct owlfb_disp_histogram_info histogram_info;
+		struct owl_gamma_info gamma_info;
+		struct owlfb_display_info display_info;
+		struct owlfb_hdmi_vid_info hdmi_vid;
+		u32				crt;
+	} p;
+
+	int r = 0;
+
+	switch (cmd) {
+	/*this for linux overlay functions */
+	case OWLFB_SYNC_GFX:
+		DBG("ioctl SYNC_GFX\n");
+		break;
+	case OWLFB_OVERLAY_REQUEST:{		
+		DBG("ioctl OWLFB_OVERLAY_REQUEST \n");
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args))){
+			r = -EFAULT;
+			break;
+		}
+				
+		owlfb_request_overlay(fbi,&p.overlay_args);
+		
+		if(p.overlay_args.overlay_id >= 0){
+			if (copy_to_user((void __user *)arg, &p.overlay_args,sizeof(struct owlfb_overlay_args))){
+				 return -EFAULT;
+			}
+		}
+		break;
+	}		
+	case OWLFB_OVERLAY_RELEASE:{
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args)) ){
+			r = -EFAULT;
+			break;
+		}
+		r = owlfb_release_overlay(fbi,p.overlay_args.overlay_id);
+		DBG("ioctl OWLFB_OVERLAY_RELEASE \n"); 
+		break;
+	}
+	case OWLFB_OVERLAY_ENABLE:{
+		DBG("ioctl OWLFB_OVERLAY_ENABLE \n"); 
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args))) {
+			r = -EFAULT;
+			break;
+		}
+		r = owlfb_set_overlay_enable(fbi,p.overlay_args.overlay_id,true);
+		break;
+	}
+	case OWLFB_OVERLAY_DISABLE:{
+		DBG("ioctl OWLFB_OVERLAY_DISABLE \n"); 
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args))) {
+			r = -EFAULT;
+			break;
+		}
+		r = owlfb_set_overlay_enable(fbi,p.overlay_args.overlay_id,false);
+		break;
+	}
+	case OWLFB_OVERLAY_GETINFO:{
+		struct owlfb_overlay_info   overlay_info;
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args))) {
+			r = -EFAULT;
+			break;
+		}
+		
+		DBG("ioctl OWLFB_OVERLAY_GETINFO \n");
+		
+		if(owlfb_get_overlay_info(fbi,p.overlay_args.overlay_id,&overlay_info) >= 0)
+		{
+			if(copy_to_user((void __user *)p.overlay_args.uintptr_overly_info,(void *)&overlay_info,sizeof(struct owlfb_overlay_info))){
+	            return -EFAULT;
+	        }
+		} 
+		break;	
+	}
+	case OWLFB_OVERLAY_SETINFO:{
+		struct owlfb_overlay_info   overlay_info;
+		DBG("ioctl OWLFB_OVERLAY_SETINFO \n"); 
+		if (copy_from_user(&p.overlay_args, (void __user *)arg, sizeof(p.overlay_args))) {
+			r = -EFAULT;
+			break;
+		}
+		if (copy_from_user(&overlay_info, (void __user *)p.overlay_args.uintptr_overly_info, sizeof(struct owlfb_overlay_info))) {
+			r = -EFAULT;
+			break;
+		}
+		r = owlfb_set_overlay_info(fbi,p.overlay_args.overlay_id,&overlay_info);		
+		break;
+	}
+	case OWLFB_WAITFORVSYNC: {
+		long long i64TimeStamp;
+		DBG("ioctl WAITFORVSYNC\n");
+		if (copy_from_user(&i64TimeStamp, (void __user *)arg, sizeof(i64TimeStamp))){
+			r = -EFAULT;
+			break;
+		}
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+		unlock_fb_info(fbi);
+		r = display->manager->wait_for_vsync(display->manager,i64TimeStamp);
+		lock_fb_info(fbi);		
+		break;
+	}
+	case OWLFB_WAITFORGO:
+		DBG("ioctl WAITFORGO\n");
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+
+		r = owlfb_wait_for_go(fbi);
+		break;
+			
+	case OWLFB_GET_MAIN_DISPLAY_RES: {
+		if (display == NULL) {
+			r = -ENODEV;
+			break;
+		}
+				
+		if(display->driver->get_resolution){
+			display->driver->get_resolution(display, &p.display_info.xres, &p.display_info.yres);
+		}else{
+			p.display_info.xres = fbdev->xres;
+			p.display_info.yres = fbdev->yres;
+		}
+		
+		p.display_info.virtual_xres = fbdev->xres;
+		p.display_info.virtual_yres = fbdev->yres;		
+		p.display_info.refresh_rate = fbdev->refresh;
+		
+		p.display_info.disp_type = display->type;
+		
+		printk("ioctl GET_DISPLAY_INFO display %p %s (%d x %d @ %d MHZ)\n",display, display->name,p.display_info.xres,p.display_info.yres,p.display_info.refresh_rate);
+		
+		if (display->driver->get_dimensions) {
+			u32 w, h;
+			display->driver->get_dimensions(display, &w, &h);
+			p.display_info.width = w;
+			p.display_info.height = h;
+		} else {
+			p.display_info.width = 0;
+			p.display_info.height = 0;
+		}
+
+		if (copy_to_user((void __user *)arg, &p.display_info,
+					sizeof(p.display_info)))
+			r = -EFAULT;
+		
+		break;
+	}
+	
+	case OWLFB_GET_HISTOGRAM_INFO: {
+		DBG("ioctl OWLFB_GET_HISTOGRAM_INFO\n");
+		owl_de_get_histogram_info((__u32 *)&p.histogram_info.hist,
+                                    (__u32 *)&p.histogram_info.totaly);
+		if (copy_to_user((void __user *)arg, &p.histogram_info,
+					sizeof(p.histogram_info)))
+			r = -EFAULT;
+		break;
+	}
+	case OWLFB_SET_GAMMA_INFO: {
+		DBG("ioctl OWLFB_SET_GAMMA_INFO, &p.gamma_info %p\n",
+			&p.gamma_info);
+		if (copy_from_user(&p.gamma_info, (void __user *)arg,
+					sizeof(p.gamma_info))) {
+			r = -EFAULT;
+			break;
+		}
+
+		dss_mgr_set_gamma_table(OWL_DSS_PATH1_ID, &p.gamma_info);
+		break;
+	}
+	case OWLFB_GET_GAMMA_INFO: {
+		DBG("ioctl OWLFB_SET_GAMMA_INFO, &p.gamma_info %p\n",&p.gamma_info);				
+		dss_mgr_get_gamma_table(OWL_DSS_PATH1_ID, &p.gamma_info);
+
+		if (copy_to_user((void __user *)arg, &p.gamma_info,
+			sizeof(p.gamma_info))) {
+			r = -EFAULT;
+		}
+		break;
+	}
+	case OWLFB_VSYNC_EVENT_EN:{
+		if (copy_from_user(&p.sync_info, (void __user *)arg, sizeof(p.sync_info))) {
+			r = -EFAULT;
+			break;
+		}
+		DBG("ioctl OWLFB_VSYNC_EVENT_EN display %d  enable %d\n",p.sync_info.disp_id,p.sync_info.enabled);
+		if (!display) {
+			r = -EINVAL;
+			break;
+		}
+		
+		r = display->manager->enable_hw_vsync(display->manager,p.sync_info.enabled,fbdev->dev);
+		
+		break;
+	}
+	case OWLFB_HDMI_SUPPORT_MODE:{
+		int support_vid[9];
+		int i = 0;
+		int k = 0;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver device %p \n",device);
+			r = -EFAULT;
+			break;
+		}
+		
+		DBG("ioctl OWLFB_HDMI_SUPPORT_MODE  vid %d mode %d \n",p.hdmi_vid.vid,p.hdmi_vid.mode);	
+		memset(support_vid, 0, sizeof(support_vid));
+		
+		if(device->driver->get_vid_cap){
+			
+			k = device->driver->get_vid_cap(device, support_vid);	
+		}
+		
+		for(i = 0 ; i < k; i++){
+			if(p.hdmi_vid.vid == support_vid[i]){		
+				return 1;
+			}
+		}
+		r = 0;		
+		break;
+	}	
+	case OWLFB_HDMI_GET_CABLE_STATUS:{
+		int i = 0;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver device %p \n",device);
+			r = -EFAULT;
+			break;
+		}
+				
+		if(device->driver->get_cable_status){
+			i = device->driver->get_cable_status(device);	
+		}
+		
+		if (copy_to_user((void __user *)arg, &i, sizeof(int))){
+			r = -EFAULT;
+		}
+		break;
+	}
+	case OWLFB_HDMI_SET_MODE:{		
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver device %p \n",device);
+			r = -EFAULT;
+			break;
+		}
+
+		if (copy_from_user(&p.hdmi_vid, (void __user *)arg, sizeof(p.hdmi_vid))) {
+			r = -EFAULT;
+			break;
+		}
+		printk("ioctl OWLFB_HDMI_SET_MODE vid %d \n",p.hdmi_vid.vid);
+				
+		if(device->driver->set_vid){
+			device->driver->set_vid(device,p.hdmi_vid.vid);	
+		}
+		break;
+	}	
+	case OWLFB_HDMI_ON:{
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver device %p \n",device);
+			r = -EFAULT;
+			break;
+		}
+		DBG("ioctl OWLFB_HDMI_ON\n");
+		if(device->driver->enable){
+			device->driver->enable(device);
+		}
+		atomic_set(&want_close_external_devices,false);
+		unlock_fb_info(fbi);
+		msleep(500);
+		lock_fb_info(fbi);
+		break;
+	}	
+	case OWLFB_HDMI_OFF:{
+		DBG("ioctl OWLFB_HDMI_OFF\n");
+		atomic_set(&want_close_external_devices,true);
+		break;
+	}
+	case OWLFB_CVBS_ON:{
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_CVBS);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver device %p \n",device);
+			r = -EFAULT;
+			break;
+		}
+		printk("ioctl OWLFB_CVBS_ON\n");
+		if(device->driver->enable){
+			device->driver->enable(device);
+		}
+		atomic_set(&want_close_external_devices,false);
+		unlock_fb_info(fbi);
+		msleep(500);
+		lock_fb_info(fbi);
+		break;
+	}	
+	case OWLFB_CVBS_OFF:{
+		printk("ioctl OWLFB_CVBS_OFF\n");
+		atomic_set(&want_close_external_devices,true);
+		break;
+	}
+	
+	case OWLFB_HDMI_DISABLE:{
+		int enable = 0;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver \n");
+			r = -EFAULT;
+			break;
+		}
+		
+		DBG("ioctl OWLFB_HDMI_DISABLE\n");
+		if (copy_from_user(&enable, (void __user *)arg, sizeof(int))) {
+			r = -EFAULT;
+			break;
+		}
+		if(enable){
+			if(device->driver->enable_hpd){
+				device->driver->enable_hpd(device, 1);
+			}			
+		}else{
+			if(device->driver->enable_hpd){
+				device->driver->enable_hpd(device, 0);
+			}		
+		}
+		break;
+	}
+	case OWLFB_HDMI_GET_VID:{
+		int vid = -1;		
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_HDMI);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver \n");
+			r = -EFAULT;
+			break;
+		}
+		
+		if(device->driver->get_vid){
+			device->driver->get_vid(device, (int *)&vid);	
+		}		
+		printk("OWLFB_HDMI_GET_VID vid %d ",vid);
+		if (copy_to_user((void __user *)arg, &vid, sizeof(int))){
+			r = -EFAULT;
+		}
+		break;
+	}	
+	/**********************CVBS***************************/
+	case OWLFB_CVBS_ENABLE:{
+		int enable = -1;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_CVBS);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver\n");
+			r = -EFAULT;
+			break;
+		}
+		
+		if (copy_from_user(&enable, (void __user *)arg, sizeof(int))){
+			r = -EFAULT;
+			break;
+		}
+	
+		if(enable){
+			if(device->driver->enable_hpd){
+				device->driver->enable_hpd(device, 1);
+			}			
+		}else{
+			if(device->driver->enable_hpd){
+				device->driver->enable_hpd(device, 0);
+			}		
+		}
+		break;
+	}
+
+	case OWLFB_CVBS_GET_VID:{
+		int vid = -1;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_CVBS);
+		DBG("enter OWLFB_CVBS_GET_VID\n");
+		
+		if(device && device->driver && device->driver->get_vid){
+			device->driver->get_vid(device, (int *)&vid);	
+		}
+		
+		if (copy_to_user((void __user *)arg, &vid, sizeof(int))){
+			r = -EFAULT;
+		}
+		break;
+	}	
+	
+	case OWLFB_CVBS_SET_VID:{
+		int vid = -1;
+		struct owl_dss_device * device = owl_dss_find_device_by_type(OWL_DISPLAY_TYPE_CVBS);
+		
+		if(!device || !device->driver){
+			dev_err(fbdev->dev, "device is NULL or no driver\n");
+			r = -EFAULT;
+			break;
+		}
+
+		if (copy_from_user(&vid, (void __user *)arg, sizeof(int))){			
+			r = -EFAULT;
+			break;
+		}	
+		DBG("OWLFB_CVBS_SET_VID  vid %d \n",vid);
+		
+		if(device->driver->set_vid){
+			device->driver->set_vid(device, vid);	
+		}
+		break;
+	}	
+		
+	case OWLFB_LAYER_REQUEST:{
+		DBG("ioctl OWLFB_LAYER_REQUEST\n");
+		break;
+	}		
+	case OWLFB_GET_DISPLAY_INFO:{
+	    	struct owlfb_disp_device info;
+	    	if(copy_from_user(&info,(void *)arg,sizeof(struct owlfb_disp_device))){
+	             return -EFAULT;
+	        }
+	        owlfb_get_effect_parameter(&info);
+	        if(copy_to_user((void *)arg,(void *)&info,sizeof(struct owlfb_disp_device))){
+	            return -EFAULT;
+	        }
+    	    
+		break;
+	}	
+	case OWLFB_SET_DISPLAY_INFO:{
+		struct owlfb_disp_device info;
+		if(copy_from_user(&info,(void *)arg,sizeof(struct owlfb_disp_device))){
+			return -EFAULT;
+		}
+		owlfb_set_effect_parameter(&info);
+		break;	
+	}
+	default:
+		dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
+		r = -EINVAL;
+	}
+
+	if (r < 0)
+		DBG("ioctl failed: %d\n", r);
+
+	return r;
+}
+
+
diff --git a/drivers/video/fbdev/owl/fb/owlfb-main.c b/drivers/video/fbdev/owl/fb/owlfb-main.c
new file mode 100755
index 0000000..b90b417
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb-main.c
@@ -0,0 +1,2118 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-main.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/fb.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <mach/dss_user-owl.h>
+#include <linux/of_device.h>
+#include <video/owldss.h>
+#include <video/owlfb.h>
+#include <mach/bootdev.h>
+#include "owlfb.h"
+
+#define MODULE_NAME     "owlfb"
+
+#define OWLFB_PLANE_XRES_MIN		8
+#define OWLFB_PLANE_YRES_MIN		8
+
+#ifdef DEBUG
+bool owlfb_debug = true;
+module_param_named(debug, owlfb_debug, bool, 0644);
+static bool owlfb_test_pattern = true;
+module_param_named(test, owlfb_test_pattern, bool, 0644);
+#endif
+
+static int owlfb_fb_init(struct owlfb_device *fbdev, struct fb_info *fbi);
+static int owlfb_get_recommended_bpp(struct owlfb_device *fbdev,
+		struct owl_dss_device *dssdev);
+
+#ifdef DEBUG
+static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	void __iomem *addr = fbi->screen_base;
+	const unsigned bytespp = var->bits_per_pixel >> 3;
+	const unsigned line_len = fix->line_length / bytespp;
+
+	int r = (color >> 16) & 0xff;
+	int g = (color >> 8) & 0xff;
+	int b = (color >> 0) & 0xff;
+
+	if (var->bits_per_pixel == 16) {
+		u16 __iomem *p = (u16 __iomem *)addr;
+		p += y * line_len + x;
+
+		r = r * 32 / 256;
+		g = g * 64 / 256;
+		b = b * 32 / 256;
+
+		__raw_writew((r << 11) | (g << 5) | (b << 0), p);
+	} else if (var->bits_per_pixel == 24) {
+		u8 __iomem *p = (u8 __iomem *)addr;
+		p += (y * line_len + x) * 3;
+
+		__raw_writeb(b, p + 0);
+		__raw_writeb(g, p + 1);
+		__raw_writeb(r, p + 2);
+	} else if (var->bits_per_pixel == 32) {
+		u32 __iomem *p = (u32 __iomem *)addr;
+		p += y * line_len + x;
+		__raw_writel(color, p);
+	}
+}
+
+static void fill_fb(struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	const short w = var->xres_virtual;
+	const short h = var->yres_virtual;
+	void __iomem *addr = fbi->screen_base;
+	int y, x;
+
+	if (!addr)
+		return;
+
+	DBG("fill_fb %dx%d, line_len %d bytes\n", w, h, fbi->fix.line_length);
+
+	for (y = 0; y < h; y++) {
+		for (x = 0; x < w; x++) {
+			if (x < 20 && y < 20)
+				draw_pixel(fbi, x, y, 0xffffff);
+			else if (x < 20 && (y > 20 && y < h - 20))
+				draw_pixel(fbi, x, y, 0xff);
+			else if (y < 20 && (x > 20 && x < w - 20))
+				draw_pixel(fbi, x, y, 0xff00);
+			else if (x > w - 20 && (y > 20 && y < h - 20))
+				draw_pixel(fbi, x, y, 0xff0000);
+			else if (y > h - 20 && (x > 20 && x < w - 20))
+				draw_pixel(fbi, x, y, 0xffff00);
+			else if (x == 20 || x == w - 20 ||
+					y == 20 || y == h - 20)
+				draw_pixel(fbi, x, y, 0xffffff);
+			else if (x == y || w - x == h - y)
+				draw_pixel(fbi, x, y, 0xff00ff);
+			else if (w - x == y || x == h - y)
+				draw_pixel(fbi, x, y, 0x00ffff);
+			else if (x > 20 && y > 20 && x < w - 20 && y < h - 20) {
+				int t = x * 3 / w;
+				unsigned r = 0, g = 0, b = 0;
+				unsigned c;
+				if (var->bits_per_pixel == 16) {
+					if (t == 0)
+						b = (y % 32) * 256 / 32;
+					else if (t == 1)
+						g = (y % 64) * 256 / 64;
+					else if (t == 2)
+						r = (y % 32) * 256 / 32;
+				} else {
+					if (t == 0)
+						b = (y % 256);
+					else if (t == 1)
+						g = (y % 256);
+					else if (t == 2)
+						r = (y % 256);
+				}
+				c = (r << 16) | (g << 8) | (b << 0);
+				draw_pixel(fbi, x, y, c);
+			} else {
+				draw_pixel(fbi, x, y, 0);
+			}
+		}
+	}
+}
+#endif
+
+static u32 owlfb_get_region_paddr(const struct owlfb_info *ofbi)
+{
+	return ofbi->region->paddr;
+}
+
+static void __iomem *owlfb_get_region_vaddr(const struct owlfb_info *ofbi)
+{
+	return ofbi->region->vaddr;
+}
+
+static struct owlfb_colormode owlfb_colormodes[] = {
+   {
+		.dssmode = OWL_DSS_COLOR_ARGB16,
+		.bits_per_pixel = 16,
+		.red	= { .length = 4, .offset = 8, .msb_right = 0 },
+		.green	= { .length = 4, .offset = 4, .msb_right = 0 },
+		.blue	= { .length = 4, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 4, .offset = 12, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_RGB16,
+		.bits_per_pixel = 16,
+		.red	= { .length = 5, .offset = 11, .msb_right = 0 },
+		.green	= { .length = 6, .offset = 5, .msb_right = 0 },
+		.blue	= { .length = 5, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_RGB24P,
+		.bits_per_pixel = 24,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_RGB24U,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_ARGB32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 8, .offset = 24, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_RGBA32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.transp	= { .length = 8, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_RGBX32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 24, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 0, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_XBGR32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 24, .msb_right = 0 },
+	}, {
+		.dssmode = OWL_DSS_COLOR_XRGB32,
+		.bits_per_pixel = 32,
+		.red	= { .length = 8, .offset = 16, .msb_right = 0 },
+		.green	= { .length = 8, .offset = 8, .msb_right = 0 },
+		.blue	= { .length = 8, .offset = 0, .msb_right = 0 },
+		.transp	= { .length = 0, .offset = 24, .msb_right = 0 },
+	},
+};
+
+static bool cmp_var_to_colormode(struct fb_var_screeninfo *var,
+		struct owlfb_colormode *color)
+{
+	bool cmp_component(struct fb_bitfield *f1, struct fb_bitfield *f2)
+	{
+		return f1->length == f2->length &&
+			f1->offset == f2->offset &&
+			f1->msb_right == f2->msb_right;
+	}
+
+	if (var->bits_per_pixel == 0 ||
+			var->red.length == 0 ||
+			var->blue.length == 0 ||
+			var->green.length == 0)
+		return 0;
+
+	return var->bits_per_pixel == color->bits_per_pixel &&
+		cmp_component(&var->red, &color->red) &&
+		cmp_component(&var->green, &color->green) &&
+		cmp_component(&var->blue, &color->blue) &&
+		cmp_component(&var->transp, &color->transp);
+}
+
+static void assign_colormode_to_var(struct fb_var_screeninfo *var,
+		struct owlfb_colormode *color)
+{
+	var->bits_per_pixel = color->bits_per_pixel;
+	var->nonstd = color->nonstd;
+	var->red = color->red;
+	var->green = color->green;
+	var->blue = color->blue;
+	var->transp = color->transp;
+}
+
+static int fb_mode_to_dss_mode(struct fb_var_screeninfo *var,
+		enum owl_color_mode *mode)
+{
+	enum owl_color_mode dssmode;
+	int i;
+
+	/* first match with nonstd field */
+	if (var->nonstd) {
+		for (i = 0; i < ARRAY_SIZE(owlfb_colormodes); ++i) {
+			struct owlfb_colormode *m = &owlfb_colormodes[i];
+			if (var->nonstd == m->nonstd) {
+				assign_colormode_to_var(var, m);
+				*mode = m->dssmode;
+				return 0;
+			}
+		}
+
+		return -EINVAL;
+	}
+
+	/* then try exact match of bpp and colors */
+	for (i = 0; i < ARRAY_SIZE(owlfb_colormodes); ++i) {
+		struct owlfb_colormode *m = &owlfb_colormodes[i];
+		if (cmp_var_to_colormode(var, m)) {
+			assign_colormode_to_var(var, m);
+			*mode = m->dssmode;
+			return 0;
+		}
+	}
+
+	/* match with bpp if user has not filled color fields
+	 * properly */
+	switch (var->bits_per_pixel) {
+	case 16:
+		dssmode = OWL_DSS_COLOR_RGB16;
+		break;
+	case 24:
+		dssmode = OWL_DSS_COLOR_RGB24P;
+		break;
+	case 32:
+		/* 
+		 * android minui only support RGBX(which is XBGR in DE),
+		 * so we set FB's default color mode to XBGR,
+		 * pls see "android/bootable/recovery/minui/graphics_fbdev.c"
+		 */
+#ifdef CONFIG_FB_COLOR_MODE_XRGB32
+		dssmode = OWL_DSS_COLOR_XRGB32;
+#else
+		dssmode = OWL_DSS_COLOR_XBGR32;
+#endif
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(owlfb_colormodes); ++i) {
+		struct owlfb_colormode *m = &owlfb_colormodes[i];
+		if (dssmode == m->dssmode) {
+			assign_colormode_to_var(var, m);
+			*mode = m->dssmode;
+			return 0;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int check_fb_res_bounds(struct fb_var_screeninfo *var)
+{
+	int xres_min = OWLFB_PLANE_XRES_MIN;
+	int xres_max = 2048;
+	int yres_min = OWLFB_PLANE_YRES_MIN;
+	int yres_max = 2048;
+
+	/* XXX: some applications seem to set virtual res to 0. */
+	if (var->xres_virtual == 0)
+		var->xres_virtual = var->xres;
+
+	if (var->yres_virtual == 0)
+		var->yres_virtual = var->yres;
+
+	if (var->xres_virtual < xres_min || var->yres_virtual < yres_min)
+		return -EINVAL;
+
+	if (var->xres < xres_min)
+		var->xres = xres_min;
+	if (var->yres < yres_min)
+		var->yres = yres_min;
+	if (var->xres > xres_max)
+		var->xres = xres_max;
+	if (var->yres > yres_max)
+		var->yres = yres_max;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+
+	return 0;
+}
+
+static void shrink_height(unsigned long max_frame_size,
+		struct fb_var_screeninfo *var)
+{
+	DBG("can't fit FB into memory, reducing y\n");
+	var->yres_virtual = max_frame_size /
+		(var->xres_virtual * var->bits_per_pixel >> 3);
+
+	if (var->yres_virtual < OWLFB_PLANE_YRES_MIN)
+		var->yres_virtual = OWLFB_PLANE_YRES_MIN;
+
+	if (var->yres > var->yres_virtual)
+		var->yres = var->yres_virtual;
+}
+
+static void shrink_width(unsigned long max_frame_size,
+		struct fb_var_screeninfo *var)
+{
+	DBG("can't fit FB into memory, reducing x\n");
+	var->xres_virtual = max_frame_size / var->yres_virtual /
+		(var->bits_per_pixel >> 3);
+
+	if (var->xres_virtual < OWLFB_PLANE_XRES_MIN)
+		var->xres_virtual = OWLFB_PLANE_XRES_MIN;
+
+	if (var->xres > var->xres_virtual)
+		var->xres = var->xres_virtual;
+}
+
+
+static int check_fb_size(const struct owlfb_info *ofbi,
+		struct fb_var_screeninfo *var)
+{
+	unsigned long max_frame_size = ofbi->region->size;
+	int bytespp = var->bits_per_pixel >> 3;
+	unsigned long line_size = var->xres_virtual * bytespp;
+
+	DBG("max frame size %lu, line size %lu\n", max_frame_size, line_size);
+
+	if (line_size * var->yres_virtual > max_frame_size)
+		shrink_height(max_frame_size, var);
+
+	if (line_size * var->yres_virtual > max_frame_size) {
+		shrink_width(max_frame_size, var);
+		line_size = var->xres_virtual * bytespp;
+	}
+
+	if (line_size * var->yres_virtual > max_frame_size) {
+		DBG("cannot fit FB to memory\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+int dss_mode_to_fb_mode(enum owl_color_mode dssmode,
+			struct fb_var_screeninfo *var)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(owlfb_colormodes); ++i) {
+		struct owlfb_colormode *mode = &owlfb_colormodes[i];
+		if (dssmode == mode->dssmode) {
+			assign_colormode_to_var(var, mode);
+			return 0;
+		}
+	}
+	return -ENOENT;
+}
+
+void set_fb_fix(struct fb_info *fbi)
+{
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_mem_region *rg = ofbi->region;
+
+	DBG("set_fb_fix\n");
+
+	/* used by open/write in fbmem.c */
+	fbi->screen_base = (char __iomem *)owlfb_get_region_vaddr(ofbi);
+
+	/* used by mmap in fbmem.c */
+	
+	fix->line_length =
+			(var->xres_virtual * var->bits_per_pixel) >> 3;
+	fix->smem_len = rg->size;
+
+	fix->smem_start = owlfb_get_region_paddr(ofbi);
+
+	fix->type = FB_TYPE_PACKED_PIXELS;
+
+	if (var->nonstd)
+		fix->visual = FB_VISUAL_PSEUDOCOLOR;
+	else {
+		switch (var->bits_per_pixel) {
+		case 32:
+		case 24:
+		case 16:
+		case 12:
+			fix->visual = FB_VISUAL_TRUECOLOR;
+			/* 12bpp is stored in 16 bits */
+			break;
+		case 1:
+		case 2:
+		case 4:
+		case 8:
+			fix->visual = FB_VISUAL_PSEUDOCOLOR;
+			break;
+		}
+	}
+
+	fix->accel = FB_ACCEL_NONE;
+
+	fix->xpanstep = 1;
+	fix->ypanstep = 1;
+}
+
+/* check new var and possibly modify it to be ok */
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owl_dss_device *display = fb2display(fbi);
+	enum owl_color_mode mode = 0;
+	int i;
+	int r;
+
+	DBG("check_fb_var %d\n", ofbi->id);
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	r = fb_mode_to_dss_mode(var, &mode);
+	if (r) {
+		DBG("cannot convert var to owl dss mode\n");
+		return r;
+	}
+
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		if ((ofbi->overlays[i]->supported_modes & mode) == 0 && mode != 0) {
+			DBG("invalid mode\n");
+			return -EINVAL;
+		}
+	}
+
+	if (var->rotate > 3)
+		return -EINVAL;
+
+	if (check_fb_res_bounds(var))
+		return -EINVAL;
+
+	/* When no memory is allocated ignore the size check */
+	if (ofbi->region->size != 0 && check_fb_size(ofbi, var))
+		return -EINVAL;
+
+	if (var->xres + var->xoffset > var->xres_virtual)
+		var->xoffset = var->xres_virtual - var->xres;
+	if (var->yres + var->yoffset > var->yres_virtual)
+		var->yoffset = var->yres_virtual - var->yres;
+
+	DBG("xres = %d, yres = %d, vxres = %d, vyres = %d\n",
+			var->xres, var->yres,
+			var->xres_virtual, var->yres_virtual);
+
+	if (display && display->driver->get_dimensions) {
+		u32 w, h;
+		display->driver->get_dimensions(display, &w, &h);
+		var->width = DIV_ROUND_CLOSEST(w, 1000);
+		var->height = DIV_ROUND_CLOSEST(h, 1000);
+	} else {
+		var->height = -1;
+		var->width = -1;
+	}
+
+	var->grayscale          = 0;
+ 
+	return 0;
+}
+
+/*
+ * ---------------------------------------------------------------------------
+ * fbdev framework callbacks
+ * ---------------------------------------------------------------------------
+ */
+static int owlfb_open(struct fb_info *fbi, int user)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	if(fbdev->mirror_fb_id != 0 && ofbi->id != 0)
+	{
+		return -1;
+	}	
+	return 0;
+}
+
+static int owlfb_release(struct fb_info *fbi, int user)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	if(fbdev->mirror_fb_id != 0 && ofbi->id != 0)
+	{
+		return -1;
+	}	
+	return 0;
+}
+
+static unsigned calc_offset_dma(const struct fb_var_screeninfo *var,
+		const struct fb_fix_screeninfo *fix)
+{
+	unsigned offset;
+
+	offset = var->yoffset * fix->line_length +
+		var->xoffset * (var->bits_per_pixel >> 3);
+
+	return offset;
+}
+
+static int owlfb_hotplug_notify(struct owl_dss_device *dssdev, int state)
+{
+	struct owl_overlay_manager *external_mgr = owl_dss_get_overlay_manager(OWL_DSS_OVL_MGR_EXTERNAL);
+	int vid ;
+	if(external_mgr != NULL 
+		&& external_mgr->device != NULL 
+		&& external_mgr->mirror_context 
+		&& external_mgr->device->type == dssdev->type)
+	{
+		if(state == 1){
+			dssdev->driver->get_vid(dssdev,&vid);
+			dssdev->driver->set_vid(dssdev,vid);		
+			dssdev->driver->enable(dssdev);	
+		}else{
+			dssdev->driver->disable(dssdev);    	
+		}
+		if(external_mgr->link_fbi != NULL){
+			owlfb_get_mem_region(FB2OFB(external_mgr->link_fbi)->region);
+			owlfb_apply_changes(external_mgr->link_fbi, 0);
+			owlfb_put_mem_region(FB2OFB(external_mgr->link_fbi)->region);
+			DBG("owlfb_hotplug_notify  dssdev %s  state %d \n",dssdev->name,state);
+		}		
+	}
+
+	return 0;	
+}
+
+static void owlfb_register_hotplug_notify(struct owl_dss_device *dssdev)
+{
+	if(dssdev && dssdev->driver){
+		if(!dssdev->driver->hot_plug_nodify){
+			dssdev->driver->hot_plug_nodify = owlfb_hotplug_notify;
+			DBG("owlfb_register_hotplug_notify  dssdev %s  \n",dssdev->name);
+		}
+	}
+}
+
+static void owlfb_calc_addr(const struct owlfb_info *ofbi,
+			     const struct fb_var_screeninfo *var,
+			     const struct fb_fix_screeninfo *fix, u32 *paddr)
+{
+	u32 data_start_p;
+	int offset;
+
+	data_start_p = owlfb_get_region_paddr(ofbi);
+
+	offset = calc_offset_dma(var, fix);
+
+	data_start_p += offset;
+
+	if (offset)
+		DBG("offset %d, %d = %d\n",
+		    var->xoffset, var->yoffset, offset);
+
+	DBG("paddr %x\n", data_start_p);
+
+	*paddr = data_start_p;
+}
+
+/* setup overlay according to the fb */
+int owlfb_setup_overlay(struct fb_info *fbi, struct owl_overlay *ovl,
+		u16 posx, u16 posy, u16 outw, u16 outh)
+{
+	int r = 0;
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	enum owl_color_mode mode = 0;
+	u32 data_start_p = 0;
+	struct owl_overlay_info info;
+	int xres, yres;
+
+	int rotation = var->rotate;
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	DBG("setup_overlay %d, posx %d, posy %d, outw %d, outh %d\n", ofbi->id,
+			posx, posy, outw, outh);
+
+	xres = var->xres;
+	yres = var->yres;
+
+	if (ofbi->region->size)
+		owlfb_calc_addr(ofbi, var, fix, &data_start_p);
+
+	r = fb_mode_to_dss_mode(var, &mode);
+	if (r) {
+		DBG("fb_mode_to_dss_mode failed");
+		goto err;
+	}
+
+	ovl->get_overlay_info(ovl, &info);
+
+	info.paddr = data_start_p;
+	info.screen_width = xres;	
+	info.img_width = xres;
+	info.img_height = yres;
+	info.width = xres;
+	info.height = yres;
+	info.color_mode = mode;
+	info.rotation = rotation;
+
+	info.pos_x = posx;
+	info.pos_y = posy;
+	info.out_width = outw;
+	info.out_height = outh;
+
+	r = ovl->set_overlay_info(ovl, &info);
+	if (r) {
+		DBG("ovl->setup_overlay_info failed\n");
+		goto err;
+	}
+
+	return 0;
+
+err:
+	DBG("setup_overlay failed\n");
+	return r;
+}
+
+/* apply var to the overlay */
+int owlfb_apply_changes(struct fb_info *fbi, int init)
+{
+	int r = 0;
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct owl_dss_device *dssdev = NULL;
+	struct owl_overlay *ovl;
+	u16 overscan_width, overscan_height;
+	u16 posx, posy;
+	u16 outw, outh;
+	int i;
+
+#ifdef DEBUG
+	if (owlfb_test_pattern)
+		fill_fb(fbi);
+#endif
+
+	if(fbdev->mirror_fb_id == 1 &&  ofbi->id == 1)
+	{
+		return 0;
+	}
+
+	WARN_ON(!atomic_read(&ofbi->region->lock_count));
+
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		ovl = ofbi->overlays[i];
+
+		DBG("apply_changes, fb %d, ovl %d var->xres %d ,var->yres %d \n", ofbi->id, ovl->id,var->xres,var->yres);
+
+		if (ofbi->region->size == 0) {
+			/* the fb is not available. disable the overlay */
+			owlfb_overlay_enable(ovl, 0);
+			if (!init && ovl->manager)
+				ovl->manager->apply(ovl->manager);
+			continue;
+		}
+
+		posx = 0;
+		posy = 0;
+		
+		dssdev = ovl->manager->device;
+		if(dssdev && dssdev->driver != NULL){
+			dssdev->driver->get_resolution(dssdev, &outw, &outh);
+		}
+		
+		if(outw == 0 || outh == 0)
+		{
+			outw = var->xres;
+			outh = var->yres;
+		}
+
+		if(dssdev->driver->get_over_scan){			
+			dssdev->driver->get_over_scan(dssdev, &overscan_width, &overscan_height);
+			outw = outw - overscan_height * 2;
+			outh = outh - overscan_height * 2;
+			posx = overscan_width;
+			posy = overscan_height;
+		}
+
+		DBG("apply_changes, init %d ,posx %d ,posy %d ,outw %d ,outh %d \n",init,posx,posy,outw,outh );
+		r = owlfb_setup_overlay(fbi, ovl, posx, posy, outw, outh);
+		
+		if (r)
+			goto err;
+
+		if (!init && ovl->manager)
+			ovl->manager->apply(ovl->manager);
+		
+		if(fbdev->mirror_fb_id == 1 && i == 0){			
+			struct owl_overlay * dest_ovl;
+			struct owl_overlay_info src_info;
+			struct owl_overlay_info dest_info;			
+			dest_ovl = owl_dss_get_overlay(3);
+			
+			dest_ovl->get_overlay_info(dest_ovl, &dest_info);
+			
+			ovl->get_overlay_info(ovl,&src_info);
+
+			dest_info.paddr = src_info.paddr;		
+			dest_info.width = src_info.width;
+			dest_info.height = src_info.height;
+			dest_info.color_mode = src_info.color_mode;
+			dest_info.rotation = src_info.rotation;
+			dest_info.img_width = src_info.img_width;
+			dest_info.img_height = src_info.img_height;
+			dest_info.pos_x = 0;
+			dest_info.pos_y = 0;
+				
+			dssdev = dest_ovl->manager->device;
+			if(dssdev != NULL && dssdev->driver){
+				if(dssdev->driver->get_resolution){
+					dssdev->driver->get_resolution(dssdev, &outw, &outh);
+				}
+				
+				if(dssdev->driver->get_over_scan){
+					dssdev->driver->get_over_scan(dssdev, &overscan_width, &overscan_height);
+					outw -= overscan_width * 2;
+					outh -= overscan_height * 2;
+					dest_info.pos_x = overscan_width;
+					dest_info.pos_y = overscan_height;
+				}
+					
+			}
+
+			dest_info.out_width = outw;
+			dest_info.out_height = outh;
+			
+			r = dest_ovl->set_overlay_info(dest_ovl, &dest_info);
+			if (r)
+				goto err;			
+				
+			if(!dest_ovl->is_enabled(dest_ovl)){	
+				dest_ovl->enable(dest_ovl);
+			}
+			//printk(KERN_ERR "  ovl->manager->apply hdmi , outw %d outh %d\n",outw,outh);
+			dest_ovl->manager->apply(dest_ovl->manager);
+		}
+	}
+	return 0;
+err:
+	DBG("apply_changes failed\n");
+	return r;
+}
+
+/* checks var and eventually tweaks it to something supported,
+ * DO NOT MODIFY PAR */
+static int owlfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	int r;
+
+	DBG("check_var(%d)\n", FB2OFB(fbi)->id);
+
+	owlfb_get_mem_region(ofbi->region);
+
+	r = check_fb_var(fbi, var);
+
+	owlfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+static void fb_videomode_to_owl_timings(struct fb_videomode *m,
+		struct owl_video_timings *t)
+{
+	t->x_res = m->xres;
+	t->y_res = m->yres;
+	t->pixel_clock = PICOS2KHZ(m->pixclock);
+	t->hsw = m->hsync_len;
+	t->hfp = m->right_margin;
+	t->hbp = m->left_margin;
+	t->vsw = m->vsync_len;
+	t->vfp = m->lower_margin;
+	t->vbp = m->upper_margin;
+}
+
+static int owlfb_set_display_mode(struct fb_info *fbi)
+{
+	struct fb_videomode mode;
+	struct owl_video_timings t;
+	struct owl_dss_device *display = fb2display(fbi);
+	
+#ifdef CONFIG_FB_MAP_TO_DE	
+	fb_var_to_videomode(&mode,&fbi->var);
+	
+	fb_videomode_to_owl_timings(&mode,&t);
+	
+	if(display->driver 
+		&& display->driver->check_timings
+		&& display->driver->set_timings
+		&& display->driver->get_timings){
+		if(!display->driver->check_timings(display,&t)){
+			display->driver->disable(display);			
+			display->driver->set_timings(display,&t);			
+			msleep(500);			
+			display->driver->enable(display);
+		}
+	}
+#endif 	
+
+	return 0;
+}
+
+/* set the video mode according to info->var */
+static int owlfb_set_par(struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	int r;
+
+	printk("set_par(%d)\n", FB2OFB(fbi)->id);
+	
+	owlfb_set_display_mode(fbi);
+
+	owlfb_get_mem_region(ofbi->region);
+
+	set_fb_fix(fbi);
+
+	r = owlfb_apply_changes(fbi, 0);
+
+	owlfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+static int owlfb_pan_display(struct fb_var_screeninfo *var,
+		struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct fb_var_screeninfo new_var;
+	int r;
+
+	DBG("pan_display(%d) var->xoffset %x ,var->yoffset %x fbi->var.xoffset %x ,fbi->var.yoffset%x \n", FB2OFB(fbi)->id,var->xoffset,var->yoffset,fbi->var.xoffset,fbi->var.yoffset);
+
+	if (var->xoffset == fbi->var.xoffset &&
+	    var->yoffset == fbi->var.yoffset)
+		//return 0;
+
+	new_var = fbi->var;
+	new_var.xoffset = var->xoffset;
+	new_var.yoffset = var->yoffset;
+
+	fbi->var = new_var;
+
+	owlfb_get_mem_region(ofbi->region);
+
+	r = owlfb_apply_changes(fbi, 0);
+
+	owlfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+static void mmap_user_open(struct vm_area_struct *vma)
+{
+	struct owlfb_mem_region *rg = vma->vm_private_data;
+
+	owlfb_get_mem_region(rg);
+	atomic_inc(&rg->map_count);
+	owlfb_put_mem_region(rg);
+}
+
+static void mmap_user_close(struct vm_area_struct *vma)
+{
+	struct owlfb_mem_region *rg = vma->vm_private_data;
+
+	owlfb_get_mem_region(rg);
+	atomic_dec(&rg->map_count);
+	owlfb_put_mem_region(rg);
+}
+
+static struct vm_operations_struct mmap_user_ops = {
+	.open = mmap_user_open,
+	.close = mmap_user_close,
+};
+
+static int owlfb_mmap(struct fb_info *fbi, struct vm_area_struct *vma)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct fb_fix_screeninfo *fix = &fbi->fix;
+	struct owlfb_mem_region *rg;
+	unsigned long off;
+	unsigned long start;
+	u32 len;
+	int r = -EINVAL;
+
+	if (vma->vm_end - vma->vm_start == 0)
+		return 0;
+	if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
+		return -EINVAL;
+	off = vma->vm_pgoff << PAGE_SHIFT;
+
+	rg = owlfb_get_mem_region(ofbi->region);
+
+	start = owlfb_get_region_paddr(ofbi);
+	len = fix->smem_len;
+	if (off >= len)
+		goto error;
+	if ((vma->vm_end - vma->vm_start + off) > len)
+		goto error;
+
+	off += start;
+
+	DBG("user mmap region start %lx, len %d, off %lx\n", start, len, off);
+
+	vma->vm_pgoff = off >> PAGE_SHIFT;
+	//vma->vm_flags |= VM_IO | VM_RESERVED;
+	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+	vma->vm_ops = &mmap_user_ops;
+	vma->vm_private_data = rg;
+	if (io_remap_pfn_range(vma, vma->vm_start, off >> PAGE_SHIFT,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot)) {
+		r = -EAGAIN;
+		goto error;
+	}
+
+	/* vm_ops.open won't be called for mmap itself. */
+	atomic_inc(&rg->map_count);
+
+	owlfb_put_mem_region(rg);
+
+	/* Apply overlay changes, SHOULD NOT be here, TODO */
+	if (ofbi->num_overlays > 0) {
+		struct owl_overlay *ovl = ofbi->overlays[0];
+		ovl->manager->apply(ovl->manager);
+	}
+
+	return 0;
+
+ error:
+	owlfb_put_mem_region(ofbi->region);
+
+	return r;
+}
+
+/* Store a single color palette entry into a pseudo palette or the hardware
+ * palette if one is available. For now we support only 16bpp and thus store
+ * the entry only to the pseudo palette.
+ */
+static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
+		u_int blue, u_int transp, int update_hw_pal)
+{
+	/*struct owlfb_info *ofbi = FB2OFB(fbi);*/
+	/*struct owlfb_device *fbdev = ofbi->fbdev;*/
+	struct fb_var_screeninfo *var = &fbi->var;
+	int r = 0;
+
+	enum owlfb_color_format mode = OWLFB_COLOR_RGB24U; /* XXX */
+
+	/*switch (plane->color_mode) {*/
+	switch (mode) {
+	case OWLFB_COLOR_YUV420:
+	case OWLFB_COLOR_YVU420:
+	case OWLFB_COLOR_YUV420SP:
+		r = -EINVAL;
+		break;	
+	case OWLFB_COLOR_RGB565:
+	case OWLFB_COLOR_RGB444:
+	case OWLFB_COLOR_RGB24P:
+	case OWLFB_COLOR_RGB24U:
+		if (r != 0)
+			break;
+
+		if (regno < 16) {
+			u16 pal;
+			pal = ((red >> (16 - var->red.length)) <<
+					var->red.offset) |
+				((green >> (16 - var->green.length)) <<
+				 var->green.offset) |
+				(blue >> (16 - var->blue.length));
+			((u32 *)(fbi->pseudo_palette))[regno] = pal;
+		}
+		break;
+	default:
+		BUG();
+	}
+	return r;
+}
+
+static int owlfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
+		u_int transp, struct fb_info *info)
+{
+	DBG("setcolreg\n");
+
+	return _setcolreg(info, regno, red, green, blue, transp, 1);
+}
+
+static int owlfb_setcmap(struct fb_cmap *cmap, struct fb_info *info)
+{
+	int count, index, r;
+	u16 *red, *green, *blue, *transp;
+	u16 trans = 0xffff;
+
+	DBG("setcmap\n");
+
+	red     = cmap->red;
+	green   = cmap->green;
+	blue    = cmap->blue;
+	transp  = cmap->transp;
+	index   = cmap->start;
+
+	for (count = 0; count < cmap->len; count++) {
+		if (transp)
+			trans = *transp++;
+		r = _setcolreg(info, index++, *red++, *green++, *blue++, trans,
+				count == cmap->len - 1);
+		if (r != 0)
+			return r;
+	}
+
+	return 0;
+}
+
+static int owlfb_blank(int blank, struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owl_dss_device *display = fb2display(fbi);
+	struct owlfb_display_data *d;
+	int r = 0;
+
+	if (!display)
+		return -EINVAL;
+	
+	DBG("owlfb_blank~~~~~~~~~~~~~~~blank %d \n",blank);
+	owlfb_lock(fbdev);
+
+	d = get_display_data(fbdev, display);
+
+	switch (blank) {
+	case FB_BLANK_UNBLANK:
+		if (display->state != OWL_DSS_DISPLAY_SUSPENDED)
+			goto exit;
+
+		if (display->driver->resume)
+			r = display->driver->resume(display);
+
+		break;
+
+	case FB_BLANK_NORMAL:
+		/* FB_BLANK_NORMAL could be implemented.
+		 * Needs DSS additions. */
+	case FB_BLANK_VSYNC_SUSPEND:
+	case FB_BLANK_HSYNC_SUSPEND:
+	case FB_BLANK_POWERDOWN:
+		if (display->state != OWL_DSS_DISPLAY_ACTIVE)
+			goto exit;
+
+		if (display->driver->suspend)
+			r = display->driver->suspend(display);
+
+		break;
+
+	default:
+		r = -EINVAL;
+	}
+
+exit:
+	owlfb_unlock(fbdev);
+
+	return r;
+}
+
+static struct fb_ops owlfb_ops = {
+	.owner          = THIS_MODULE,
+	.fb_open        = owlfb_open,
+	.fb_release     = owlfb_release,
+#if 1
+	.fb_fillrect    = cfb_fillrect,
+	.fb_copyarea    = cfb_copyarea,
+	.fb_imageblit   = cfb_imageblit,
+#endif
+	.fb_blank       = owlfb_blank,
+	.fb_ioctl       = owlfb_ioctl,
+	.fb_check_var   = owlfb_check_var,
+	.fb_set_par     = owlfb_set_par,
+	.fb_pan_display = owlfb_pan_display,
+	.fb_mmap	= owlfb_mmap,
+	.fb_setcolreg	= owlfb_setcolreg,
+	.fb_setcmap	= owlfb_setcmap,
+	/*.fb_write	= owlfb_write,*/
+};
+
+static void owlfb_free_fbmem(struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_mem_region *rg;
+
+	rg = ofbi->region;
+
+	WARN_ON(atomic_read(&rg->map_count));
+
+	if (rg->paddr) {
+        /* paddr free? TODO */
+    }
+
+	if (rg->vaddr)
+		iounmap(rg->vaddr);
+
+	rg->vaddr = NULL;
+	rg->paddr = 0;
+	rg->alloc = 0;
+	rg->size = 0;
+}
+
+static void clear_fb_info(struct fb_info *fbi)
+{
+	memset(&fbi->var, 0, sizeof(fbi->var));
+	memset(&fbi->fix, 0, sizeof(fbi->fix));
+	strlcpy(fbi->fix.id, MODULE_NAME, sizeof(fbi->fix.id));
+}
+
+int owlfb_free_all_fbmem_after_dc(struct owlfb_device *fbdev)
+{
+	int i;   
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct owlfb_info *ofbi = FB2OFB(fbi);
+		struct owlfb_mem_region *rg;
+		rg = ofbi->region;	
+		if (rg->paddr) {
+	        dma_free_coherent(NULL, rg->size, rg->vaddr, rg->paddr);
+	        DBG("owlfb_free_all_fbmem_after_dc size 0x%x\n",rg->size);
+	    }
+	}
+	return 0;
+}
+
+static int owlfb_free_all_fbmem(struct owlfb_device *fbdev)
+{
+	int i;
+
+	DBG("free all fbmem\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		owlfb_free_fbmem(fbi);
+		clear_fb_info(fbi);
+	}
+
+	return 0;
+}
+
+static int owlfb_alloc_fbmem(struct fb_info *fbi, unsigned long size)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_mem_region *rg;
+	void __iomem *vaddr = NULL;
+	unsigned long paddr;
+
+	rg = ofbi->region;
+
+	rg->paddr = 0;
+	rg->vaddr = NULL;
+	rg->size = 0;
+	rg->type = 0;
+	rg->alloc = false;
+	rg->map = false;
+
+	size = PAGE_ALIGN(size);
+
+	DBG("allocating %lu bytes for fb %d\n", size, ofbi->id);
+		
+     /* really cast me? TODO */
+	vaddr = dma_alloc_coherent(NULL, size,
+                                   (dma_addr_t *)&paddr, GFP_KERNEL);
+	
+    if (!vaddr) {
+        printk(KERN_ERR "fail to allocate fb mem (size: %ldK))\n", size / 1024);
+        return -ENOMEM;
+    }
+
+	//SetPageReserved(pfn_to_page(((unsigned long) paddr) >> PAGE_SHIFT));
+
+	DBG("allocated VRAM paddr %lx, vaddr %p\n", paddr, vaddr);
+
+	rg->paddr = paddr;
+	rg->vaddr = vaddr;
+	rg->size = size;
+	rg->alloc = 1;
+
+	return 0;
+}
+
+/* allocate fbmem using display resolution as reference */
+static int owlfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owl_dss_device *display;
+	int bytespp;
+
+	display =  fb2display(fbi);
+
+	if (!display)
+		return 0;
+
+	switch (owlfb_get_recommended_bpp(fbdev, display)) {
+	case 16:
+		bytespp = 2;
+		break;
+	case 24:
+		bytespp = 4;
+		break;
+	default:
+		bytespp = 4;
+		break;
+	}
+
+	if (!size) {
+		u16 w, h;
+
+		display->driver->get_resolution(display, &w, &h);
+
+		size = w * h * bytespp * OWLFB_NUM_BUFFERS_PER_FB;
+
+	}
+
+	if (!size)
+		return 0;
+
+	return owlfb_alloc_fbmem(fbi, size);
+}
+static int owlfb_allocate_all_fbs(struct owlfb_device *fbdev)
+{
+	int i, r;
+	unsigned long size = 0;
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		/* allocate memory automatically only for fb0, or if
+		 * excplicitly defined with vram or plat data option */
+		size = 0;
+		if(i == 0){
+			size = OWLFB_BUFFERS_MAX_XRES * OWLFB_BUFFERS_MAX_YRES * fbdev->bpp * OWLFB_NUM_BUFFERS_PER_FB;
+#if CONFIG_FB_MAP_TO_DE	
+			size += OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL * OWLFB_MAX_OVL_MEM_RESERVE_NUM + OWLFB_MAX_CURSOR_MEM_RESERVE;		
+#endif 
+		}
+		DBG("owlfb_allocate_all_fbs allocating %lu bytes for fb %d\n", size,i);
+		r = owlfb_alloc_fbmem_display(fbdev->fbs[i],size);
+		if (r)
+			return r;		
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		struct owlfb_mem_region *rg;
+		rg = ofbi->region;
+		
+		if(i == 0){
+			ofbi->overlay_free_mem_size = OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL * OWLFB_MAX_OVL_MEM_RESERVE_NUM;
+			ofbi->overlay_free_mem_off = 0;
+			ofbi->overlay_mem_base = fbdev->xres * fbdev->yres * fbdev->bpp * OWLFB_NUM_BUFFERS_PER_FB;
+			
+			DBG("ofbi->overlay_free_mem_size 0x%x ofbi->overlay_mem_base 0x%x \n",ofbi->overlay_free_mem_size,ofbi->overlay_mem_base);
+		}
+		ofbi->used_overlay_mask |= 0x01;
+
+		DBG("region%d phys %08x virt %p size=%lu\n",
+				i,
+				rg->paddr,
+				rg->vaddr,
+				rg->size);
+	}
+
+	return 0;
+}
+
+int owlfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owlfb_mem_region *rg = ofbi->region;
+	unsigned long old_size = rg->size;
+	int old_type = rg->type;
+	int r;
+
+	if (type > OWLFB_MEMTYPE_MAX)
+		return -EINVAL;
+
+	size = PAGE_ALIGN(size);
+
+	if (old_size == size && old_type == type)
+		return 0;
+
+	owlfb_free_fbmem(fbi);
+
+	if (size == 0) {
+		clear_fb_info(fbi);
+		return 0;
+	}
+
+	r = owlfb_alloc_fbmem(fbi, size);
+
+	if (r) {
+		if (old_size)
+			owlfb_alloc_fbmem(fbi, old_size);
+
+		if (rg->size == 0)
+			clear_fb_info(fbi);
+
+		return r;
+	}
+
+	if (old_size == size)
+		return 0;
+
+	if (old_size == 0) {
+		DBG("initializing fb %d\n", ofbi->id);
+		r = owlfb_fb_init(fbdev, fbi);
+		if (r) {
+			DBG("owlfb_fb_init failed\n");
+			goto err;
+		}
+		r = owlfb_apply_changes(fbi, 1);
+		if (r) {
+			DBG("owlfb_apply_changes failed\n");
+			goto err;
+		}
+	} else {
+		struct fb_var_screeninfo new_var;
+		memcpy(&new_var, &fbi->var, sizeof(new_var));
+		r = check_fb_var(fbi, &new_var);
+		if (r)
+			goto err;
+		memcpy(&fbi->var, &new_var, sizeof(fbi->var));
+		set_fb_fix(fbi);
+		
+	}
+
+	return 0;
+err:
+	owlfb_free_fbmem(fbi);
+	clear_fb_info(fbi);
+	return r;
+}
+
+struct fb_videomode cvbs_mode_list[2] ={
+	/* 720x576i @ 50 Hz, 15.625 kHz hsync (PAL RGB) */
+	[0] = {
+		NULL, 50, 720, 576, 74074, 64, 16, 39, 5, 64, 5, 0,
+		FB_VMODE_INTERLACED
+	},
+	/* #3: 720x480i at 59.94/60Hz */
+	[1] = {
+		NULL, 60, 720, 480, 37037, 60, 16, 30, 9, 62, 6, 0,
+		FB_VMODE_INTERLACED, 0,
+	},
+};
+static int owlfb_build_modelist(struct fb_info *fbi,struct owl_dss_device *display)
+{
+	struct fb_monspecs *specs;
+	u8 *edid;
+	int r, i, len;	
+	if (!display->driver->read_edid){
+		if(display->type == OWL_DISPLAY_TYPE_CVBS){
+			for(i = 0 ; i < 2 ; i++){
+				fb_add_videomode(&cvbs_mode_list[i],&fbi->modelist);
+			}
+			return 0;			
+		}else{
+			return -ENODEV;
+		}		
+	}
+	
+	len = 0x80 * 2;
+	edid = kmalloc(len, GFP_KERNEL);
+
+	r = display->driver->read_edid(display, edid, len);
+	if (r < 0){
+		printk("read_edid r %d \n",r);
+		goto err1;
+	}
+	
+	fb_destroy_modelist(&fbi->modelist);
+	
+	memset(&fbi->monspecs, 0, sizeof(fbi->monspecs));
+
+	specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+
+	fb_edid_to_monspecs(edid, specs);
+
+	if (edid[126] > 0)
+		fb_edid_add_monspecs(edid + 0x80, specs);
+
+	DBG("specs->modedb_len %d \n",specs->modedb_len);
+	for (i = 0; i < specs->modedb_len; ++i) {
+		struct fb_videomode *m;
+		struct owl_video_timings t;
+
+		m = &specs->modedb[i];
+
+		if (m->pixclock == 0)
+			continue;
+			
+		if (m->vmode & FB_VMODE_INTERLACED ||
+				m->vmode & FB_VMODE_DOUBLE)
+			continue;
+
+		fb_videomode_to_owl_timings(m, &t);		
+					
+		r = display->driver->check_timings(display, &t);
+		if (r == 0 ) {
+			fb_add_videomode(m,	&fbi->modelist);
+		}
+	}
+	r = 0;
+
+	fb_destroy_modedb(specs->modedb);
+	kfree(specs);
+err1:
+	kfree(edid);
+
+	return r;
+}
+
+/* initialize fb_info, var, fix to something sane based on the display */
+static int owlfb_fb_init(struct owlfb_device *fbdev, struct fb_info *fbi)
+{
+	struct fb_var_screeninfo *var = &fbi->var;
+	struct owl_dss_device *display = fb2display(fbi);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	const struct fb_videomode * best_mode = NULL;
+	int r = 0;
+
+	fbi->fbops = &owlfb_ops;
+	fbi->flags = FBINFO_FLAG_DEFAULT;
+	fbi->pseudo_palette = fbdev->pseudo_palette;
+
+	if (ofbi->region->size == 0) {
+		clear_fb_info(fbi);
+		return 0;
+	}
+
+	var->nonstd = 0;
+	var->bits_per_pixel = 0;
+	
+	
+	switch (owlfb_get_recommended_bpp(fbdev, display)) {
+	case 16:
+		var->bits_per_pixel = 16;
+		break;
+	case 24:
+		var->bits_per_pixel = 32;
+		break;
+	default:
+		var->bits_per_pixel = 32;
+		break;
+	}
+	
+	fbdev->bpp = var->bits_per_pixel / 8;
+	
+
+	if(owlfb_build_modelist(fbi,display) == 0)
+	{
+		best_mode =  fb_find_best_display(&fbi->monspecs, &fbi->modelist);
+		best_mode = NULL;
+				
+	}	
+	if(best_mode != NULL){		
+		
+		fb_videomode_to_var(var, best_mode);
+				
+	}else{
+		/*is primary fb or display is null ,we used fbdev res as ofbi res */
+		if(display != NULL && display->driver != NULL && display->driver->get_timings)
+		{
+			struct owl_video_timings timings;
+			display->driver->get_timings(display,&timings);			
+			var->xres = timings.x_res;
+			var->yres = timings.y_res;
+			var->xres_virtual = timings.x_res;
+			var->yres_virtual = timings.y_res;
+			var->xoffset = 0;
+			var->yoffset = 0;
+			var->pixclock = KHZ2PICOS(timings.pixel_clock);
+			var->left_margin = timings.hfp;
+			var->right_margin = timings.hbp;
+			var->upper_margin = timings.vfp;
+			var->lower_margin = timings.vbp;
+			var->hsync_len = timings.hsw;
+			var->vsync_len = timings.vsw;			
+		}else{
+			var->xres = fbdev->xres;
+			var->yres = fbdev->yres;
+			var->xres_virtual = var->xres;
+			var->yres_virtual = var->yres;
+			var->bits_per_pixel = fbdev->bpp * 8;	
+		}	
+	}	
+	
+	r = check_fb_var(fbi, var);
+	
+	if (r)
+		goto err;
+
+	set_fb_fix(fbi);
+
+	r = fb_alloc_cmap(&fbi->cmap, 256, 0);
+	if (r)
+		dev_err(fbdev->dev, "unable to allocate color map memory\n");
+
+	DBG("obfi %d  var:xres %d ,yres %d ,bit_per_pixel %d pixclock %d \n",ofbi->id,var->xres,var->yres,var->bits_per_pixel,var->pixclock);	
+err:
+	return r;
+}
+
+static int owlfb_hotplug_notify(struct owl_dss_device *dssdev, int state)
+{
+	
+	struct owl_overlay_manager *external_mgr = owl_dss_get_overlay_manager(OWL_DSS_OVL_MGR_EXTERNAL);
+	int vid ;		 
+	printk("owlfb_hotplug_notify %d ~~~~~~ \n",state);	
+	if(state == 1){
+		dssdev->driver->disable(dssdev);
+		dssdev->driver->get_vid(dssdev,&vid);
+		dssdev->driver->set_vid(dssdev,vid);
+		dssdev->driver->enable(dssdev);
+			
+	}else{
+		dssdev->driver->disable(dssdev);
+	}	
+#ifdef CONFIG_FB_MAP_TO_DE
+	printk("owlfb_hotplug_notify owlfb_apply_changes \n");
+	if(external_mgr != NULL && external_mgr->link_fbi != NULL){	
+		if(state)
+			{
+				struct owlfb_info *ofbi = FB2OFB(external_mgr->link_fbi);
+				struct owlfb_device *fbdev = ofbi->fbdev;
+				struct fb_info *fbi = fbdev->fbs[0];
+				
+				if(external_mgr->device->type == dssdev->type)
+				{
+					fbi=fbdev->fbs[1];
+					printk("external_mgr is fb1\n");
+				}
+				owlfb_build_modelist(fbi,dssdev);	
+			}	
+		
+			owlfb_get_mem_region(FB2OFB(external_mgr->link_fbi)->region);
+			owlfb_apply_changes(external_mgr->link_fbi, 0);
+			owlfb_put_mem_region(FB2OFB(external_mgr->link_fbi)->region);	
+	}
+#endif
+
+	return 0;
+}
+
+static void owlfb_register_hotplug_notify(struct owl_dss_device *dssdev)
+{
+	if(dssdev && dssdev->driver){
+		if(!dssdev->driver->hot_plug_nodify){
+			dssdev->driver->hot_plug_nodify = owlfb_hotplug_notify;
+			DBG("owlfb_register_hotplug_notify  dssdev %s  \n",dssdev->name);
+		}
+	}
+}
+
+static void fbinfo_cleanup(struct owlfb_device *fbdev, struct fb_info *fbi)
+{
+	fb_dealloc_cmap(&fbi->cmap);
+}
+
+
+static void owlfb_free_resources(struct owlfb_device *fbdev)
+{
+	int i;
+
+	DBG("free_resources\n");
+
+	if (fbdev == NULL)
+		return;
+
+	for (i = 0; i < fbdev->num_fbs; i++)
+		unregister_framebuffer(fbdev->fbs[i]);
+
+	/* free the reserved fbmem */
+	owlfb_free_all_fbmem(fbdev);
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		fbinfo_cleanup(fbdev, fbdev->fbs[i]);
+		framebuffer_release(fbdev->fbs[i]);
+	}
+
+	for (i = 0; i < fbdev->num_displays; i++) {
+		struct owl_dss_device *dssdev = fbdev->displays[i].dssdev;
+
+		if (dssdev->state != OWL_DSS_DISPLAY_DISABLED)
+			dssdev->driver->disable(dssdev);
+
+		owl_dss_put_device(dssdev);
+	}
+
+	dev_set_drvdata(fbdev->dev, NULL);
+	kfree(fbdev);
+}
+
+static int owlfb_create_framebuffers(struct owlfb_device *fbdev)
+{
+	int r, i ,k = 0 , j = 0;
+
+	fbdev->num_fbs = 0;
+
+	DBG("create %d framebuffers\n",	OWLFB_NUM_FBS);
+
+	/* allocate fb_infos */
+	for (i = 0; i < OWLFB_NUM_FBS; i++) {
+		struct fb_info *fbi;
+		struct owlfb_info *ofbi;
+
+		fbi = framebuffer_alloc(sizeof(struct owlfb_info),
+				fbdev->dev);
+
+		if (fbi == NULL) {
+			dev_err(fbdev->dev,
+				"unable to allocate memory for plane info\n");
+			return -ENOMEM;
+		}
+
+		clear_fb_info(fbi);
+
+		fbdev->fbs[i] = fbi;
+
+		ofbi = FB2OFB(fbi);
+		ofbi->fbdev = fbdev;
+		ofbi->id = i;
+
+		ofbi->region = &fbdev->regions[i];
+		ofbi->region->id = i;
+		init_rwsem(&ofbi->region->lock);
+		INIT_LIST_HEAD(&fbi->modelist);
+		fbdev->num_fbs++;
+	}
+
+	printk("fb_infos allocated\n");
+	
+	/* assign managers for the fbs */
+	DBG("assign managers for the fbs fbdev->def_display %p \n",fbdev->def_display);
+	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		ofbi->manager =  owl_dss_get_overlay_manager(i);
+		
+		if(ofbi->manager->device){
+			ofbi->manager->unset_device(ofbi->manager);
+		}		
+		/* connected display to managers */
+		if(fbdev->def_display != NULL && i == 0){
+			ofbi->manager->set_device(ofbi->manager,fbdev->def_display);
+		}else{
+			for( j = 0 ; j < fbdev->num_displays ; j++){
+				if(!fbdev->displays[j].connected){
+					fbdev->displays[j].connected = true;
+					ofbi->manager->set_device(ofbi->manager,fbdev->displays[j].dssdev);
+					
+					if(i != 0){
+						DBG("owlfb_register_hotplug_notify allocated %s \n",fbdev->displays[j].dssdev->name);
+						owlfb_register_hotplug_notify(fbdev->displays[j].dssdev);
+					}
+					
+					break;
+				}
+			}			
+		}
+	}	
+
+	/* assign overlays for the fbs */
+	DBG(" assign overlays for the fbs  \n");
+	for (i = 0; i < min(fbdev->num_fbs, fbdev->num_overlays); i++) {
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		/*this primary fb , we used ovl 1,2*/
+		if(i == 0)
+		{			
+			ofbi->num_overlays = 2;
+			for(j = 0 ; j < ofbi->num_overlays; j++)
+			{
+				ofbi->overlays[j] = fbdev->overlays[k++];
+				DBG("assign ovl %d  for fbs  %d \n", k,i);
+			}
+		}else{
+			/*this external fb , we used ovl 4*/
+			ofbi->num_overlays = 2;
+			for(j = 0 ; j < ofbi->num_overlays; j++)
+			{
+				ofbi->overlays[j] = fbdev->overlays[k++];
+				DBG("assign ovl %d  for fbs  %d \n", k,i);
+			}
+		}
+	}
+	
+	/* check overlay and manager for ofbi*/
+	DBG(" check overlay and manager for ofbi \n");
+	for (i = 0; i < fbdev->num_fbs; i++) {		
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+		DBG(" ofbi %d , ofbi->num_overlays %d  \n",i,ofbi->num_overlays);
+		for( j = 0 ; j < ofbi->num_overlays;j++){
+			struct owl_overlay *ovl = ofbi->overlays[j];	
+			if (ovl != NULL && ovl->manager != NULL
+				&& ovl->manager->id != ofbi->manager->id) {
+					ovl->disable(ovl);
+			    	ovl->unset_manager(ovl);		    	
+			}
+			ovl->set_manager(ovl,ofbi->manager); 
+			DBG("ovl %s set to manager %s ",ovl->name,ofbi->manager->name);
+		}		
+	}		
+	/* allocate fb memories */
+	r = owlfb_allocate_all_fbs(fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to allocate fbmem\n");
+		return r;
+	}
+
+	DBG("fbmems allocated\n");
+
+	/* setup fb_infos */
+    DBG(" setup fb_infos %d \n",fbdev->num_fbs);
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct owlfb_info *ofbi = FB2OFB(fbi);
+
+		owlfb_get_mem_region(ofbi->region);
+		r = owlfb_fb_init(fbdev, fbi);
+		owlfb_put_mem_region(ofbi->region);
+
+		if (r) {
+			dev_err(fbdev->dev, "failed to setup fb_info\n");
+			return r;
+		}
+	}
+
+	DBG("fb_infos initialized\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		r = register_framebuffer(fbdev->fbs[i]);
+		if (r != 0) {
+			dev_err(fbdev->dev,
+				"registering framebuffer %d failed\n", i);
+			return r;
+		}
+	}
+
+	DBG("framebuffers registered\n");
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct fb_info *fbi = fbdev->fbs[i];
+		struct owlfb_info *ofbi = FB2OFB(fbi);
+
+		owlfb_get_mem_region(ofbi->region);
+		r = owlfb_apply_changes(fbi, 1);
+		owlfb_put_mem_region(ofbi->region);
+
+		if (r) {
+			dev_err(fbdev->dev, "failed to change mode\n");
+			return r;
+		}
+	}
+
+	/* Enable fb0 */
+	if (fbdev->num_fbs > 0) {
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[0]);
+
+		if (ofbi->num_overlays > 0) {
+			struct owl_overlay *ovl = ofbi->overlays[0];
+
+			r = owlfb_overlay_enable(ovl, 1);
+
+			if (r) {
+				dev_err(fbdev->dev,
+						"failed to enable overlay\n");
+				return r;
+			}
+		}
+	}
+
+	DBG("create_framebuffers done\n");
+
+	return 0;
+}
+
+static int owlfb_get_recommended_bpp(struct owlfb_device *fbdev,
+		struct owl_dss_device *dssdev)
+{
+	struct owlfb_display_data *d;
+
+	BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
+
+	d = get_display_data(fbdev, dssdev);
+
+	if (d->bpp_override != 0)
+		return d->bpp_override;
+
+	return dssdev->driver->get_recommended_bpp(dssdev);
+}
+static int owlfb_init_display(struct owlfb_device *fbdev,
+		struct owl_dss_device *dssdev)
+{
+	struct owl_dss_driver *dssdrv = dssdev->driver;
+	struct owlfb_display_data *d;
+	int r;
+
+	r = dssdrv->enable(dssdev);
+	if (r) {
+		dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
+				dssdev->name);
+		return r;
+	}
+
+	d = get_display_data(fbdev, dssdev);
+
+	d->fbdev = fbdev;
+		
+	return 0;
+}
+
+
+static int owlfb_parse_params(struct platform_device *pdev,struct owlfb_device * fbdev)
+{
+	struct device_node      *of_node;
+	const char *def_display_name;
+	u32 xres , yres;
+	int i ;
+
+	of_node = pdev->dev.of_node;
+
+	of_property_read_string(of_node, "def_display", &def_display_name);
+	DBG("def_display is %s \n",def_display_name);
+	for (i = 0; i < fbdev->num_displays; ++i) {
+		if (strcmp(fbdev->displays[i].dssdev->name,
+					def_display_name) == 0) {
+			fbdev->def_display = fbdev->displays[i].dssdev;
+			fbdev->displays[i].connected = true;
+			DBG("fbdev->def_display is %p \n",fbdev->def_display);
+			break;
+		}
+	}
+
+	if(fbdev->def_display == NULL){
+		fbdev->def_display = fbdev->displays[0].dssdev;
+		fbdev->displays[0].connected = true;
+	}
+
+	if( fbdev->def_display != NULL 
+	   && fbdev->def_display->driver != NULL 
+	   && fbdev->def_display->driver->get_timings != NULL){
+		struct owl_video_timings timings;
+		if(fbdev->def_display->driver->get_timings){
+			fbdev->def_display->driver->get_timings(fbdev->def_display,&timings);
+			fbdev->xres = timings.x_res;
+			fbdev->yres = timings.y_res;
+			fbdev->refresh = timings.pixel_clock * 1000 
+					/ ((timings.x_res + timings.hsw + timings.hfp + timings.hbp) 
+					* (timings.y_res + timings.vsw + timings.vfp + timings.vbp));
+		}
+	}
+
+	if(!of_property_read_u32(of_node, "xres", &xres) 
+	   && !of_property_read_u32(of_node, "yres", &yres)) {    	
+		fbdev->xres = xres;
+		fbdev->yres = yres;
+		if(fbdev->refresh == 0)
+		{
+			fbdev->refresh = 60;
+		}    	
+	} 
+	fbdev->bpp = 4;       
+	printk("fbdev info : xres %d yres %d refresh %d name %s \n",fbdev->xres,fbdev->yres,fbdev->refresh,fbdev->def_display->name);
+
+	return 0;
+}
+
+static struct of_device_id owl_fb_of_match[] = {
+	{
+		.compatible	= "actions,framebuffer",
+	},
+	{},
+};
+static int owlfb_probe(struct platform_device *pdev)
+{
+	struct owlfb_device *fbdev = NULL;
+	const struct of_device_id *match;
+	int r = 0;
+	int i;
+	struct owl_dss_device *dssdev;
+	struct device *dev = &pdev->dev;
+	DBG("owlfb_probe\n");
+	
+	match = of_match_device(of_match_ptr(owl_fb_of_match), dev);
+	if (!match) {
+		dev_err(dev, "Error: No device match found\n");
+		return -ENODEV;
+	}	
+
+	fbdev = kzalloc(sizeof(struct owlfb_device), GFP_KERNEL);
+	if (fbdev == NULL) {
+		r = -ENOMEM;
+		goto err0;
+	}
+
+	mutex_init(&fbdev->mtx);
+
+	fbdev->dev = &pdev->dev;
+	platform_set_drvdata(pdev, fbdev);
+
+	r = 0;
+	fbdev->num_displays = 0;
+	dssdev = NULL;
+	for_each_dss_dev(dssdev) {
+		struct owlfb_display_data *d;
+
+		owl_dss_get_device(dssdev);
+
+		if (!dssdev->driver) {
+			owl_dss_put_device(dssdev);
+			continue;
+		}
+
+		d = &fbdev->displays[fbdev->num_displays++];
+		d->dssdev = dssdev;
+	}
+
+	if (r)
+		goto cleanup;
+
+	if (fbdev->num_displays == 0) {
+		dev_err(&pdev->dev, "no displays\n");
+		r = -EINVAL;
+		goto cleanup;
+	}
+
+	fbdev->num_overlays = owl_dss_get_num_overlays();
+	for (i = 0; i < fbdev->num_overlays; i++)
+		fbdev->overlays[i] = owl_dss_get_overlay(i);
+
+	fbdev->num_managers = owl_dss_get_num_overlay_managers();
+	
+	for (i = 0; i < fbdev->num_managers; i++)
+		fbdev->managers[i] = owl_dss_get_overlay_manager(i);
+		
+	fbdev->mirror_fb_id	 = 0;
+		
+	owlfb_parse_params(pdev,fbdev);  
+	
+	r = owlfb_create_framebuffers(fbdev);
+	if (r)
+		goto cleanup;
+
+	if (fbdev->def_display) {
+	    if(owl_get_boot_mode() != OWL_BOOT_MODE_UPGRADE){
+				r = owlfb_init_display(fbdev, fbdev->def_display);
+				if (r) {
+					dev_err(fbdev->dev,
+							"failed to initialize default "
+							"display\n");
+					goto cleanup;
+				}
+			}else{
+			    printk(" upgrade mode not open display \n");
+			}
+	}
+
+#ifdef CONFIG_FB_MAP_TO_DE
+	for (i = 0; i < fbdev->num_managers; i++) {
+		struct owl_overlay_manager *mgr;
+		mgr = fbdev->managers[i];
+		r = mgr->apply(mgr);
+		if (r)
+			dev_warn(fbdev->dev, "failed to apply dispc config\n");
+	}
+#endif
+
+	DBG("create sysfs for fbs\n");
+	r = owlfb_create_sysfs(fbdev);
+	if (r) {
+		dev_err(fbdev->dev, "failed to create sysfs entries\n");
+		goto cleanup;
+	}
+	
+	owlfb_dc_init(fbdev);
+	
+	return 0;
+
+cleanup:
+	owlfb_free_resources(fbdev);
+err0:
+	dev_err(&pdev->dev, "failed to setup owlfb\n");
+	return r;
+}
+
+static int owlfb_remove(struct platform_device *pdev)
+{
+	struct owlfb_device *fbdev = platform_get_drvdata(pdev);
+
+	/* FIXME: wait till completion of pending events */
+
+	owlfb_remove_sysfs(fbdev);
+
+	owlfb_free_resources(fbdev);
+
+	return 0;
+}
+
+static struct platform_driver owlfb_driver = {
+	.probe          = owlfb_probe,
+	.remove         = owlfb_remove,
+	.driver         = {
+		.name   = "framebuffer",
+		.owner  = THIS_MODULE,
+		.of_match_table	= owl_fb_of_match,
+	},
+};
+
+static int __init owlfb_init(void)
+{
+	DBG("owlfb_init\n");
+
+	if (platform_driver_register(&owlfb_driver)) {
+		printk(KERN_ERR "failed to register owlfb driver\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __exit owlfb_exit(void)
+{
+	DBG("owlfb_exit\n");
+
+	platform_driver_unregister(&owlfb_driver);
+}
+
+/* late_initcall to let panel/ctrl drivers loaded first.
+ * I guess better option would be a more dynamic approach,
+ * so that owlfb reowl to new panels when they are loaded */
+late_initcall(owlfb_init);
+/*module_init(owlfb_init);*/
+module_exit(owlfb_exit);
+
+MODULE_AUTHOR("Hui Wang  <wanghui at actions-semi.com>");
+MODULE_DESCRIPTION("OWL2/3 Framebuffer");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/owl/fb/owlfb-sysfs.c b/drivers/video/fbdev/owl/fb/owlfb-sysfs.c
new file mode 100755
index 0000000..a87e46c
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb-sysfs.c
@@ -0,0 +1,498 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb-sysfs.c
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+#include <mach/bootdev.h>
+#include <linux/fb.h>
+#include <linux/sysfs.h>
+#include <linux/device.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+
+#include <video/owldss.h>
+#include <video/owlfb.h>
+
+#include "owlfb.h"
+
+extern int dss_mgr_enable(struct owl_overlay_manager *mgr);
+extern int dss_mgr_disable(struct owl_overlay_manager *mgr);
+
+static ssize_t show_mirror_to_hdmi(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", fbdev->mirror_fb_id);
+}
+
+static ssize_t store_mirror_to_hdmi(struct device *dev,
+		struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	bool mirror_to_hdmi;
+	int vid = 1;
+	
+	struct owl_overlay_manager *external_mgr = owl_dss_get_overlay_manager(OWL_DSS_OVL_MGR_EXTERNAL);
+	struct owl_dss_device *dssdev = external_mgr->device;
+	
+	if (owl_get_boot_mode() == OWL_BOOT_MODE_UPGRADE || dssdev == NULL) {
+		printk("upgrade process hdmi disabled!!\n");
+		return -ENODEV;
+	}
+	
+	r = strtobool(buf, &mirror_to_hdmi);
+	if (r)
+		return r;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	fbdev->mirror_fb_id = mirror_to_hdmi;
+	
+	owlfb_get_mem_region(ofbi->region);
+	DBG("store_mirror_to_hdmi %d\n",mirror_to_hdmi);
+	if(mirror_to_hdmi){
+		external_mgr->mirror_context = true;
+		if(dssdev->driver->get_cable_status){
+			if(dssdev->driver->get_cable_status(dssdev)){
+				dssdev->driver->get_vid(dssdev,&vid);
+				dssdev->driver->set_vid(dssdev,vid);		
+				dssdev->driver->enable(dssdev);	
+			}
+		}else{
+			dssdev->driver->get_vid(dssdev,&vid);
+			dssdev->driver->set_vid(dssdev,vid);		
+			dssdev->driver->enable(dssdev);	
+		}		
+		external_mgr->link_fbi	= fbi;
+		
+    }else{
+    	
+    	dssdev->driver->disable(dssdev);
+    	external_mgr->mirror_context = false;
+    	external_mgr->link_fbi	= NULL;
+    }   
+    
+	r = owlfb_apply_changes(fbi, 0);
+	if (r)
+		goto out;
+
+	r = count;
+out:
+	owlfb_put_mem_region(ofbi->region);
+
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_overlays(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	ssize_t l = 0;
+	int t;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	owlfb_lock(fbdev);
+
+	for (t = 0; t < ofbi->num_overlays; t++) {
+		struct owl_overlay *ovl = ofbi->overlays[t];
+		int ovlnum;
+
+		for (ovlnum = 0; ovlnum < fbdev->num_overlays; ++ovlnum)
+			if (ovl == fbdev->overlays[ovlnum])
+				break;
+
+		l += snprintf(buf + l, PAGE_SIZE - l, "%s%d",
+				t == 0 ? "" : ",", ovlnum);
+	}
+
+	l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+	owlfb_unlock(fbdev);
+	unlock_fb_info(fbi);
+
+	return l;
+}
+
+static struct owlfb_info *get_overlay_fb(struct owlfb_device *fbdev,
+		struct owl_overlay *ovl)
+{
+	int i, t;
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct owlfb_info *ofbi = FB2OFB(fbdev->fbs[i]);
+
+		for (t = 0; t < ofbi->num_overlays; t++) {
+			if (ofbi->overlays[t] == ovl)
+				return ofbi;
+		}
+	}
+
+	return NULL;
+}
+
+static ssize_t store_overlays(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owl_overlay *ovls[OWLFB_MAX_OVL_PER_FB];
+	struct owl_overlay *ovl;
+	int num_ovls, r, i;
+	int len;
+	bool added = false;
+
+	num_ovls = 0;
+
+	len = strlen(buf);
+	if (buf[len - 1] == '\n')
+		len = len - 1;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	owlfb_lock(fbdev);
+
+	if (len > 0) {
+		char *p = (char *)buf;
+		int ovlnum;
+
+		while (p < buf + len) {
+			int found;
+			if (num_ovls == OWLFB_MAX_OVL_PER_FB) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			ovlnum = simple_strtoul(p, &p, 0);
+			if (ovlnum > fbdev->num_overlays) {
+				r = -EINVAL;
+				goto out;
+			}
+
+			found = 0;
+			for (i = 0; i < num_ovls; ++i) {
+				if (ovls[i] == fbdev->overlays[ovlnum]) {
+					found = 1;
+					break;
+				}
+			}
+
+			if (!found)
+				ovls[num_ovls++] = fbdev->overlays[ovlnum];
+
+			p++;
+		}
+	}
+
+	for (i = 0; i < num_ovls; ++i) {
+		struct owlfb_info *ofbi2 = get_overlay_fb(fbdev, ovls[i]);
+		if (ofbi2 && ofbi2 != ofbi) {
+			dev_err(fbdev->dev, "overlay already in use\n");
+			r = -EINVAL;
+			goto out;
+		}
+	}
+
+	/* detach unused overlays */
+	for (i = 0; i < ofbi->num_overlays; ++i) {
+		int t, found;
+
+		ovl = ofbi->overlays[i];
+
+		found = 0;
+
+		for (t = 0; t < num_ovls; ++t) {
+			if (ovl == ovls[t]) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			continue;
+
+		DBG("detaching %d\n", ofbi->overlays[i]->id);
+
+		owlfb_get_mem_region(ofbi->region);
+
+		owlfb_overlay_enable(ovl, 0);
+
+		if (ovl->manager)
+			ovl->manager->apply(ovl->manager);
+
+		owlfb_put_mem_region(ofbi->region);
+
+		for (t = i + 1; t < ofbi->num_overlays; t++) {
+			ofbi->rotation[t-1] = ofbi->rotation[t];
+			ofbi->overlays[t-1] = ofbi->overlays[t];
+		}
+
+		ofbi->num_overlays--;
+		i--;
+	}
+
+	for (i = 0; i < num_ovls; ++i) {
+		int t, found;
+
+		ovl = ovls[i];
+
+		found = 0;
+
+		for (t = 0; t < ofbi->num_overlays; ++t) {
+			if (ovl == ofbi->overlays[t]) {
+				found = 1;
+				break;
+			}
+		}
+
+		if (found)
+			continue;
+		ofbi->rotation[ofbi->num_overlays] = 0;
+		ofbi->overlays[ofbi->num_overlays++] = ovl;
+
+		added = true;
+	}
+
+	if (added) {
+		owlfb_get_mem_region(ofbi->region);
+
+		r = owlfb_apply_changes(fbi, 0);
+
+		owlfb_put_mem_region(ofbi->region);
+
+		if (r)
+			goto out;
+	}
+
+	r = count;
+out:
+	owlfb_unlock(fbdev);
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_overscan(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owl_dss_device *display = fb2display(fbi);
+	u16 overscan_w ,overscan_h;
+	ssize_t l = 0;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	
+	if(display != NULL && display->driver != NULL && display->driver->get_over_scan){
+		display->driver->get_over_scan(display,&overscan_w ,&overscan_h);
+		l += snprintf(buf + l, PAGE_SIZE - l, "%d,%d\n",overscan_w,overscan_h);
+	}else{
+		l += snprintf(buf + l, PAGE_SIZE - l, "%d,%d\n",0,0);
+	}
+	
+	unlock_fb_info(fbi);
+
+	return l;
+}
+
+static ssize_t store_overscan(struct device *dev,
+		struct device_attribute *attr, const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owl_dss_device *display = fb2display(fbi);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	u32 overscan_w ,overscan_h;
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+	
+	sscanf(buf,"%d,%d",&overscan_w,&overscan_h);
+	
+	if(display != NULL && display->driver != NULL && display->driver->set_over_scan){
+		display->driver->set_over_scan(display,overscan_w ,overscan_h);
+	}
+	
+	owlfb_get_mem_region(ofbi->region);
+	
+	owlfb_apply_changes(fbi, 0);
+	
+	owlfb_put_mem_region(ofbi->region);
+
+	unlock_fb_info(fbi);
+
+	return count;
+}
+
+static ssize_t show_size(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%lu\n", ofbi->region->size);
+}
+
+static ssize_t store_size(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	struct owlfb_device *fbdev = ofbi->fbdev;
+	struct owlfb_mem_region *rg;
+	unsigned long size;
+	int r;
+	int i;
+
+	r = kstrtoul(buf, 0, &size);
+	if (r)
+		return r;
+
+	size = PAGE_ALIGN(size);
+
+	if (!lock_fb_info(fbi))
+		return -ENODEV;
+
+	rg = ofbi->region;
+
+	down_write_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
+
+	if (atomic_read(&rg->map_count)) {
+		r = -EBUSY;
+		goto out;
+	}
+
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		struct owlfb_info *ofbi2 = FB2OFB(fbdev->fbs[i]);
+		int j;
+
+		if (ofbi2->region != rg)
+			continue;
+
+		for (j = 0; j < ofbi2->num_overlays; j++) {
+			struct owl_overlay *ovl;
+			ovl = ofbi2->overlays[j];
+			if (ovl->is_enabled(ovl)) {
+				r = -EBUSY;
+				goto out;
+			}
+		}
+	}
+
+	if (size != ofbi->region->size) {
+		r = owlfb_realloc_fbmem(fbi, size, ofbi->region->type);
+		if (r) {
+			dev_err(dev, "realloc fbmem failed\n");
+			goto out;
+		}
+	}
+
+	r = count;
+out:
+	atomic_dec(&rg->lock_count);
+	up_write(&rg->lock);
+
+	unlock_fb_info(fbi);
+
+	return r;
+}
+
+static ssize_t show_phys(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	short offset = 0; 
+
+	offset += snprintf(buf, PAGE_SIZE, "%0x\n", ofbi->region->paddr);
+	return offset;
+}
+
+static ssize_t show_virt(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct fb_info *fbi = dev_get_drvdata(dev);
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+
+	return snprintf(buf, PAGE_SIZE, "%p\n", ofbi->region->vaddr);
+}
+
+static struct device_attribute owlfb_attrs[] = {
+	__ATTR(mirror_to_hdmi, S_IRUGO | S_IWUSR, show_mirror_to_hdmi, store_mirror_to_hdmi),
+	__ATTR(size, S_IRUGO | S_IWUSR, show_size, store_size),
+	__ATTR(overlays, S_IRUGO | S_IWUSR, show_overlays, store_overlays),
+	__ATTR(overscan, S_IRUGO | S_IWUSR, show_overscan, store_overscan),
+	__ATTR(phys_addr, S_IRUGO, show_phys, NULL),
+	__ATTR(virt_addr, S_IRUGO, show_virt, NULL),
+};
+
+int owlfb_create_sysfs(struct owlfb_device *fbdev)
+{
+	int i;
+	int r;
+
+	DBG("create sysfs for fbs\n");
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		int t;
+		for (t = 0; t < ARRAY_SIZE(owlfb_attrs); t++) {
+			r = device_create_file(fbdev->fbs[i]->dev,
+					&owlfb_attrs[t]);
+
+			if (r) {
+				dev_err(fbdev->dev, "failed to create sysfs "
+						"file\n");
+				return r;
+			}
+			
+			#ifdef CONFIG_FB_DEFAULT_MIRROR_TO_HDMI
+			store_mirror_to_hdmi(fbdev->fbs[i]->dev,
+						&owlfb_attrs[0], "1", sizeof("1"));			
+			#endif
+		}
+	}
+
+	return 0;
+}
+
+void owlfb_remove_sysfs(struct owlfb_device *fbdev)
+{
+	int i, t;
+
+	DBG("remove sysfs for fbs\n");
+	for (i = 0; i < fbdev->num_fbs; i++) {
+		for (t = 0; t < ARRAY_SIZE(owlfb_attrs); t++)
+			device_remove_file(fbdev->fbs[i]->dev,
+					&owlfb_attrs[t]);
+	}
+}
+
diff --git a/drivers/video/fbdev/owl/fb/owlfb.h b/drivers/video/fbdev/owl/fb/owlfb.h
new file mode 100755
index 0000000..d213399
--- /dev/null
+++ b/drivers/video/fbdev/owl/fb/owlfb.h
@@ -0,0 +1,228 @@
+/*
+ * linux/drivers/video/fbdev/owl/owlfb.h
+ *
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * Some code and ideas taken from drivers/video/fbdev/owl/ driver
+ * by leopard.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __DRIVERS_VIDEO_OWL2_OWLFB_H__
+#define __DRIVERS_VIDEO_OWL2_OWLFB_H__
+
+#ifdef CONFIG_FB_OWL2_DEBUG_SUPPORT
+#define DEBUG
+#endif
+
+#include <linux/rwsem.h>
+
+#include <video/owldss.h>
+
+#define DEBUGx
+
+#ifdef DEBUG
+extern bool owlfb_debug;
+#define DBG(format, ...) \
+	do { \
+		if (owlfb_debug) \
+			printk(KERN_ERR "OWLFB: " format, ## __VA_ARGS__); \
+	} while (0)
+#else
+#define DBG(format, ...)
+#endif
+
+#define FB2OFB(fb_info) ((struct owlfb_info *)(fb_info->par))
+
+/* max number of overlays to which a framebuffer data can be direct */
+#define OWLFB_NUM_FBS        2
+#define OWLFB_MAX_OVL_PER_FB 3
+#define OWLFB_NUM_BUFFERS_PER_FB 2
+
+#define OWLFB_BUFFERS_MAX_XRES 1920
+#define OWLFB_BUFFERS_MAX_YRES 1080
+
+#define OWLFB_MAX_OVL_MEM_RESERVE_PER_OVL  (2048 * 2048 * 3 / 2)
+#define OWLFB_MAX_OVL_MEM_RESERVE_NUM  1
+#define OWLFB_MAX_CURSOR_MEM_RESERVE  (64 * 64 * 4)
+#define OWLFB_CURSOR_OVL_ID 3
+struct owlfb_mem_region {
+	int             id;
+	u32		paddr;
+	void __iomem	*vaddr;
+
+	unsigned long	size;
+	u8		type;		/* OWLFB_PLANE_MEM_* */
+	bool		alloc;		/* allocated by the driver */
+	bool		map;		/* kernel mapped by the driver */
+	atomic_t	map_count;
+	struct rw_semaphore lock;
+	atomic_t	lock_count;
+};
+
+/* appended to fb_info */
+struct owlfb_info {
+	int id;
+	struct owlfb_mem_region *region;
+	u32 overlay_mem_base;
+	u32 overlay_free_mem_off;
+	u32 overlay_free_mem_size;	
+	int num_overlays;
+	int used_overlay_mask;
+	struct owl_overlay_manager * manager;
+	struct owl_overlay *overlays[OWLFB_MAX_OVL_PER_FB];
+	struct owlfb_device *fbdev;
+	u8 rotation[OWLFB_MAX_OVL_PER_FB];
+	bool mirror_to_hdmi;
+};
+
+struct owlfb_display_data {
+	struct owlfb_device *fbdev;
+	struct owl_dss_device *dssdev;
+	u8 bpp_override;
+	bool connected;
+};
+
+struct owlfb_device {
+	struct device *dev;
+	struct mutex  mtx;
+	int mirror_fb_id;
+
+	u32 pseudo_palette[17];
+
+	int state;
+
+	unsigned num_fbs;
+	struct fb_info *fbs[10];
+	struct owlfb_mem_region regions[10];
+
+	unsigned num_displays;
+	struct owlfb_display_data displays[10];
+	unsigned num_overlays;
+	struct owl_overlay *overlays[10];
+	unsigned num_managers;
+	struct owl_overlay_manager *managers[10];
+
+	struct workqueue_struct *auto_update_wq;
+	
+	struct owl_dss_device *def_display;
+	
+	int xres;
+	int yres;
+	int bpp;
+	int refresh;
+	
+};
+
+struct owlfb_colormode {
+	enum owl_color_mode dssmode;
+	u32 bits_per_pixel;
+	u32 nonstd;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+};
+
+void set_fb_fix(struct fb_info *fbi);
+int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var);
+int owlfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type);
+int owlfb_apply_changes(struct fb_info *fbi, int init);
+
+int owlfb_create_sysfs(struct owlfb_device *fbdev);
+void owlfb_remove_sysfs(struct owlfb_device *fbdev);
+
+int owlfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
+
+int owlfb_update_window(struct fb_info *fbi,
+		u32 x, u32 y, u32 w, u32 h);
+
+int dss_mode_to_fb_mode(enum owl_color_mode dssmode,
+			struct fb_var_screeninfo *var);
+
+int owlfb_setup_overlay(struct fb_info *fbi, struct owl_overlay *ovl,
+		u16 posx, u16 posy, u16 outw, u16 outh);
+
+void owlfb_start_auto_update(struct owlfb_device *fbdev,
+		struct owl_dss_device *display);
+void owlfb_stop_auto_update(struct owlfb_device *fbdev,
+		struct owl_dss_device *display);
+int owlfb_get_update_mode(struct fb_info *fbi, enum owlfb_update_mode *mode);
+int owlfb_set_update_mode(struct fb_info *fbi, enum owlfb_update_mode mode);
+int owlfb_free_all_fbmem_after_dc(struct owlfb_device *fbdev);
+int owlfb_dc_init(struct owlfb_device *fbdev);
+
+/* find the display connected to this fb, if any */
+static inline struct owl_dss_device *fb2display(struct fb_info *fbi)
+{
+	struct owlfb_info *ofbi = FB2OFB(fbi);
+	int i;
+
+	/* XXX: returns the display connected to first attached overlay */
+	for (i = 0; i < ofbi->num_overlays; i++) {
+		if (ofbi->overlays[i]->manager)
+			return ofbi->overlays[i]->manager->device;
+	}
+
+	return NULL;
+}
+
+static inline struct owlfb_display_data *get_display_data(
+		struct owlfb_device *fbdev, struct owl_dss_device *dssdev)
+{
+	int i;
+
+	for (i = 0; i < fbdev->num_displays; ++i)
+		if (fbdev->displays[i].dssdev == dssdev)
+			return &fbdev->displays[i];
+
+	/* This should never happen */
+	BUG();
+}
+
+static inline void owlfb_lock(struct owlfb_device *fbdev)
+{
+	mutex_lock(&fbdev->mtx);
+}
+
+static inline void owlfb_unlock(struct owlfb_device *fbdev)
+{
+	mutex_unlock(&fbdev->mtx);
+}
+
+static inline int owlfb_overlay_enable(struct owl_overlay *ovl,
+		int enable)
+{
+	if (enable)
+		return ovl->enable(ovl);
+	else
+		return ovl->disable(ovl);
+}
+
+static inline struct owlfb_mem_region *
+owlfb_get_mem_region(struct owlfb_mem_region *rg)
+{
+	down_read_nested(&rg->lock, rg->id);
+	atomic_inc(&rg->lock_count);
+	return rg;
+}
+
+static inline void owlfb_put_mem_region(struct owlfb_mem_region *rg)
+{
+	atomic_dec(&rg->lock_count);
+	up_read(&rg->lock);
+}
+
+#endif
diff --git a/drivers/video/fbdev/owl/switch/Kconfig b/drivers/video/fbdev/owl/switch/Kconfig
new file mode 100644
index 0000000..19404b6
--- /dev/null
+++ b/drivers/video/fbdev/owl/switch/Kconfig
@@ -0,0 +1,15 @@
+menuconfig SWITCH
+	tristate "Switch class support"
+	help
+	  Say Y here to enable switch class support. This allows
+	  monitoring switches by userspace via sysfs and uevent.
+
+if SWITCH
+
+config SWITCH_GPIO
+	tristate "GPIO Swith support"
+	depends on GPIOLIB
+	help
+	  Say Y here to enable GPIO based switch support.
+
+endif # SWITCH
diff --git a/drivers/video/fbdev/owl/switch/Makefile b/drivers/video/fbdev/owl/switch/Makefile
new file mode 100644
index 0000000..f7606ed
--- /dev/null
+++ b/drivers/video/fbdev/owl/switch/Makefile
@@ -0,0 +1,4 @@
+# Switch Class Driver
+obj-$(CONFIG_SWITCH)		+= switch_class.o
+obj-$(CONFIG_SWITCH_GPIO)	+= switch_gpio.o
+
diff --git a/drivers/video/fbdev/owl/switch/switch_class.c b/drivers/video/fbdev/owl/switch/switch_class.c
new file mode 100644
index 0000000..3ee9832
--- /dev/null
+++ b/drivers/video/fbdev/owl/switch/switch_class.c
@@ -0,0 +1,174 @@
+/*
+ *  drivers/switch/switch_class.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood at android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/err.h>
+#include <mach/switch.h>
+
+struct class *switch_class;
+static atomic_t device_count;
+
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct switch_dev *sdev = (struct switch_dev *)
+		dev_get_drvdata(dev);
+
+	if (sdev->print_state) {
+		int ret = sdev->print_state(sdev, buf);
+		if (ret >= 0)
+			return ret;
+	}
+	return sprintf(buf, "%d\n", sdev->state);
+}
+
+static ssize_t name_show(struct device *dev, struct device_attribute *attr,
+		char *buf)
+{
+	struct switch_dev *sdev = (struct switch_dev *)
+		dev_get_drvdata(dev);
+
+	if (sdev->print_name) {
+		int ret = sdev->print_name(sdev, buf);
+		if (ret >= 0)
+			return ret;
+	}
+	return sprintf(buf, "%s\n", sdev->name);
+}
+
+static DEVICE_ATTR(state, S_IRUGO, state_show, NULL);
+static DEVICE_ATTR(name, S_IRUGO, name_show, NULL);
+
+void switch_set_state(struct switch_dev *sdev, int state)
+{
+	char name_buf[120];
+	char state_buf[120];
+	char *prop_buf;
+	char *envp[3];
+	int env_offset = 0;
+	int length;
+
+	if (sdev->state != state) {
+		sdev->state = state;
+
+		prop_buf = (char *)get_zeroed_page(GFP_KERNEL);
+		if (prop_buf) {
+			length = name_show(sdev->dev, NULL, prop_buf);
+			if (length > 0) {
+				if (prop_buf[length - 1] == '\n')
+					prop_buf[length - 1] = 0;
+				snprintf(name_buf, sizeof(name_buf),
+					"SWITCH_NAME=%s", prop_buf);
+				envp[env_offset++] = name_buf;
+			}
+			length = state_show(sdev->dev, NULL, prop_buf);
+			if (length > 0) {
+				if (prop_buf[length - 1] == '\n')
+					prop_buf[length - 1] = 0;
+				snprintf(state_buf, sizeof(state_buf),
+					"SWITCH_STATE=%s", prop_buf);
+				envp[env_offset++] = state_buf;
+			}
+			envp[env_offset] = NULL;
+			kobject_uevent_env(&sdev->dev->kobj, KOBJ_CHANGE, envp);
+			free_page((unsigned long)prop_buf);
+		} else {
+			printk(KERN_ERR "out of memory in switch_set_state\n");
+			kobject_uevent(&sdev->dev->kobj, KOBJ_CHANGE);
+		}
+	}
+}
+EXPORT_SYMBOL_GPL(switch_set_state);
+
+static int create_switch_class(void)
+{
+	if (!switch_class) {
+		switch_class = class_create(THIS_MODULE, "switch");
+		if (IS_ERR(switch_class))
+			return PTR_ERR(switch_class);
+		atomic_set(&device_count, 0);
+	}
+
+	return 0;
+}
+
+int switch_dev_register(struct switch_dev *sdev)
+{
+	int ret;
+
+	if (!switch_class) {
+		ret = create_switch_class();
+		if (ret < 0)
+			return ret;
+	}
+
+	sdev->index = atomic_inc_return(&device_count);
+	sdev->dev = device_create(switch_class, NULL,
+		MKDEV(0, sdev->index), NULL, sdev->name);
+	if (IS_ERR(sdev->dev))
+		return PTR_ERR(sdev->dev);
+
+	ret = device_create_file(sdev->dev, &dev_attr_state);
+	if (ret < 0)
+		goto err_create_file_1;
+	ret = device_create_file(sdev->dev, &dev_attr_name);
+	if (ret < 0)
+		goto err_create_file_2;
+
+	dev_set_drvdata(sdev->dev, sdev);
+	sdev->state = 0;
+	return 0;
+
+err_create_file_2:
+	device_remove_file(sdev->dev, &dev_attr_state);
+err_create_file_1:
+	device_destroy(switch_class, MKDEV(0, sdev->index));
+	printk(KERN_ERR "switch: Failed to register driver %s\n", sdev->name);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(switch_dev_register);
+
+void switch_dev_unregister(struct switch_dev *sdev)
+{
+	device_remove_file(sdev->dev, &dev_attr_name);
+	device_remove_file(sdev->dev, &dev_attr_state);
+	device_destroy(switch_class, MKDEV(0, sdev->index));
+	dev_set_drvdata(sdev->dev, NULL);
+}
+EXPORT_SYMBOL_GPL(switch_dev_unregister);
+
+static int __init switch_class_init(void)
+{
+	return create_switch_class();
+}
+
+static void __exit switch_class_exit(void)
+{
+	class_destroy(switch_class);
+}
+
+module_init(switch_class_init);
+module_exit(switch_class_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood at android.com>");
+MODULE_DESCRIPTION("Switch class driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/switch/switch_gpio.c b/drivers/video/fbdev/owl/switch/switch_gpio.c
new file mode 100644
index 0000000..6f837ea
--- /dev/null
+++ b/drivers/video/fbdev/owl/switch/switch_gpio.c
@@ -0,0 +1,172 @@
+/*
+ *  drivers/switch/switch_gpio.c
+ *
+ * Copyright (C) 2008 Google, Inc.
+ * Author: Mike Lockwood <lockwood at android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <mach/switch.h>
+#include <linux/workqueue.h>
+#include <linux/gpio.h>
+
+struct gpio_switch_data {
+	struct switch_dev sdev;
+	unsigned gpio;
+	const char *name_on;
+	const char *name_off;
+	const char *state_on;
+	const char *state_off;
+	int irq;
+	struct work_struct work;
+};
+
+static void gpio_switch_work(struct work_struct *work)
+{
+	int state;
+	struct gpio_switch_data	*data =
+		container_of(work, struct gpio_switch_data, work);
+
+	state = gpio_get_value(data->gpio);
+	switch_set_state(&data->sdev, state);
+}
+
+static irqreturn_t gpio_irq_handler(int irq, void *dev_id)
+{
+	struct gpio_switch_data *switch_data =
+	    (struct gpio_switch_data *)dev_id;
+
+	schedule_work(&switch_data->work);
+	return IRQ_HANDLED;
+}
+
+static ssize_t switch_gpio_print_state(struct switch_dev *sdev, char *buf)
+{
+	struct gpio_switch_data	*switch_data =
+		container_of(sdev, struct gpio_switch_data, sdev);
+	const char *state;
+	if (switch_get_state(sdev))
+		state = switch_data->state_on;
+	else
+		state = switch_data->state_off;
+
+	if (state)
+		return sprintf(buf, "%s\n", state);
+	return -1;
+}
+
+static int gpio_switch_probe(struct platform_device *pdev)
+{
+	struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_switch_data *switch_data;
+	int ret = 0;
+
+	if (!pdata)
+		return -EBUSY;
+
+	switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
+	if (!switch_data)
+		return -ENOMEM;
+
+	switch_data->sdev.name = pdata->name;
+	switch_data->gpio = pdata->gpio;
+	switch_data->name_on = pdata->name_on;
+	switch_data->name_off = pdata->name_off;
+	switch_data->state_on = pdata->state_on;
+	switch_data->state_off = pdata->state_off;
+	switch_data->sdev.print_state = switch_gpio_print_state;
+
+	ret = switch_dev_register(&switch_data->sdev);
+	if (ret < 0)
+		goto err_switch_dev_register;
+
+	ret = gpio_request(switch_data->gpio, pdev->name);
+	if (ret < 0)
+		goto err_request_gpio;
+
+	ret = gpio_direction_input(switch_data->gpio);
+	if (ret < 0)
+		goto err_set_gpio_input;
+
+	INIT_WORK(&switch_data->work, gpio_switch_work);
+
+	switch_data->irq = gpio_to_irq(switch_data->gpio);
+	if (switch_data->irq < 0) {
+		ret = switch_data->irq;
+		goto err_detect_irq_num_failed;
+	}
+
+	ret = request_irq(switch_data->irq, gpio_irq_handler,
+			  IRQF_TRIGGER_LOW, pdev->name, switch_data);
+	if (ret < 0)
+		goto err_request_irq;
+
+	/* Perform initial detection */
+	gpio_switch_work(&switch_data->work);
+
+	return 0;
+
+err_request_irq:
+err_detect_irq_num_failed:
+err_set_gpio_input:
+	gpio_free(switch_data->gpio);
+err_request_gpio:
+	switch_dev_unregister(&switch_data->sdev);
+err_switch_dev_register:
+	kfree(switch_data);
+
+	return ret;
+}
+
+static int gpio_switch_remove(struct platform_device *pdev)
+{
+	struct gpio_switch_data *switch_data = platform_get_drvdata(pdev);
+
+	cancel_work_sync(&switch_data->work);
+	gpio_free(switch_data->gpio);
+	switch_dev_unregister(&switch_data->sdev);
+	kfree(switch_data);
+
+	return 0;
+}
+
+static struct platform_driver gpio_switch_driver = {
+	.probe		= gpio_switch_probe,
+	.remove		= gpio_switch_remove,
+	.driver		= {
+		.name	= "switch-gpio",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init gpio_switch_init(void)
+{
+	return platform_driver_register(&gpio_switch_driver);
+}
+
+static void __exit gpio_switch_exit(void)
+{
+	platform_driver_unregister(&gpio_switch_driver);
+}
+
+module_init(gpio_switch_init);
+module_exit(gpio_switch_exit);
+
+MODULE_AUTHOR("Mike Lockwood <lockwood at android.com>");
+MODULE_DESCRIPTION("GPIO Switch driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/vce/Kconfig b/drivers/video/fbdev/owl/vce/Kconfig
new file mode 100755
index 0000000..cdb58ae
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/Kconfig
@@ -0,0 +1,11 @@
+config VIDEO_ACTIONS_VCE
+	tristate "Asoc Video encoder support"
+	depends on ARCH_OWL
+	---help---
+	  Say Y here if you need video recoder support to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vce_drv.ko.
+
diff --git a/drivers/video/fbdev/owl/vce/Makefile b/drivers/video/fbdev/owl/vce/Makefile
new file mode 100755
index 0000000..8b00b17
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIDEO_ACTIONS_VCE) += vce_drv.o
+
diff --git a/drivers/video/fbdev/owl/vce/readme.txt b/drivers/video/fbdev/owl/vce/readme.txt
new file mode 100755
index 0000000..70c4058
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/readme.txt
@@ -0,0 +1,11 @@
+\B4\FA\C2\EB\B7\C5\D4\DAgl5202\gs702a\leopard\platform\drivers\\CF\C2\C3\E6
+
+#make vce_ko
+
+\BF\C9\CAֶ\AF\D4\DA\D6ն\CB\D6\D0\C7\C3
+insmod /lib/modules/vce_drv.ko
+
+#\BD\F8\C8\EB\D6ն˺\F3\A3\AC\C7\C3
+mdev -s
+
+\BC\B4\BF\C9
\ No newline at end of file
diff --git a/drivers/video/fbdev/owl/vce/vce_drv.c b/drivers/video/fbdev/owl/vce/vce_drv.c
new file mode 100755
index 0000000..7af5c39
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/vce_drv.c
@@ -0,0 +1,1616 @@
+#include <linux/platform_device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/kernel.h>   /* pr_err() */
+#include <linux/errno.h>    /* error codes */
+#include <linux/vmalloc.h>
+#include <linux/init.h>     /* module_init/module_exit */
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h> /*#include <asm/uaccess.h>*/
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/sched.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <mach/powergate.h>
+#include <mach/module-owl.h>
+#include <mach/clkname.h>
+#include "vce_drv.h"
+#include "vce_reg.h"
+
+#define DEVDRV_NAME_VCE      "vce"       /*device_driver.h*/
+#define DEVICE_VCE           "/dev/vce"  /*major.h*/
+#define MINOR_VCE        32
+#define _MAX_HANDLES_ 1024
+#define IRQ_VCE OWL_IRQ_H264_JPEG_ENCODER/*81*/
+#define WAIT_TIMEOUT HZ  /*1s <--> HZ*/
+#define WAIT_TIMEOUT_MS  3000 /*ms*/
+#define VCE_DEFAULT_WIDTH   320
+#define VCE_DEFAULT_HEIGHT  240
+#define VCE_DEFAULT_FREQ    240/*MHZ*/
+#define IC_TYPE_ATM7039	 0x7039
+#define IC_TYPE_ATM7021	 0x7021
+//#define VOL_INIT 975000
+//#define VOL_RUG 1050000
+/*wurui: raise 0.05v for dcdc voltage precision distance*/
+#define VOL_INIT 1050000
+#define VOL_RUG 1125000
+#define VOL_MAX 1200000
+
+
+#define PUT_USER          put_user
+#define GET_USER          get_user
+#define GET_USER_STRUCT   copy_from_user
+#define SET_USER_STRUCT   copy_to_user
+
+#define Enable_More_PrintK 0  /*show more print*/
+#define Enable_Debug_PrintK  0 /*check register*/
+#if Enable_More_PrintK
+#define vce_info(fmt, ...)  printk("vce_drv: " fmt, ## __VA_ARGS__);
+#else
+#define vce_info(fmt, ...)  {}
+#endif
+#define vce_warning(fmt, ...) printk(KERN_WARNING"vce_drv: warning: " fmt, ## __VA_ARGS__)    
+#define vce_err(fmt, ...) printk(KERN_ERR "vce_drv: %s(L%d) error: " fmt, __func__, __LINE__, ## __VA_ARGS__)
+
+/*
+ SPS_PG_CTL,b4 VCE&BISP&AISP power on enable
+ SPS_PG_ACK,b4 VCE&BISP&AISP power on enable
+ CMU_VCECLK
+ CMU_DEVCLKEN0 bit26 VCE interface clock enable
+ */
+/*sram\B5Ŀ\D8\D6\C6Ȩ*/
+#define Share_Mem_REG      0xB0240004
+/*ʵ\CF\D6 Reset*/
+/*#define CMU_DEVRST0     (0xB0160000 + 0xA8)*/ /*redefined*/
+#define VCE_RESET          0x00100000
+/*ʵ\CF\D6power gating*/
+/*#define SPS_PG_CTL       0xB01B0100*/         /*redefined*/
+#define VCE_BISP_POWERON   0x00000002
+#define SPS_PG_ACK         0xB01B0100
+/*ʵ\CF\D6clk\C7л\BB\B5\BDvce\D6\D0*/
+#define VCE_CLKEN  	       0x04000000
+/*#define CMU_DEVCLKEN0    (0xB0160000 + 0xA0)*/ /*redefined*/
+/*CMU_VCECLKѡ\D4\F1ʱ\D6\D3Դ\BA\CD\C9\E8\D6÷\D6Ƶ\CA\FD*/
+/*#define  CMU_DEVPLL      (0xB0160000 + 0x04)*/  /*redefined*/
+/*#define  CMU_DDRPLL      (0xB0160000 + 0x08)*/  /*redefined*/
+/*#define  CMU_DISPLAYPLL  (0xB0160000 + 0x10)*/  /*redefined*/
+/*#define  CMU_VCECLK      (0xB0160000 + 0x44)*/  /*redefined*/
+
+enum {
+	STOPED,
+	RUNNING,
+	ERR,
+};
+
+typedef struct{
+	vce_input_t  vce_in;
+	vce_output_t vce_out;
+	unsigned int vce_count;
+	unsigned int vce_status;
+}vce_info_t;
+
+static DEFINE_MUTEX(vce_ioctl_mutex);
+static DEFINE_MUTEX(vce_reset_mutex);
+static struct completion vce_complete;
+static int vce_status = 0;
+static int vce_irq_registered = 0;
+static int vce_open_count = 0;
+static int vce_last_handle = 0;
+static void *pAbuf[_MAX_HANDLES_];
+static int vce_clk_isEnable = 0;
+static vce_multi_freq_t vce_freq_multi = {VCE_DEFAULT_WIDTH,VCE_DEFAULT_HEIGHT,VCE_DEFAULT_FREQ}; 
+static int vce_freq_is_init = 0;   
+static int vce_resumed_flag = 0;
+static wait_queue_head_t vce_wait;
+static int gPownOnOffCount = 0;
+static unsigned int gVceStatus = 0;
+static int ic_type = IC_TYPE_ATM7021;
+static unsigned int irq_vce = -1;
+static unsigned long iobase_vce = 0;  /*VCE_BASE_ADDR*/
+static unsigned long iobase_sram = 0; /*Share_Mem_REG*/
+static unsigned long iobase_cmu_devclken0  = 0;  /*CMU_DEVCLKEN0*/
+static unsigned long iobase_sps_pg_ctl     = 0;  /*SPS_PG_CTL*/
+static struct regulator *power = NULL;/*voltage regulation*/
+
+#if Enable_Debug_PrintK
+static unsigned long iobase_cmu_devrst0    = 0;  /*CMU_DEVRST0*/
+static unsigned long iobase_cmu_vceclk     = 0;  /*CMU_VCECLK*/
+static unsigned long iobase_sps_pg_ack     = 0;  /*SPS_PG_ACK*/ 
+static unsigned long iobase_cmu_devpll     = 0;  /*CMU_DEVPLL*/ 
+static unsigned long iobase_cmu_ddrpll     = 0;  /*CMU_DDRPLL*/ 
+static unsigned long iobase_cmu_displaypll = 0;  /*CMU_DISPLAYPLL*/ 
+#endif
+
+static void *vce_malloc(int32_t size)
+{
+	return kzalloc(size, GFP_KERNEL | GFP_DMA);
+}
+
+static void vce_free(void *ptr)
+{
+	kfree(ptr);
+	ptr = NULL;
+}
+
+static unsigned int Re_Reg(unsigned int reg)
+{
+	unsigned int value = readl((void*)(iobase_vce + reg));
+	return value;
+}
+
+static void Wr_Reg(unsigned int reg, unsigned int value)
+{
+	writel(value, (void*)(iobase_vce + reg));
+}
+
+static unsigned int Re_Reg_Self(unsigned long reg)
+{
+	unsigned int value = readl((void*)(reg));
+	return value;
+}
+
+static void Wr_Reg_Self(unsigned long reg, unsigned int value)
+{
+	writel(value, (void*)(reg));
+}
+
+static int query_status(void)
+{
+	int ret_value = 0;
+	int vce_status = Re_Reg(VCE_STATUS);
+	gVceStatus = vce_status;
+
+	if ((vce_status & 0x1) && ((vce_status & 0x100) == 0)){
+		ret_value = VCE_BUSY;/*codec is runing*/		
+	}
+	else if (((vce_status & 0x1) == 0) && (vce_status & 0x100) &&(vce_status & 0x1000)){
+		ret_value = VCE_READY;
+	}
+	else if (((vce_status & 0x1) == 0) && ((vce_status & 0x100) == 0)){
+		ret_value = VCE_IDLE;
+	}
+	else if ((vce_status & 0x100) && (vce_status & 0x8000)){
+		ret_value = VCE_ERR_STM_FULL;
+	}
+	else if ((vce_status & 0x100) && (vce_status & 0x10000)){
+		ret_value = VCE_ERR_STM;
+	}
+	else if ((vce_status & 0x100) && (vce_status & 0x40000)){
+		ret_value = VCE_ERR_TIMEOUT;
+	}
+	return ret_value;
+}
+
+static void vce_reset(void)
+{
+	vce_info("vce_reset\n");
+	module_reset(MOD_ID_VCE);
+}
+
+static void vce_stop(void)
+{
+	if (owl_powergate_is_powered(OWL_POWERGATE_VCE_BISP)) {
+		int i = 0x10000000;
+		while ((VCE_BUSY == query_status())) {
+			mdelay(1);
+			if (i-- < 0)
+				break;
+			vce_err("OWL_POWERGATE_VCE_BISP is PownOn when VCE_BUSY\n");
+		}
+	}
+}
+
+static void vce_power_on(void)
+{
+	vce_info("vce_power_on in\n");
+	vce_stop();
+
+	if (owl_powergate_is_powered(OWL_POWERGATE_VCE_BISP)){
+		vce_info("OWL_POWERGATE_VCE_BISP is PownOn\n");
+	}
+
+	owl_powergate_power_on(OWL_POWERGATE_VCE_BISP);
+
+	gPownOnOffCount++;
+	vce_info("vce_power_on out %d\n", gPownOnOffCount);
+}
+
+static void vce_power_off(void)
+{
+	vce_info("vce_power_off in\n");
+	if (owl_powergate_is_powered(OWL_POWERGATE_VCE_BISP)) {
+		vce_info("OWL_POWERGATE_VCE_BISP is PownOn\n");
+	}
+
+	owl_powergate_power_off(OWL_POWERGATE_VCE_BISP);
+	gPownOnOffCount--;
+	vce_info("vce_power_off out %d\n", gPownOnOffCount);
+}
+
+#if 0
+static void vce_drv_cfg(void)
+{
+	vce_info("vce_drv_cfg in\n");
+	unsigned int value;
+
+	value = Re_Reg_Self(iobase_cmu_devrst0);
+	value = value & (~VCE_RESET);
+	Wr_Reg_Self(iobase_cmu_devrst0, value);
+
+	value = Re_Reg_Self(iobase_cmu_devclken0);
+	value = value | VCE_CLKEN;
+	Wr_Reg_Self(iobase_cmu_devclken0, value);
+
+	value = Re_Reg_Self(iobase_sps_pg_ctl);
+	value = value | VCE_BISP_POWERON;
+	Wr_Reg_Self(iobase_sps_pg_ctl, value);
+
+loop: value = Re_Reg_Self(iobase_sps_pg_ack);
+	value = value & VCE_BISP_POWERON;
+	if (value == 0)
+		goto loop;
+
+	value = Re_Reg_Self(iobase_cmu_devrst0);
+	value = value | VCE_RESET;
+	Wr_Reg_Self(iobase_cmu_devrst0, value);
+
+	value = 0x2;
+	Wr_Reg_Self(iobase_cmu_vceclk, value);
+	vce_info("vce_drv_cfg out\n");
+}
+
+static void vce_drv_cfg_close(void)
+{
+	unsigned int value;
+	value = Re_Reg_Self(iobase_sps_pg_ctl);
+	value = value & (~VCE_BISP_POWERON);
+	Wr_Reg_Self(iobase_sps_pg_ctl, value);
+}
+#endif
+
+static void share_mem_reg_enable(void)
+{
+	if(ic_type == IC_TYPE_ATM7039)
+	{
+		unsigned int value;
+		value = Re_Reg_Self(iobase_sram);
+		value = value | 0x2;
+		Wr_Reg_Self(iobase_sram, value);
+	}	
+}
+
+static void share_mem_reg_disable(void)
+{
+	if(ic_type == IC_TYPE_ATM7039)
+	{
+		unsigned int value;
+		value = Re_Reg_Self(iobase_sram);
+		value = value & (~0x2);
+		Wr_Reg_Self(iobase_sram, value);
+	}
+}
+
+static void vce_clk_enable(void)
+{
+#if 1
+	struct clk *vce_clk;
+	/*vce reset should be prior to vce clk enable , or vce may work abnormally*/
+	vce_power_on();	
+	if ((vce_open_count == 1) || (vce_resumed_flag == 1)) {
+		vce_reset();
+	}
+	module_clk_enable(MOD_ID_VCE);
+	vce_clk = clk_get_sys(NULL, CLKNAME_VCE_CLK);
+	if (IS_ERR(vce_clk)) {
+		vce_err("clk_get_sys(NULL, CLKNAME_VCE_CLK) failed\n");
+		return;
+	}
+	clk_prepare(vce_clk);
+	clk_enable(vce_clk);
+#else
+	vce_drv_cfg();
+#endif
+    vce_clk_isEnable = 1;
+}
+
+static void vce_clk_disable(void)
+{
+#if 1
+	struct clk *vce_clk;
+	vce_clk = clk_get_sys(NULL, CLKNAME_VCE_CLK);
+	if (IS_ERR(vce_clk)) {
+		vce_err("clk_get_sys(NULL,CLKNAME_VCE_CLK) failed\n");
+		return;
+	}	
+	clk_disable(vce_clk);	
+	clk_unprepare(vce_clk);
+	
+	if (vce_open_count == 0) {		
+		module_clk_disable(MOD_ID_VCE);
+	}	
+	vce_power_off();
+#else
+	vce_drv_cfg_close();
+#endif
+    vce_clk_isEnable = 0;
+}
+
+/*================== \B5\F7Ƶ\CF\E0\B9\D8  =================*/
+/* \C9\E8\D6\C3vceƵ\C2ʣ\AC\B7\B5\BB\D8ʵ\BC\CA\C9\E8\D6óɹ\A6\B5\C4Ƶ\C2ʵ㣬\B7\B5\BB\D8-1\B1\EDʾ\C9\E8\D6\C3ʧ\B0ܣ\BB*/
+static unsigned long  vce_setFreq(vce_multi_freq_t*  freq_MHz) 
+{
+	static struct clk *vce_clk;
+	unsigned long rate, new_rate = freq_MHz->freq;
+	unsigned int voltage;
+	int ret;
+
+	vce_info("width:%d  height:%d freq:%d\n",
+	freq_MHz->width, freq_MHz->height, (int) freq_MHz->freq);
+
+	if (new_rate > 500) {
+		vce_err("cannot set vce freq to : %ld MHz\n",new_rate);
+		return -1;
+	}
+
+	if (vce_clk_isEnable == 0)
+		vce_warning("vce clk is not enable yet\n");
+
+	vce_clk = clk_get_sys(NULL, CLKNAME_VCE_CLK);
+	if (IS_ERR(vce_clk)) {
+		vce_err("clk_get_sys(NULL,CLKNAME_VCE_CLK) failed\n");
+		return -1;
+	}
+
+	rate = clk_get_rate(vce_clk);/*\BB\F1ȡclk\B5\B1ǰƵ\C2\CAhz\A3\AC\C8\E7hosc\A3\BA24000000*/
+	if (rate == new_rate * 1000 * 1000) {
+		vce_info("requested rate (%ld Mhz)is the same as the current rate,do nothing\n",new_rate);
+		return new_rate;
+	}
+
+	if ((vce_open_count > 1) && (vce_freq_is_init == 1)) {
+		if (freq_MHz->width * freq_MHz->height <
+			vce_freq_multi.width * vce_freq_multi.height) {
+			vce_info("multi instance, vce freq %ld MHz force to %ld MH!\n",new_rate, vce_freq_multi.freq);
+			new_rate = vce_freq_multi.freq;
+		} else {
+			vce_info("multi instance, vce freq %ld MHz\n",new_rate);
+			vce_freq_multi.width = freq_MHz->width;
+			vce_freq_multi.height = freq_MHz->height;
+			vce_freq_multi.freq = new_rate;
+		}
+	} else {
+		vce_freq_multi.width = freq_MHz->width;
+		vce_freq_multi.height = freq_MHz->height;
+		vce_freq_multi.freq = new_rate;
+		vce_freq_is_init = 1;
+	}
+
+	if(!IS_ERR(power))
+	{
+		/*720p/1280p \B5\F7ѹ*/
+		if (vce_freq_multi.width * vce_freq_multi.height >= 1280*720)
+	    {
+			voltage=VOL_RUG;	  	
+	    }
+		else
+		{
+			voltage=VOL_INIT;
+		}
+		if(regulator_set_voltage(power, voltage, VOL_MAX))
+		{
+	        vce_err("cannot set corevdd to %duV !\n", voltage);
+	        return -1;
+	    }
+		vce_info("voltage regulator is ok!,to %duV.\n",voltage);
+	}
+	
+	/*ͨ\B9\FDround rate \D5ҵ\BD\D3\EB\C9\E8\D6\C3Ƶ\C2\CA\D7\EE\BDӽ\FC\B5\C4Ƶ\C2\CA*/
+	rate = clk_round_rate(vce_clk, new_rate*1000*1000);	
+	if (rate > 0) {		
+		ret = clk_set_rate(vce_clk, rate); /*\C9\E8\D6\C3clkƵ\C2\CAhz*/		
+		if (ret != 0) {			
+			vce_err("clk_set_rate failed\n");
+			return -1;
+		}		
+	}
+
+	rate = clk_get_rate(vce_clk); /*\BB\F1ȡclk\B5\B1ǰƵ\C2\CAhz\A3\AC\C8\E7hosc\A3\BA24000000*/
+	vce_info("new rate (%ld MHz) is set\n",rate / (1000*1000));
+
+	return rate / (1000 * 1000);
+}
+
+/* \B7\B5\BB\D8vceƵ\C2ʣ\AC\B7\B5\BB\D80\B1\EDʾʧ\B0\DC*/
+static unsigned long vce_getFreq(void)
+{
+
+	static struct clk *vce_clk;
+	unsigned long rate;
+
+	if(vce_clk_isEnable == 0) {
+		vce_warning("vce clk is not enable yet\n");
+	}
+	/*\B8\F9\BE\DDclk_name\BB\F1ȡclk\BDṹ\CC\E5*/
+	vce_clk = clk_get_sys(NULL, CLKNAME_VCE_CLK);
+	if (IS_ERR(vce_clk)) {
+		vce_err("clk_get_sys(CLK_NAME_VCE_CLK, NULL) failed\n");
+		return 0;
+	}
+
+	rate = clk_get_rate(vce_clk); /*\BB\F1ȡclk\B5\B1ǰƵ\C2\CAhz\A3\AC\C8\E7hosc\A3\BA24000000*/
+	vce_info("cur vce freq : %ld MHz\n",rate / (1000*1000));
+
+	return rate / (1000 * 1000);
+}
+
+/* enable int */
+static inline void enable_vce_irq(void)
+{
+}
+
+static inline void disable_vce_irq(void)
+{
+	int vce_status;
+
+	vce_status = Re_Reg(VCE_STATUS);
+
+	/*vce_status = 0; vce_status&(~0x101);*/
+	vce_status = vce_status & (~0x100);
+	Wr_Reg(VCE_STATUS, vce_status); /*new*/
+	gVceStatus = vce_status;
+}
+
+/**
+ * This function is vce ISR.
+ */
+irqreturn_t vce_ISR(int irq, void *dev_id)
+{
+	if(vce_open_count > 0)
+	{
+		disable_vce_irq();
+		complete(&vce_complete);
+		wake_up_interruptible(&vce_wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+typedef struct{
+	unsigned int vce_status;
+	unsigned int vce_outstanding;
+	unsigned int vce_cfg;
+	unsigned int vce_param0;
+	unsigned int vce_param1;
+	unsigned int vce_strm;
+	unsigned int vce_strm_addr;
+	unsigned int vce_yaddr;
+	unsigned int vce_list0;
+	unsigned int vce_list1;
+	unsigned int vce_me_param;
+	unsigned int vce_swindow;
+	unsigned int vce_scale_out;
+	unsigned int vce_rect;
+	unsigned int vce_rc_param1;
+	unsigned int vce_rc_param2;
+	unsigned int vce_rc_hdbits;
+	unsigned int vce_ts_info;
+	unsigned int vce_ts_header;
+	unsigned int vce_ts_blu;
+	unsigned int vce_ref_dhit;
+	unsigned int vce_ref_dmiss;
+
+	unsigned int ups_yas;
+	unsigned int ups_cacras;
+	unsigned int ups_cras;
+	unsigned int ups_ifomat;
+	unsigned int ups_ratio;
+	unsigned int ups_ifs;
+}vce_input_t_7021;
+
+static int set_registers_7021(vce_input_t_7021  *vce_in)
+{
+	Wr_Reg(UPS_YAS_7021,vce_in->ups_yas);
+	Wr_Reg(UPS_CBCRAS_7021,vce_in->ups_cacras);
+	Wr_Reg(UPS_CRAS_7021,vce_in->ups_cras);
+	Wr_Reg(UPS_IFORMAT_7021,vce_in->ups_ifomat);
+	Wr_Reg(UPS_RATIO_7021,vce_in->ups_ratio);
+	Wr_Reg(UPS_IFS_7021,vce_in->ups_ifs); 
+
+	Wr_Reg(VCE_CFG,vce_in->vce_cfg);
+	Wr_Reg(VCE_PARAM0,vce_in->vce_param0);
+	Wr_Reg(VCE_OUTSTANDING_7021,vce_in->vce_outstanding);
+	Wr_Reg(VCE_PARAM1,vce_in->vce_param1);
+	Wr_Reg(VCE_STRM,vce_in->vce_strm);
+	Wr_Reg(VCE_STRM_ADDR,vce_in->vce_strm_addr);
+	Wr_Reg(VCE_YADDR,vce_in->vce_yaddr);
+	Wr_Reg(VCE_LIST0_ADDR,vce_in->vce_list0);
+	Wr_Reg(VCE_LIST1_ADDR,vce_in->vce_list1);
+	Wr_Reg(VCE_ME_PARAM,vce_in->vce_me_param);
+	Wr_Reg(VCE_SWIN,vce_in->vce_swindow);
+	Wr_Reg(VCE_SCALE_OUT,vce_in->vce_scale_out);
+	Wr_Reg(VCE_RECT,vce_in->vce_rect);
+	Wr_Reg(VCE_RC_PARAM1,vce_in->vce_rc_param1);
+	Wr_Reg(VCE_RC_PARAM2,vce_in->vce_rc_param2);
+	Wr_Reg(VCE_TS_INFO,vce_in->vce_ts_info);
+	Wr_Reg(VCE_TS_HEADER,vce_in->vce_ts_header);
+	Wr_Reg(VCE_TS_BLUHD,vce_in->vce_ts_blu);
+	Wr_Reg(VCE_RC_HDBITS,vce_in->vce_rc_hdbits);
+	Wr_Reg(VCE_REF_DHIT,vce_in->vce_ref_dhit);
+	Wr_Reg(VCE_REF_DMISS,vce_in->vce_ref_dmiss);
+
+	return 0;
+}
+
+static unsigned int get_ups_ifomat_7021(vce_input_t  *vce_in)
+{
+	unsigned int ups_ifomat = 0;
+	unsigned int stride = (vce_in->ups_str &0x3ff)  *8;
+	unsigned int input_fomat = vce_in->input_fomat;
+	ups_ifomat = input_fomat |  ( stride  << 16) ;
+
+	return ups_ifomat;
+}
+
+static unsigned int get_ups_ratio_7021(vce_input_t  *vce_in)
+{
+	unsigned int ups_ratio = 0;
+	unsigned int ups_ifs= vce_in->ups_ifs;
+	unsigned int ups_ofs = vce_in->ups_ofs;
+	int srcw = (ups_ifs & 0xffff)*8;
+	int srch =  ((ups_ifs>>16) & 0xffff)*8;
+	int dstw = (ups_ofs & 0xffff)*16;
+	int dsth = ((ups_ofs>>16) & 0xffff)*16;
+
+	unsigned int upscale_factor_h_int,upscale_factor_v_int;
+	if(dstw<=srcw)
+		upscale_factor_h_int =  (srcw*8192) / dstw;
+	else
+		upscale_factor_h_int = (srcw/2 - 1)*8192  / (dstw/2 - 1) ;
+
+	if(dsth <= srch)
+		upscale_factor_v_int =  (srch*8192) / dsth;
+	else
+		upscale_factor_v_int = (srch/2 - 1)*8192  / (dsth/2 - 1) ;
+	ups_ratio = (upscale_factor_v_int & 0xffff) <<16 | (upscale_factor_h_int & 0xffff);
+
+	return ups_ratio;
+}
+
+static void registers_7039_to_7021(vce_input_t  *vce_in,vce_input_t_7021  *vce_in_7021)
+{
+	vce_in_7021->ups_ifomat = get_ups_ifomat_7021(vce_in);
+	vce_in_7021->ups_ratio = get_ups_ratio_7021(vce_in);
+	vce_in_7021->ups_ifs = vce_in->ups_ifs<<3;  //*
+	vce_in_7021->ups_yas = vce_in->ups_yas;
+	vce_in_7021->ups_cacras = vce_in->ups_cacras;
+	vce_in_7021->ups_cras = vce_in->ups_cras;
+	vce_in_7021->vce_outstanding = (1<<31) |  (12<<16) | (1<<15) | 128;
+
+	vce_in_7021->vce_status = vce_in->vce_status;
+	vce_in_7021->vce_cfg = vce_in->vce_cfg;
+	vce_in_7021->vce_param0 = vce_in->vce_param0;
+	vce_in_7021->vce_param1 = vce_in->vce_param1;
+	vce_in_7021->vce_strm = vce_in->vce_strm;
+	vce_in_7021->vce_strm_addr = vce_in->vce_strm_addr;
+	vce_in_7021->vce_yaddr = vce_in->vce_yaddr;
+	vce_in_7021->vce_list0 = vce_in->vce_list0;
+	vce_in_7021->vce_list1 = vce_in->vce_list1;
+	vce_in_7021->vce_me_param = vce_in->vce_me_param;
+	vce_in_7021->vce_swindow = vce_in->vce_swindow;
+	vce_in_7021->vce_scale_out = vce_in->vce_scale_out;
+	vce_in_7021->vce_rect = vce_in->vce_rect;
+	vce_in_7021->vce_rc_param1 = vce_in->vce_rc_param1;
+	vce_in_7021->vce_rc_param2 = vce_in->vce_rc_param2;
+	vce_in_7021->vce_ts_info = vce_in->vce_ts_info;
+	vce_in_7021->vce_ts_header = vce_in->vce_ts_header;
+	vce_in_7021->vce_ts_blu = vce_in->vce_ts_blu;
+	vce_in_7021->vce_rc_hdbits = vce_in->vce_rc_hdbits;
+	vce_in_7021->vce_ref_dhit = vce_in->vce_ref_dhit;
+	vce_in_7021->vce_ref_dmiss = vce_in->vce_ref_dmiss;
+}
+
+#if Enable_Debug_PrintK
+static void print_vce_input_t_7021(vce_input_t_7021* vce_input)
+{
+	vce_info("ko.vce_input_t1!vce_status:%x,vce_cfg:%x,vce_param0:%x,vce_param1:%x\n",
+		vce_input->vce_status,vce_input->vce_cfg,vce_input->vce_param0,vce_input->vce_param1);
+
+	vce_info("ko.vce_input_t2!vce_strm:%x,vce_strm_addr:%x,vce_yaddr:%x,vce_list0:%x\n",
+		vce_input->vce_strm,vce_input->vce_strm_addr,vce_input->vce_yaddr,vce_input->vce_list0);
+
+	vce_info("ko.vce_input_t3!vce_list1:%x,vce_me_param:%x,vce_swindow:%x,vce_scale_out:%x\n",
+		vce_input->vce_list1,vce_input->vce_me_param,vce_input->vce_swindow,vce_input->vce_scale_out);
+
+	vce_info("ko.vce_input_t4!vce_rect:%x,vce_rc_param1:%x,vce_rc_param2:%x,vce_rc_hdbits:%x\n",
+		vce_input->vce_rect,vce_input->vce_rc_param1,vce_input->vce_rc_param2,vce_input->vce_rc_hdbits);
+
+	vce_info("ko.vce_input_t5!vce_ts_info:%x,vce_ts_header:%x,vce_ts_blu:%x\n",
+		vce_input->vce_ts_info,vce_input->vce_ts_header,vce_input->vce_ts_blu);
+
+	vce_info("ko.vce_input_t6!ups_ifomat:%x,ups_ratio:%x,ups_ifs:%x\n",
+		vce_input->ups_ifomat,vce_input->ups_ratio,vce_input->ups_ifs);
+
+	vce_info("ko.vce_input_t7!ups_yas:%x,ups_cacras:%x,ups_cras:%x,\n",
+		vce_input->ups_yas,vce_input->ups_cacras,vce_input->ups_cras);
+
+	vce_info("ko.vce_input_t8!vce_ref_dhit:%x,vce_ref_dmiss:%x\n",
+		vce_input->vce_ref_dhit,vce_input->vce_ref_dmiss); 
+}
+#endif
+
+static int set_registers_atm7021(vce_input_t  *vce_in)
+{
+	vce_input_t_7021  vce_in_7021;
+	registers_7039_to_7021(vce_in,&vce_in_7021);
+#if Enable_Debug_PrintK
+	print_vce_input_t_7021(&vce_in_7021);
+#endif
+	set_registers_7021(&vce_in_7021);
+	return 0;
+}
+
+static int set_registers_atm7039(vce_input_t  *vce_in)
+{
+	Wr_Reg(UPS_IFS_7039, vce_in->ups_ifs);
+	Wr_Reg(UPS_STR_7039, vce_in->ups_str);
+	Wr_Reg(UPS_OFS_7039, vce_in->ups_ofs);
+	Wr_Reg(UPS_RATH_7039, vce_in->ups_rath);
+	Wr_Reg(UPS_RATV_7039, vce_in->ups_ratv);
+	Wr_Reg(UPS_YAS_7039, vce_in->ups_yas);
+	Wr_Reg(UPS_CBCRAS_7039, vce_in->ups_cacras);
+	Wr_Reg(UPS_CRAS_7039, vce_in->ups_cras);
+	Wr_Reg(UPS_DWH_7039, vce_in->ups_dwh);
+	Wr_Reg(UPS_BCT_7039, vce_in->ups_bct);
+	Wr_Reg(UPS_SAB0_7039, vce_in->ups_sab0);
+	Wr_Reg(UPS_SAB1_7039, vce_in->ups_sab1);
+	Wr_Reg(UPS_DAB_7039, vce_in->ups_dab);
+	Wr_Reg(UPS_CTL_7039, vce_in->ups_ctl);/*enable blding*/
+	Wr_Reg(UPS_RGB32_SR_7039, vce_in->ups_rgb32_sr);
+	Wr_Reg(UPS_BLEND_W_7039, vce_in->ups_blend_w);
+
+	Wr_Reg(VCE_CFG, vce_in->vce_cfg);
+	Wr_Reg(VCE_PARAM0, vce_in->vce_param0);
+	Wr_Reg(VCE_PARAM1, vce_in->vce_param1);
+	Wr_Reg(VCE_STRM, vce_in->vce_strm);
+	Wr_Reg(VCE_STRM_ADDR, vce_in->vce_strm_addr);
+	Wr_Reg(VCE_YADDR, vce_in->vce_yaddr);
+	Wr_Reg(VCE_LIST0_ADDR, vce_in->vce_list0);
+	Wr_Reg(VCE_LIST1_ADDR, vce_in->vce_list1);
+	Wr_Reg(VCE_ME_PARAM, vce_in->vce_me_param);
+	Wr_Reg(VCE_SWIN, vce_in->vce_swindow);
+	Wr_Reg(VCE_SCALE_OUT, vce_in->vce_scale_out);
+	Wr_Reg(VCE_RECT, vce_in->vce_rect);
+	Wr_Reg(VCE_RC_PARAM1, vce_in->vce_rc_param1);
+	Wr_Reg(VCE_RC_PARAM2, vce_in->vce_rc_param2);
+	Wr_Reg(VCE_TS_INFO, vce_in->vce_ts_info);
+	Wr_Reg(VCE_TS_HEADER, vce_in->vce_ts_header);
+	Wr_Reg(VCE_TS_BLUHD, vce_in->vce_ts_blu);
+	Wr_Reg(VCE_RC_HDBITS, vce_in->vce_rc_hdbits);
+	Wr_Reg(VCE_REF_DHIT, vce_in->vce_ref_dhit);
+	Wr_Reg(VCE_REF_DMISS, vce_in->vce_ref_dmiss);
+
+	return 0;
+}
+
+static int get_registers(vce_output_t *vce_out)
+{
+	vce_out->vce_strm = Re_Reg(VCE_STRM);
+	vce_out->vce_rc_param3 = Re_Reg(VCE_RC_PARAM3);
+	vce_out->vce_rc_hdbits = Re_Reg(VCE_RC_HDBITS);
+
+	vce_out->strm_addr = Re_Reg(VCE_STRM_ADDR);
+	vce_out->i_ts_offset = Re_Reg(VCE_TS_INFO);
+	vce_out->i_ts_header = Re_Reg(VCE_TS_HEADER);
+
+	vce_out->vce_ref_dhit = Re_Reg(VCE_REF_DHIT);
+	vce_out->vce_ref_dmiss = Re_Reg(VCE_REF_DMISS);
+	return 0;
+}
+
+static void print_all_regs(char *s)
+{
+	if(ic_type == IC_TYPE_ATM7039)
+	{
+	vce_info("%s", s);
+
+	vce_info("ShareSRam_CTL:%x\n", Re_Reg_Self(iobase_sram));
+
+	vce_info("VCE_ID:%x,VCE_STATUS:%x,VCE_CFG:%x\n",
+	Re_Reg(VCE_ID), Re_Reg(VCE_STATUS), Re_Reg(VCE_CFG));
+
+	vce_info("VCE_PARAM0:%x,VCE_PARAM1:%x,VCE_STRM:%x\n",
+	Re_Reg(VCE_PARAM0), Re_Reg(VCE_PARAM1), Re_Reg(VCE_STRM));
+
+	vce_info("VCE_STRM_ADDR:%x,VCE_YADDR:%x,VCE_LIST0_ADDR:%x\n",
+	Re_Reg(VCE_STRM_ADDR), Re_Reg(VCE_YADDR), Re_Reg(VCE_LIST0_ADDR));
+
+	vce_info("VCE_LIST1_ADDR:%x,VCE_ME_PARAM:%x,VCE_SWIN:%x\n",
+	Re_Reg(VCE_LIST1_ADDR), Re_Reg(VCE_ME_PARAM), Re_Reg(VCE_SWIN));
+
+	vce_info("VCE_SCALE_OUT:%x,VCE_RECT:%x,VCE_RC_PARAM1:%x\n",
+	Re_Reg(VCE_SCALE_OUT), Re_Reg(VCE_RECT), Re_Reg(VCE_RC_PARAM1));
+
+	vce_info("VCE_RC_PARAM2:%x,VCE_RC_PARAM3:%x,VCE_RC_HDBITS:%x\n",
+	Re_Reg(VCE_RC_PARAM2), Re_Reg(VCE_RC_PARAM3), Re_Reg(VCE_RC_HDBITS));
+
+	vce_info("VCE_TS_INFO:%x,VCE_TS_HEADER:%x,VCE_TS_BLUHD:%x\n",
+	Re_Reg(VCE_TS_INFO), Re_Reg(VCE_TS_HEADER), Re_Reg(VCE_TS_BLUHD));
+
+	vce_info("UPS_CTL:%x,UPS_IFS:%x,UPS_STR:%x\n",
+	Re_Reg(UPS_CTL_7039), Re_Reg(UPS_IFS_7039), Re_Reg(UPS_STR_7039));
+
+	vce_info("UPS_OFS:%x,UPS_RATH:%x,UPS_RATV:%x\n",
+	Re_Reg(UPS_OFS_7039), Re_Reg(UPS_RATH_7039), Re_Reg(UPS_RATV_7039));
+
+	vce_info("UPS_YAS:%x,UPS_CBCRAS:%x,UPS_CRAS:%x\n",
+	Re_Reg(UPS_YAS_7039), Re_Reg(UPS_CBCRAS_7039), Re_Reg(UPS_CRAS_7039));
+
+	vce_info("UPS_BCT:%x,UPS_DAB:%x,UPS_DWH:%x\n",
+	Re_Reg(UPS_BCT_7039), Re_Reg(UPS_DAB_7039), Re_Reg(UPS_DWH_7039));
+
+	vce_info("UPS_SAB0:%x,UPS_SAB1:%x\n",
+	Re_Reg(UPS_SAB0_7039), Re_Reg(UPS_SAB1_7039));
+
+	vce_info("%s", s);
+	}
+}
+
+#if Enable_Debug_PrintK
+static void print_vce_input_t(vce_input_t* vce_input)
+{
+	vce_info("ko.vce_input_t1!vce_status:%x,vce_cfg:%x,vce_param0:%x,vce_param1:%x\n",\
+		vce_input->vce_status, vce_input->vce_cfg,vce_input->vce_param0, vce_input->vce_param1);
+
+	vce_info("ko.vce_input_t2!vce_strm:%x,vce_strm_addr:%x,vce_yaddr:%x,vce_list0:%x\n",\
+		vce_input->vce_strm, vce_input->vce_strm_addr,vce_input->vce_yaddr, vce_input->vce_list0);
+
+	vce_info("ko.vce_input_t3!vce_list1:%x,vce_me_param:%x,vce_swindow:%x,vce_scale_out:%x\n",\
+		vce_input->vce_list1, vce_input->vce_me_param,vce_input->vce_swindow, vce_input->vce_scale_out);
+
+	vce_info("ko.vce_input_t4!vce_rect:%x,vce_rc_param1:%x,vce_rc_param2:%x,vce_rc_hdbits:%x\n",\
+		vce_input->vce_rect, vce_input->vce_rc_param1,vce_input->vce_rc_param2, vce_input->vce_rc_hdbits);
+
+	vce_info("ko.vce_input_t5!vce_ts_info:%x,vce_ts_header:%x,vce_ts_blu:%x\n",\
+		vce_input->vce_ts_info, vce_input->vce_ts_header,vce_input->vce_ts_blu);
+
+	vce_info("ko.vce_input_t6!ups_ctl:%x,ups_ifs:%x,ups_str:%x,ups_ofs:%x\n",\
+		vce_input->ups_ctl, vce_input->ups_ifs,vce_input->ups_str, vce_input->ups_ofs);
+
+	vce_info("ko.vce_input_t7!ups_rath:%x,ups_ratv:%x,ups_yas:%x,ups_cacras:%x\n",\
+		vce_input->ups_rath, vce_input->ups_ratv,vce_input->ups_yas, vce_input->ups_cacras);
+
+	vce_info("ko.vce_input_t8!ups_cras:%x,ups_bct:%x,ups_dab:%x,ups_dwh:%x\n",\
+		vce_input->ups_cras, vce_input->ups_bct,vce_input->ups_dab, vce_input->ups_dwh);
+
+	vce_info("ko.vce_input_t9!ups_sab0:%x,ups_sab1:%x\n",\
+		vce_input->ups_sab0, vce_input->ups_sab1);
+
+	vce_info("ko.vce_input_t10!vce_ref_dhit:%x,vce_ref_dmiss:%x,ups_rgb32_sr:%x,ups_blend_w:%x\n",\
+		vce_input->vce_ref_dhit, vce_input->vce_ref_dmiss,vce_input->ups_rgb32_sr, vce_input->ups_blend_w);
+}
+
+static void print_vce_output_t(vce_output_t* vce_output)
+{
+	vce_info("ko.vce_output_t1!vce_strm:%x,vce_rc_param3:%x,vce_rc_hdbits:%x\n",\
+		vce_output->vce_strm, vce_output->vce_rc_param3,vce_output->vce_rc_hdbits);
+
+	vce_info("ko.vce_output_t2!strm_addr:%x,i_ts_offset:%x,i_ts_header:%x\n",\
+		vce_output->strm_addr, vce_output->i_ts_offset,vce_output->i_ts_header);
+}
+
+static void print_ShareSRam_CTL(char *str)
+{
+	vce_info("%s!ShareSRam_CTL:%x\n", str, Re_Reg_Self(iobase_sram));
+}
+
+void print_CMU_Reg(char *s)
+{
+	vce_info("%s\n", s);
+	vce_info("Share_Mem_REG:%x  CMU_DEVRST0:%x  SPS_PG_CTL:%x\n",
+		Re_Reg_Self(iobase_sram), Re_Reg_Self(iobase_cmu_devrst0), Re_Reg_Self(iobase_sps_pg_ctl));
+	vce_info("DEV:%x,DDR:%x,DISPLAY:%x\n",
+		Re_Reg_Self(iobase_cmu_devpll), Re_Reg_Self(iobase_cmu_ddrpll), Re_Reg_Self(iobase_cmu_displaypll));
+	vce_info("VCECLK:%x,DEVCLKEN0:%x\n",
+		Re_Reg_Self(iobase_cmu_vceclk), Re_Reg_Self(iobase_cmu_devclken0));
+}
+#endif
+
+static void pAbuf_release(int vce_count)
+{
+	int i;
+	vce_info_t *info = NULL;
+	if (vce_count >= 1 && vce_count <= vce_open_count) {
+		/*delete\B8ýڵ\E3*/
+		for (i = vce_count; i < vce_open_count;i++) {
+			pAbuf[i-1] = pAbuf[i];              /*\D3ú\F3\C3\E6\CD\F9ǰŲ\B6\AF*/
+			info = (vce_info_t*)pAbuf[i-1];
+			info->vce_count--;                   /*ע\D2\E2-1*/
+		}
+		pAbuf[vce_open_count - 1] = NULL;
+
+		if (vce_last_handle == vce_count)
+			vce_last_handle = 0;
+		else if (vce_last_handle > vce_count)
+			vce_last_handle--;
+	} else {
+		vce_warning("vce_count(%d) is out of range(%d)!\n",vce_count,vce_open_count);
+	}
+};
+
+long vce_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	vce_info_t *info = (vce_info_t*) filp->private_data;
+	
+	int ret_value = 0;	
+	void __user *from,*to;
+	long time_rest = 0;
+	int cur_status = 0;	
+	unsigned long timeout;
+	unsigned long expire;	
+	int left_time;	
+	vce_multi_freq_t  vce_freq;
+
+	if ((Re_Reg_Self(iobase_cmu_devclken0) & VCE_CLKEN) == 0) {
+		vce_err("vce clk is not enabled,CMU_DEVCLKEN0 = %x\n",Re_Reg_Self(iobase_cmu_devclken0));		
+		return VCE_ERR_UNKOWN;
+	}
+
+	if ((Re_Reg_Self(iobase_sps_pg_ctl) & VCE_BISP_POWERON) == 0) {		
+		vce_err("vce power gate is not enabled,SPS_PG_CTL = %x\n",Re_Reg_Self(iobase_sps_pg_ctl));		
+		return VCE_ERR_UNKOWN;
+	}
+
+	switch (cmd) {
+	case VCE_CHECK_VERSION:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		if (Re_Reg(VCE_ID) != 0x78323634) {
+			vce_err("VCE_ID ERR....");
+		}
+		mutex_unlock(&vce_ioctl_mutex);
+	}
+	break;
+
+	case VCE_CMD_ENC_RUN/*VCE_RUN*/:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		from = (void __user *)arg;
+		
+		/*\C8\F4\B3\ACʱ*/
+		cur_status = query_status();
+		time_rest = wait_event_interruptible_timeout(vce_wait,
+			(!((gVceStatus & 0x1) == 1) &&
+			((gVceStatus & 0x100) == 0)), WAIT_TIMEOUT);
+
+		cur_status = query_status();
+
+		if (time_rest <= 0 && (cur_status == VCE_BUSY)) {
+			print_all_regs("vce_dev timeout when runing!reginfo:");
+			vce_reset();
+			mutex_unlock(&vce_ioctl_mutex);
+			return VCE_ERR_BUSY;
+		} else {
+			/*already done,clear all & save irqs*/
+			/*\B0\D1\C9\CFһ\B8\F6\C7\FD\B6\AF\B1\A3\B4\E6\BD\E1\B9\FB*/
+			if (vce_last_handle >= 1 && vce_last_handle < _MAX_HANDLES_) {
+				vce_info_t *pinfo = (vce_info_t *)pAbuf[vce_last_handle - 1];
+				if (pinfo != NULL) {
+					get_registers(&pinfo->vce_out);
+					pinfo->vce_status = STOPED;
+				}
+			}
+		}
+		if( GET_USER_STRUCT(&info->vce_in,from,sizeof(vce_input_t)) ) {
+			vce_err("copy_from_user fail!\n");
+			mutex_unlock(&vce_ioctl_mutex);
+			return VCE_ERR_UNKOWN;
+		}
+
+#if Enable_Debug_PrintK
+		//print_vce_input_t(&info->vce_in);
+#endif
+
+		/* init completion var */
+		init_completion(&vce_complete);
+
+		if(ic_type == IC_TYPE_ATM7039)
+			set_registers_atm7039(&info->vce_in);
+		else
+			set_registers_atm7021(&info->vce_in);
+
+#if Enable_Debug_PrintK
+		print_ShareSRam_CTL("b4 vce run");
+#endif
+		Wr_Reg(VCE_STATUS, 0); /**new add*/
+
+		vce_status = info->vce_in.vce_status;/*Re_Reg(VCE_STATUS);*/
+		vce_status = (vce_status|0x1)&(~(0x1<<8));
+		Wr_Reg(VCE_STATUS, vce_status); /**newW*/
+		vce_last_handle = info->vce_count;
+		info->vce_status = RUNNING;
+		mutex_unlock(&vce_ioctl_mutex);
+		break;
+	}
+
+	case VCE_GET_ENC_STATUS:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		ret_value = query_status();
+		mutex_unlock(&vce_ioctl_mutex);
+		break;
+	}
+
+	case VCE_CMD_QUERY_FINISH:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		to = (void __user *)arg;
+
+		if (info->vce_status == STOPED) {
+			if( SET_USER_STRUCT(to,&info->vce_out,sizeof(vce_output_t)) ){
+				vce_err("copy_to_user fail!\n");
+				mutex_unlock(&vce_ioctl_mutex);
+				return VCE_ERR_UNKOWN;
+			}
+			mutex_unlock(&vce_ioctl_mutex);
+			return 0;
+		}
+
+#if Enable_Debug_PrintK
+		print_ShareSRam_CTL("b4 vce finish");
+#endif
+
+		/*\D2ѽ\E2\CD\EAһ֡*/
+		ret_value = query_status();
+
+		if (ret_value != VCE_BUSY) {
+			get_registers(&info->vce_out);
+			if( SET_USER_STRUCT(to,&info->vce_out,sizeof(vce_output_t)) ){
+				vce_err("copy_to_user fail!\n");
+				mutex_unlock(&vce_ioctl_mutex);
+				return VCE_ERR_UNKOWN;
+			}
+			info->vce_status = STOPED;
+			mutex_unlock(&vce_ioctl_mutex);
+			goto out;
+		}
+
+		timeout = msecs_to_jiffies(WAIT_TIMEOUT_MS) + 1;
+
+		/*pr_err(KERN_ERR"timeout:%d  jiffies ...\n",timeout);*/
+		if (vce_irq_registered) {
+			enable_vce_irq();
+			left_time = wait_for_completion_timeout(&vce_complete,
+				 timeout);
+			if (unlikely(left_time == 0)) {
+				vce_status = Re_Reg(VCE_STATUS);
+				vce_err("time out!\n");
+
+				if (vce_status & 0x100) {
+					ret_value = 0;
+					get_registers(&info->vce_out);
+					if( SET_USER_STRUCT(to,&info->vce_out,sizeof(vce_output_t)) ){
+						vce_err("copy_to_user fail!\n");
+						mutex_unlock(&vce_ioctl_mutex);
+						return VCE_ERR_UNKOWN;
+					}
+
+					info->vce_status = STOPED;
+					disable_vce_irq();
+					mutex_unlock(&vce_ioctl_mutex);
+					goto out;
+				}
+
+				info->vce_status = STOPED;
+				ret_value = VCE_ERR_TIMEOUT;
+				disable_vce_irq();
+				vce_err("timeout when QUERY_FINISH\n");
+				vce_reset();
+				mutex_unlock(&vce_ioctl_mutex);
+				goto out;
+			} else {
+				/* normal case */
+				ret_value = 0;
+				get_registers(&info->vce_out);
+				if( SET_USER_STRUCT(to,&info->vce_out,sizeof(vce_output_t)) ){
+					vce_err("copy_to_user fail!\n");
+					mutex_unlock(&vce_ioctl_mutex);
+					return VCE_ERR_UNKOWN;
+				}
+
+				info->vce_status = STOPED;
+				disable_vce_irq();
+				mutex_unlock(&vce_ioctl_mutex);
+				goto out;
+			}
+		}
+
+		/*
+		*ȫ\BEֱ\E4\C1\BFjiffiesȡֵΪ\D7Բ\D9\D7\F7ϵͳ\C6\F4\B6\AF\D2\D4\C0\B4\B5\C4ʱ\D6ӵδ\F0\B5\C4\CA\FDĿ\A3\AC
+		*\D4\DAͷ\CEļ\FE<linux/sched.h>\D6ж\A8\D2\E5,\CA\FD\BE\DD\C0\E0\D0\CDΪunsigned long volatile
+		*ϵͳ\D6в\C9\D3\C3jiffies\C0\B4\BC\C6\CB\E3ʱ\BC䣬
+		*\B5\AB\D3\C9\D3\DAjiffies\D2\E7\B3\F6\BF\C9\C4\DC\D4\EC\B3\C9ʱ\BC\E4\B1ȽϵĴ\ED\CE\F3\A3\AC
+		*\D2\F2\B6\F8ǿ\C1ҽ\A8\D2\E9\D4ڱ\E0\C2\EB\D6\D0ʹ\D3\C3time_after\B5Ⱥ\EA\C0\B4\B1Ƚ\CFʱ\BC\E4\CFȺ\F3\B9\D8ϵ\A3\AC
+		*\D5\E2Щ\BA\EA\BF\C9\D2Է\C5\D0\C4ʹ\D3\C3
+		*/
+		expire = timeout + jiffies;
+		do {
+			ret_value = query_status();
+
+			if (ret_value != VCE_BUSY) {
+				get_registers(&info->vce_out);
+				if( SET_USER_STRUCT(to,&info->vce_out,sizeof(vce_output_t)) ){
+					vce_err("copy_to_user fail!\n");
+					mutex_unlock(&vce_ioctl_mutex);
+					return VCE_ERR_UNKOWN;
+				}
+
+				info->vce_status = STOPED;
+				disable_vce_irq();
+				mutex_unlock(&vce_ioctl_mutex);
+				goto out;
+			}
+
+			if (time_after(jiffies, expire)) {
+				ret_value = VCE_ERR_TIMEOUT;
+				info->vce_status = STOPED;
+				disable_vce_irq();
+				vce_err("timeout when QUERY_FINISH jiffies\n");
+				vce_reset();
+				mutex_unlock(&vce_ioctl_mutex);
+				goto out;
+			}
+		} while (1);
+
+		mutex_unlock(&vce_ioctl_mutex);
+	}
+	break;
+
+	case VCE_SET_DISABLE_CLK/*VCE_DISABLE_CLK*/:
+	vce_info("vce_ioctl get clk disable cmd!\n");
+	/*vce_clk_disable();*/
+	break;
+
+	case VCE_SET_ENABLE_CLK/*VCE_ENABLE_CLK*/:
+	vce_info("vce_ioctl get clk enable cmd!\n");
+	/*vce_clk_enable();*/
+	break;
+
+	case VCE_SET_FREQ:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		vce_info("VCE_SET_FREQ...\n");
+		from = (void __user *)arg;
+		if( GET_USER_STRUCT(&vce_freq,from,sizeof(vce_multi_freq_t)) ){
+			vce_err("copy_from_user fail!\n");
+			mutex_unlock(&vce_ioctl_mutex);
+			return VCE_ERR_UNKOWN;
+		}
+		ret_value = vce_setFreq(&vce_freq);
+		mutex_unlock(&vce_ioctl_mutex);
+	}
+	break;
+
+	case VCE_GET_FREQ:
+	{
+		mutex_lock(&vce_ioctl_mutex);
+		vce_info("VCE_GET_FREQ...\n");
+		ret_value = vce_getFreq();
+		mutex_unlock(&vce_ioctl_mutex);
+	}
+	break;
+
+	default:
+	vce_err("no such cmd ...\n");
+	return -EIO;
+}
+	
+out:
+	return ret_value;
+}
+
+int vce_open(struct inode *inode, struct file *filp)
+{
+	vce_info_t *info = NULL;
+
+	int ret_frep;
+	
+	mutex_lock(&vce_ioctl_mutex);
+	vce_open_count++;
+	filp->private_data = NULL;
+
+	if (vce_open_count > _MAX_HANDLES_) {
+		vce_open_count--;
+		vce_err("max vce_drv_open ...%d.\n", vce_open_count);
+		mutex_unlock(&vce_ioctl_mutex);
+		return -1;
+	}
+
+	info = (vce_info_t*)vce_malloc(sizeof(vce_info_t));
+	printk("vce_drv: vce_open!info:%p,count:%d\n", info, vce_open_count);
+	if (info == NULL) {
+		vce_open_count--;
+		vce_err("vce info malloc failed!...\n");
+		mutex_unlock(&vce_ioctl_mutex);
+		return -1;
+	}
+
+	/* init completion var */
+	if (vce_open_count == 1)
+		init_completion(&vce_complete);
+
+	share_mem_reg_enable();
+	vce_clk_enable(); /**new add*/
+	disable_vce_irq();
+	vce_info("vce disable_vce_irq ok\n");	
+#if Enable_Debug_PrintK
+	print_CMU_Reg("CMU_Reg");
+#endif
+
+	if (vce_open_count == 1) {
+		vce_freq_multi.width = VCE_DEFAULT_WIDTH;
+		vce_freq_multi.height = VCE_DEFAULT_HEIGHT;
+		vce_freq_multi.freq = VCE_DEFAULT_FREQ;
+		ret_frep = vce_setFreq(&vce_freq_multi);
+		if (ret_frep < 0) {
+			vce_freq_is_init = 0;	
+			vce_open_count--;
+			vce_free(info);
+			share_mem_reg_disable();
+			vce_clk_disable();
+			mutex_unlock(&vce_ioctl_mutex);
+			vce_err("freq_init to %d MHZ fail %d\n",VCE_DEFAULT_FREQ, vce_open_count);
+			return -1;
+		}
+		vce_info("freq_init to %d MHZ!!\n", ret_frep);
+  }
+  
+	pAbuf[vce_open_count - 1] = (void *)info;
+	info->vce_count = vce_open_count; /*\B5\B1ǰvce info\D0\F2\C1кţ\AC\B4\D31\BF\AAʼ*/
+	info->vce_status = STOPED;
+	filp->private_data = (void *)info;
+	mutex_unlock(&vce_ioctl_mutex);
+	printk("vce_drv: out of vce_drv_open ...%d.\n", vce_open_count);
+
+	return 0;
+}
+
+int vce_release(struct inode *inode, struct file *filp)
+{
+	vce_info_t *info = (vce_info_t *) filp->private_data;
+	printk("vce_drv: vce_drv_release..count:%d,info:%p\n",
+		vce_open_count, info);
+
+	if (info == NULL) {
+		vce_err("Vce Info is Null ,return\n");
+		return 0;
+	}
+	mutex_lock(&vce_ioctl_mutex);
+	
+	if (vce_open_count >= 1) 
+		pAbuf_release(info->vce_count);
+	
+	vce_open_count--;
+	
+	if (vce_open_count >= 0) {
+			vce_free(info);
+			info = filp->private_data = NULL;
+	} else if (vce_open_count < 0) {
+		vce_err("count %d,%p\n",
+			vce_open_count, info);
+		vce_open_count = 0;
+	}
+
+	vce_stop();
+	if (vce_open_count == 0) {
+		vce_freq_multi.width = VCE_DEFAULT_WIDTH;
+		vce_freq_multi.height = VCE_DEFAULT_HEIGHT;
+		vce_freq_multi.freq = VCE_DEFAULT_FREQ;
+		vce_freq_is_init = 0;
+
+		vce_last_handle = 0;
+		disable_vce_irq();
+		share_mem_reg_disable();
+	}
+
+	vce_clk_disable();
+	mutex_unlock(&vce_ioctl_mutex);
+
+	return 0;
+}
+
+/* \BD\F8\C8\EB\B5͹\A6\BA\C4֮ǰ\A3\AC\B1\D8\D0뱣֤\D2Ѿ\AD\BD\E2\C2\EB\CD굱ǰ֡\A1\A3
+ *
+ */
+int vce_suspend(struct platform_device *dev, pm_message_t state)
+{
+	vce_info("vce_suspend in %d,%d\n",
+		vce_clk_isEnable, vce_open_count);
+	mutex_lock(&vce_ioctl_mutex);
+	if ((vce_open_count > 0) && (vce_clk_isEnable == 1)) {
+		vce_stop();		
+		disable_vce_irq();		
+		share_mem_reg_disable();		
+		vce_clk_disable();		
+		vce_info("vce_suspend!clk disable!\n");
+	}	
+	disable_irq(irq_vce);
+	if (!IS_ERR(power)){
+	    regulator_disable(power);
+		vce_info("vce_suspend!vdd regulator disable!\n");
+	}
+	mutex_unlock(&vce_ioctl_mutex);
+	vce_info("vce_suspend out %d,%d\n",
+		vce_clk_isEnable, vce_open_count);
+	return 0;
+}
+
+int vce_resume(struct platform_device *dev)
+{
+	vce_info("vce_resume in %d,%d\n",
+		vce_clk_isEnable, vce_open_count);
+	mutex_lock(&vce_ioctl_mutex);
+	vce_resumed_flag = 1;
+	if ((vce_open_count > 0) && (vce_clk_isEnable == 0)) {
+		share_mem_reg_enable();
+		vce_clk_enable();
+		disable_vce_irq();	
+	} else {	
+		/*
+			there may be invalid vce interrupt when cpu resume, though vce module is not enabled;
+			vce isr is crashed due to the non-initialized variable vce_complete;
+			to clear the invalid vce interrupt,  enable the vce module first , clear vce pending bit, disable the module at last.		
+		*/
+		share_mem_reg_enable();
+		module_reset(MOD_ID_VCE);
+		module_clk_enable(MOD_ID_VCE);		
+		disable_vce_irq();
+		module_clk_disable(MOD_ID_VCE);		
+		share_mem_reg_disable();	
+	}
+
+	enable_irq(irq_vce);
+    if (!IS_ERR(power)){
+	    if(regulator_enable(power)!=0){
+            vce_err("vce_resume!vdd regulator err!\n");
+            return -1;
+	    }
+		vce_info("vce_resume!vdd regulator enable!\n");
+	}
+	vce_resumed_flag = 0;
+	mutex_unlock(&vce_ioctl_mutex);
+	vce_info("vce_resume out %d,%d\n",
+		vce_clk_isEnable, vce_open_count);
+	return 0;
+}
+
+struct ic_info {
+	int ic_type;
+};
+
+static struct ic_info atm7039_data = {
+   .ic_type = IC_TYPE_ATM7039,
+};
+ 
+static  struct ic_info atm7021_data = {
+   .ic_type = IC_TYPE_ATM7021,
+};
+
+static  struct ic_info atm6082_data = {
+   .ic_type = IC_TYPE_ATM7021,
+};
+
+static const struct of_device_id owl_vce_of_match[] = {
+	{.compatible = "actions,atm7039c-vce", .data = &atm7039_data},
+	{.compatible = "actions,atm7059a-vce", .data = &atm7021_data},
+	{.compatible = "actions,atm7059tc-vce", .data = &atm6082_data},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, owl_vce_of_match);
+
+static int vce_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *res;
+	const struct of_device_id *id = of_match_device(owl_vce_of_match, &pdev->dev);
+	if(id != NULL) {
+		struct ic_info * info = (struct ic_info *)id->data;	
+		if(info != NULL){
+			ic_type = info->ic_type;
+			vce_info("ic_type(0x%x)!\n",ic_type);
+		}else{
+			vce_warning("info is null!\n");
+		}
+		//platform_set_drvdata(pdev, info);
+	}
+	else {
+		vce_warning("id is null!\n");
+	}
+	
+	irq_vce = platform_get_irq(pdev, 0);
+	vce_info("vce->irq =%d\n",irq_vce);
+	if (irq_vce < 0)
+		return irq_vce;
+
+	ret = devm_request_irq(&pdev->dev, irq_vce, (void *) vce_ISR, 0, "vce_isr", 0);
+	if (ret) {
+		vce_err("register vce irq failed!...\n");
+		return ret;
+	} else {
+		vce_irq_registered = 1;
+	}
+	//vce_info("aft request_irq ...\n");
+
+	power = devm_regulator_get(&pdev->dev,"corevdd");
+	vce_info("power:%p\n",power);
+
+	if (IS_ERR(power))
+	{
+		vce_warning("cannot get corevdd regulator,may be this board not need, or lost in dts!\n");
+	}
+	else
+	{
+		if(regulator_set_voltage(power, VOL_INIT, VOL_MAX))
+		{
+	        vce_err("cannot set corevdd to %duV !\n",VOL_INIT);
+	        return -1;
+	    }
+		vce_info("init vdd:%d\n",VOL_INIT);
+	    if(regulator_enable(power)!=0)
+	    {
+            vce_err("vdd regulator err!\n");
+            return -1;
+	    }
+		vce_info("vdd regulator enable!\n");
+	}
+	
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if(res != NULL){
+		if( request_mem_region(res->start, resource_size(res), "vce") != NULL) {
+			
+			/*res->start:VCE_BASE_ADDR;size:(256,gl5203) or (148,gl5206)*/
+			vce_info("vce_probe!start = %p,size = %d!\n",(void*)res->start, resource_size(res));
+			iobase_vce = (unsigned long)ioremap(res->start, resource_size(res));
+			vce_info("vce_probe!iobase_vce = %p!\n",(void*)iobase_vce);
+			if (iobase_vce == 0) {
+				vce_err("iobase_vce is NULL!\n");
+				goto err;
+			}
+			
+			iobase_sram = (unsigned long)ioremap(Share_Mem_REG, 4);
+			vce_info("vce_probe!iobase_sram = %p!\n",(void*)iobase_sram);
+			if (iobase_sram == 0) {
+				vce_err("iobase_sram is NULL!\n");
+				goto err;
+			}
+			
+			iobase_cmu_devclken0 = (unsigned long)ioremap(CMU_DEVCLKEN0, 4);
+			vce_info("vce_probe!iobase_cmu_devclken0 = %p!\n",(void*)iobase_cmu_devclken0);
+			if (iobase_cmu_devclken0 == 0) {
+				vce_err("iobase_cmu_devclken0 is NULL!\n");
+				goto err;
+			}
+			
+			iobase_sps_pg_ctl = (unsigned long)ioremap(SPS_PG_CTL, 4);
+			vce_info("vce_probe!iobase_sps_pg_ctl = %p!\n",(void*)iobase_sps_pg_ctl);
+			if (iobase_sps_pg_ctl == 0) {
+				vce_err("iobase_sps_pg_ctl is NULL!\n");
+				goto err;
+			}
+				
+#if Enable_Debug_PrintK
+			iobase_cmu_devrst0 = (unsigned long)ioremap(CMU_DEVRST0, 4);
+			vce_info("vce_probe!iobase_cmu_devrst0 = %p!\n",(void*)iobase_cmu_devrst0);
+			if (iobase_cmu_devrst0 == 0) {
+				vce_err("iobase_cmu_devrst0 is NULL!\n");
+				goto err;
+			}
+				
+			iobase_cmu_vceclk = (unsigned long)ioremap(CMU_VCECLK, 4);
+			vce_info("vce_probe!iobase_cmu_vceclk = %p!\n",(void*)iobase_cmu_vceclk);
+			if (iobase_cmu_vceclk == 0) {
+				vce_err("iobase_cmu_vceclk is NULL!\n");
+				goto err;
+			}
+			
+			iobase_sps_pg_ack = (unsigned long)ioremap(SPS_PG_ACK, 4);
+			vce_info("vce_probe!iobase_sps_pg_ack = %p!\n",(void*)iobase_sps_pg_ack);
+			if (iobase_sps_pg_ack == 0) {
+				vce_err("iobase_sps_pg_ack is NULL!\n");
+				goto err;
+			}
+				
+			iobase_cmu_devpll = (unsigned long)ioremap(CMU_DEVPLL, 4);
+			vce_info("vce_probe!iobase_cmu_devpll = %p!\n",(void*)iobase_cmu_devpll);
+			if (iobase_cmu_devpll == 0) {
+				vce_err("iobase_cmu_devpll is NULL!\n");
+				goto err;
+			}
+			
+			iobase_cmu_ddrpll = (unsigned long)ioremap(CMU_DDRPLL, 4);
+			vce_info("vce_probe!iobase_cmu_ddrpll = %p!\n",(void*)iobase_cmu_ddrpll);
+			if (iobase_cmu_ddrpll == 0) {
+				vce_err("iobase_cmu_ddrpll is NULL!\n");
+				goto err;
+			}
+			
+			iobase_cmu_displaypll = (unsigned long)ioremap(CMU_DISPLAYPLL, 4);
+			vce_info("vce_probe!iobase_cmu_displaypll = %p!\n",(void*)iobase_cmu_displaypll);
+			if (iobase_cmu_displaypll == 0) {
+				vce_err("iobase_cmu_displaypll is NULL!\n");
+				goto err;
+			}
+#endif
+			
+		}else{
+			vce_err("request_mem_region is fail!\n");
+			return -1;
+		}
+	}else{
+		vce_err("res is null!\n");
+		return -1;
+	}
+	
+	return 0;
+	
+	err:
+	if(iobase_vce != 0){iounmap((void *)iobase_vce);iobase_vce = 0;};
+	if(iobase_sram != 0){iounmap((void *)iobase_sram);iobase_sram = 0;};
+	if(iobase_cmu_devclken0 != 0){iounmap((void *)iobase_cmu_devclken0);iobase_cmu_devclken0 = 0;}
+	if(iobase_sps_pg_ctl != 0){iounmap((void *)iobase_sps_pg_ctl);iobase_sps_pg_ctl = 0;}
+#if Enable_Debug_PrintK
+	if(iobase_cmu_devrst0 != 0){iounmap((void *)iobase_cmu_devrst0);iobase_cmu_devrst0 = 0;}
+	if(iobase_cmu_vceclk != 0){iounmap((void *)iobase_cmu_vceclk);iobase_cmu_vceclk = 0;}
+	if(iobase_sps_pg_ack != 0){iounmap((void *)iobase_sps_pg_ack);iobase_sps_pg_ack = 0;}
+	if(iobase_cmu_devpll != 0){iounmap((void *)iobase_cmu_devpll);iobase_cmu_devpll = 0;}
+	if(iobase_cmu_ddrpll != 0){iounmap((void *)iobase_cmu_ddrpll);iobase_cmu_ddrpll = 0;}
+	if(iobase_cmu_displaypll != 0){iounmap((void *)iobase_cmu_displaypll);iobase_cmu_displaypll = 0;}
+#endif
+	return -1;
+}
+
+static int vce_remove(struct platform_device *pdev)
+{
+	struct resource *res;
+	
+	if (!IS_ERR(power))
+	{
+	    regulator_disable(power);
+		vce_info("vdd regulator disable!\n");
+	}
+	
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if(res) {
+		vce_info("vce_remove!start = %p,size = %d!\n",(void*)res->start, resource_size(res));
+		release_mem_region(res->start, resource_size(res));
+	}else{
+		vce_warning("res is null!\n");
+	}
+
+	vce_info("vce_remove!iobase_vce = %p!\n",(void*)iobase_vce);
+	if(iobase_vce != 0){iounmap((void *)iobase_vce);iobase_vce = 0;}
+	if(iobase_sram != 0){iounmap((void *)iobase_sram);iobase_sram = 0;};
+	if(iobase_cmu_devclken0 != 0){iounmap((void *)iobase_cmu_devclken0);iobase_cmu_devclken0 = 0;}
+	if(iobase_sps_pg_ctl != 0){iounmap((void *)iobase_sps_pg_ctl);iobase_sps_pg_ctl = 0;}
+#if Enable_Debug_PrintK
+	if(iobase_cmu_devrst0 != 0){iounmap((void *)iobase_cmu_devrst0);iobase_cmu_devrst0 = 0;}
+	if(iobase_cmu_vceclk != 0){iounmap((void *)iobase_cmu_vceclk);iobase_cmu_vceclk = 0;}
+	if(iobase_sps_pg_ack != 0){iounmap((void *)iobase_sps_pg_ack);iobase_sps_pg_ack = 0;}
+	if(iobase_cmu_devpll != 0){iounmap((void *)iobase_cmu_devpll);iobase_cmu_devpll = 0;}
+	if(iobase_cmu_ddrpll != 0){iounmap((void *)iobase_cmu_ddrpll);iobase_cmu_ddrpll = 0;}
+	if(iobase_cmu_displaypll != 0){iounmap((void *)iobase_cmu_displaypll);iobase_cmu_displaypll = 0;}
+#endif
+	return 0;
+}
+
+static const struct file_operations vce_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = vce_ioctl,
+	.open = vce_open,
+	.release = vce_release,
+};
+
+#ifndef CONFIG_OF
+static void vce_platform_device_release(struct device * dev)
+{
+  return ;
+}
+
+static struct platform_device vce_platform_device = {
+	.name = DEVDRV_NAME_VCE,
+	.id = -1,
+	.dev = {
+		.release = vce_platform_device_release,
+	}, 
+	
+};
+#endif
+
+static struct platform_driver vce_platform_driver = {
+	.driver = {
+		.name = DEVDRV_NAME_VCE,
+		.owner = THIS_MODULE,
+		.of_match_table = owl_vce_of_match,
+	},
+	.probe = vce_probe,
+	.remove = vce_remove,
+	.suspend = vce_suspend,
+	.resume = vce_resume,
+};
+
+static struct miscdevice vce_miscdevice = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = DEVDRV_NAME_VCE,
+	.fops = &vce_fops,
+};
+
+static int vce_init(void)
+{
+	int ret;
+
+	/*\D7Զ\AFinsmod\A3\ACע\B2\E1\C9豸*/
+	ret = misc_register(&vce_miscdevice);
+	if (ret) {
+		vce_err("register vce misc device failed!...\n");
+		goto err0;
+	}
+	vce_info("vce_init!(ic_type:0x%x)......\n",ic_type);
+
+#ifndef CONFIG_OF
+	ret = platform_device_register(&vce_platform_device);
+	if (ret) {
+		vce_err("register vce platform_device error!...\n");
+		goto err1;
+	}
+#endif
+
+	ret = platform_driver_register(&vce_platform_driver);
+	if (ret) {
+		vce_err("register vce platform driver error!...\n");
+		goto err2;
+	}
+
+	init_waitqueue_head(&vce_wait);
+
+	return 0;
+
+err2: 
+    
+#ifndef CONFIG_OF
+    platform_device_unregister(&vce_platform_device);
+err1:
+#endif
+
+	misc_deregister(&vce_miscdevice);
+
+err0: return ret;
+}
+
+static void vce_exit(void)
+{
+	vce_info("vce_exit!(ic_type:0x%x)......\n",ic_type);
+	misc_deregister(&vce_miscdevice);
+#ifndef CONFIG_OF
+	platform_device_unregister(&vce_platform_device);
+#endif
+	platform_driver_unregister(&vce_platform_driver);
+}
+
+late_initcall(vce_init);
+module_exit(vce_exit);
+
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/video/fbdev/owl/vce/vce_drv.h b/drivers/video/fbdev/owl/vce/vce_drv.h
new file mode 100755
index 0000000..8feeb89
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/vce_drv.h
@@ -0,0 +1,91 @@
+#ifndef __VCE_DRV__
+#define __VCE_DRV__
+
+/*
+*  driver including UPS and VCE
+*/
+enum {
+VCE_IDLE,
+VCE_BUSY,
+VCE_READY,
+VCE_ERR
+};
+
+enum {
+VCE_ERR_UNKOWN = -1,
+VCE_ERR_BUSY = -100,
+VCE_ERR_STM = -201,
+VCE_ERR_STM_FULL = -202,
+VCE_ERR_TIMEOUT = -203
+};
+
+typedef struct {
+	unsigned int vce_status;
+	unsigned int vce_cfg;
+	unsigned int vce_param0;
+	unsigned int vce_param1;
+	unsigned int vce_strm;
+	unsigned int vce_strm_addr;
+	unsigned int vce_yaddr;
+	unsigned int vce_list0;
+	unsigned int vce_list1;
+	unsigned int vce_me_param;
+	unsigned int vce_swindow;
+	unsigned int vce_scale_out;
+	unsigned int vce_rect;
+	unsigned int vce_rc_param1;
+	unsigned int vce_rc_param2;
+	unsigned int vce_rc_hdbits;
+	unsigned int vce_ts_info;
+	unsigned int vce_ts_header;
+	unsigned int vce_ts_blu;
+	unsigned int vce_ref_dhit;
+	unsigned int vce_ref_dmiss;
+
+	unsigned int ups_ctl;
+	unsigned int ups_ifs;
+	unsigned int ups_str;
+	unsigned int ups_ofs;
+	unsigned int ups_rath;
+	unsigned int ups_ratv;
+	unsigned int ups_yas;
+	unsigned int ups_cacras;
+	unsigned int ups_cras;
+	unsigned int ups_bct;
+	unsigned int ups_dab;
+	unsigned int ups_dwh;
+	unsigned int ups_sab0;
+	unsigned int ups_sab1;
+	unsigned int ups_rgb32_sr;
+	unsigned int ups_blend_w;
+	unsigned int input_fomat;
+}vce_input_t;
+
+typedef struct {
+	unsigned int vce_strm;
+	unsigned int vce_rc_param3;
+	unsigned int vce_rc_hdbits;
+	unsigned int strm_addr;
+	unsigned int i_ts_offset;
+	unsigned int i_ts_header;
+	unsigned int vce_ref_dhit;
+	unsigned int vce_ref_dmiss;
+}vce_output_t;
+
+typedef struct  {
+	int width;
+	int height;
+	unsigned long freq;
+}vce_multi_freq_t;
+
+#define VCE_DRV_IOC_MAGIC_NUMBER             'v'
+#define VCE_SET_ENABLE_CLK         _IO(VCE_DRV_IOC_MAGIC_NUMBER, 0x0)
+#define VCE_SET_DISABLE_CLK        _IO(VCE_DRV_IOC_MAGIC_NUMBER, 0x1)
+#define VCE_CMD_ENC_RUN            _IOW(VCE_DRV_IOC_MAGIC_NUMBER, 0x2,vce_input_t)
+#define VCE_CMD_QUERY_FINISH       _IOR(VCE_DRV_IOC_MAGIC_NUMBER, 0x3,vce_output_t)
+#define VCE_GET_ENC_STATUS         _IO(VCE_DRV_IOC_MAGIC_NUMBER, 0x4)
+#define VCE_SET_FREQ               _IOW(VCE_DRV_IOC_MAGIC_NUMBER, 0x5,vce_multi_freq_t)
+#define VCE_GET_FREQ               _IO(VCE_DRV_IOC_MAGIC_NUMBER, 0x6)
+#define VCE_CHECK_VERSION          _IO(VCE_DRV_IOC_MAGIC_NUMBER, 0x7)
+
+#endif
diff --git a/drivers/video/fbdev/owl/vce/vce_reg.h b/drivers/video/fbdev/owl/vce/vce_reg.h
new file mode 100755
index 0000000..af6fbc9
--- /dev/null
+++ b/drivers/video/fbdev/owl/vce/vce_reg.h
@@ -0,0 +1,55 @@
+#ifndef __VCE_REG_H__
+#define __VCE_REG_H__
+
+#define VCE_BASE_ADDR   0xB0288000/*GL5207/GL5202C:0xB0278000*/
+#define VCE_ID          (0)  /*0X78323634*/
+#define VCE_STATUS      (4)  /*swreg1*/
+#define VCE_CFG         (16) /*swreg4*/
+#define VCE_PARAM0      (20) /*swreg5*/
+#define VCE_PARAM1      (24)
+#define VCE_STRM        (28)
+#define VCE_STRM_ADDR   (32)
+#define VCE_YADDR       (36)
+#define VCE_LIST0_ADDR  (40)
+#define VCE_LIST1_ADDR  (44)
+#define VCE_ME_PARAM    (48) /*swreg12*/
+#define VCE_SWIN        (52)
+#define VCE_SCALE_OUT   (56)
+#define VCE_RECT        (60)
+#define VCE_RC_PARAM1   (64)
+#define VCE_RC_PARAM2   (68)
+#define VCE_RC_PARAM3   (72)
+#define VCE_RC_HDBITS   (76)
+#define VCE_TS_INFO     (80)
+#define VCE_TS_HEADER   (84)
+#define VCE_TS_BLUHD    (88)
+#define VCE_REF_DHIT    (92)
+#define VCE_REF_DMISS   (96)
+
+#define VCE_OUTSTANDING_7021 (8)
+#define UPS_YAS_7021         (120)
+#define UPS_CBCRAS_7021      (124)
+#define UPS_CRAS_7021        (128)
+#define UPS_IFORMAT_7021     (132)
+#define UPS_RATIO_7021       (140)
+#define UPS_IFS_7021         (144)
+
+#define UPS_BASE_7039      (VCE_BASE_ADDR + 0xc0)
+#define UPS_CTL_7039       (0xc0 + 0) /*swreg48*/
+#define UPS_IFS_7039       (0xc0 + 4)
+#define UPS_STR_7039       (0xc0 + 8)
+#define UPS_OFS_7039       (0xc0 + 12)
+#define UPS_RATH_7039      (0xc0 + 16)
+#define UPS_RATV_7039      (0xc0 + 20)
+#define UPS_YAS_7039       (0xc0 + 24)
+#define UPS_CBCRAS_7039    (0xc0 + 28)
+#define UPS_CRAS_7039      (0xc0 + 32)
+#define UPS_BCT_7039       (0xc0 + 36)
+#define UPS_DAB_7039       (0xc0 + 40)
+#define UPS_DWH_7039       (0xc0 + 44)
+#define UPS_SAB0_7039      (0xc0 + 48)
+#define UPS_SAB1_7039      (0xc0 + 52)
+#define UPS_RGB32_SR_7039  (0xc0 + 56)  /*swreg62*/
+#define UPS_BLEND_W_7039   (0xc0 + 60)  /*swreg63*/
+
+#endif
diff --git a/drivers/video/fbdev/owl/vde/Kconfig b/drivers/video/fbdev/owl/vde/Kconfig
new file mode 100755
index 0000000..6be12e9
--- /dev/null
+++ b/drivers/video/fbdev/owl/vde/Kconfig
@@ -0,0 +1,11 @@
+config VIDEO_ACTIONS_VDE
+	tristate "Asoc Video decoder support"
+	depends on ARCH_OWL
+	---help---
+	  Say Y here if you need video decoder support to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called vde_drv.ko.
+
diff --git a/drivers/video/fbdev/owl/vde/Makefile b/drivers/video/fbdev/owl/vde/Makefile
new file mode 100755
index 0000000..9f12af8
--- /dev/null
+++ b/drivers/video/fbdev/owl/vde/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_VIDEO_ACTIONS_VDE) += vde_drv.o
+
diff --git a/drivers/video/fbdev/owl/vde/vde_core.h b/drivers/video/fbdev/owl/vde/vde_core.h
new file mode 100755
index 0000000..210c8e0
--- /dev/null
+++ b/drivers/video/fbdev/owl/vde/vde_core.h
@@ -0,0 +1,188 @@
+#ifndef _VDE_CORE_H_
+#define _VDE_CORE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum VDE_REG_NO
+{
+    VDE_REG0 = 0,    
+    VDE_REG1 ,  VDE_REG2,  VDE_REG3,  VDE_REG4,  VDE_REG5,  VDE_REG6,  VDE_REG7,  VDE_REG8, 
+    VDE_REG9 , VDE_REG10, VDE_REG11, VDE_REG12, VDE_REG13, VDE_REG14, VDE_REG15, VDE_REG16,
+    VDE_REG17, VDE_REG18, VDE_REG19, VDE_REG20, VDE_REG21, VDE_REG22, VDE_REG23, VDE_REG24,
+    VDE_REG25, VDE_REG26, VDE_REG27, VDE_REG28, VDE_REG29, VDE_REG30, VDE_REG31, VDE_REG32,
+    VDE_REG33, VDE_REG34, VDE_REG35, VDE_REG36, VDE_REG37, VDE_REG38, VDE_REG39, VDE_REG40,          
+    VDE_REG41 ,VDE_REG42, VDE_REG43, VDE_REG44, VDE_REG45, VDE_REG46, VDE_REG47, VDE_REG48,
+    VDE_REG49, VDE_REG50, VDE_REG51, VDE_REG52, VDE_REG53, VDE_REG54, VDE_REG55, VDE_REG56,
+    VDE_REG57, VDE_REG58, VDE_REG59, VDE_REG60, VDE_REG61, VDE_REG62, VDE_REG63, VDE_REG64,
+    VDE_REG65, VDE_REG66, VDE_REG67, VDE_REG68, VDE_REG69, VDE_REG70, VDE_REG71, VDE_REG72,  
+    VDE_REG73, VDE_REG74, VDE_REG75, VDE_REG76, VDE_REG77, VDE_REG78, VDE_REG79, VDE_REG80,
+    VDE_REG81, VDE_REG82, VDE_REG83, VDE_REG84, VDE_REG85, VDE_REG86, VDE_REG87, VDE_REG88,
+    VDE_REG89, VDE_REG90, VDE_REG91, VDE_REG92, VDE_REG93, VDE_REG94, VDE_REG_MAX
+} VDE_RegNO_t;   
+
+
+#define MAX_VDE_REG_NUM         (VDE_REG_MAX+1)
+
+
+// \D7\F7Ϊһ\B8\F6backdoor, \CCṩ\B6\EE\CD\E2\B5IJ\CE\CA\FD\CA\E4\C8\EB\BDӿ\DA, ʹ\D3÷\BD\B7\A8\BA\CD\C5\E4\D6üĴ\E6\C6\F7\CE\DE\D2\EC
+#define CODEC_CUSTOMIZE_ADDR            (VDE_REG_MAX)
+#define CODEC_CUSTOMIZE_VALUE_PERFORMANCE  0x00000001
+#define CODEC_CUSTOMIZE_VALUE_LOWPOWER     0x00000002
+#define CODEC_CUSTOMIZE_VALUE_DROPFRAME    0x00000004
+#define CODEC_CUSTOMIZE_VALUE_MAX          0xffffffff
+
+
+typedef enum VDE_STATUS
+{
+    VDE_STATUS_IDLE                 = 0x1,   
+    VDE_STATUS_READY_TO_RUN,                // \B5\B1ǰinstance\D2Ѿ\ADִ\D0\D0run, \B5\ABvde\B1\BB\C6\E4\CB\FBinstanceռ\D3\C3
+    VDE_STATUS_RUNING,                      // \D5\FD\D4\DA\D4\CB\D0\D0
+    VDE_STATUS_GOTFRAME,                    // \D3\D0֡\CA\E4\B3\F6
+    VDE_STATUS_JPEG_SLICE_READY     = 0x100, // JPEG \BD\E2\C2\EBһ\B8\F6slice\CD\EA\B3\C9, \B4\CBʱ\B2\BB\C4ܱ\BB\C6\E4\CB\FBinstance\B4\F2\B6ϣ\ACֱ\B5\BDGOTFRAMEʱ\B2ſ\C9\D2Ա\BB\B4\F2\B6\CF
+    VDE_STATUS_DIRECTMV_FULL,               // h264 Direct mv buffer\B2\BB\B9\BB\D3\C3,\D0\E8Ҫ\D6\D8\D0\C2\C9\EA\C7\EB\D4\D9\C6\F4\B6\AF\BD\E2\C2\EB    
+    VDE_STATUS_STREAM_EMPTY,                // \C2\EB\C1\F7\CF\FB\BA\C4\CD꣬\D0\E8Ҫ\BC\CC\D0\F8\C5\E4\D6\C3\CA\FD\BE\DD\D4\D9\C6\F4\B6\AFVDE, 5202\B2\BB\D4\CA\D0\ED\B3\F6\CFִ\CB\C7\E9\BF\F6     
+    VDE_STATUS_ASO_DETECTED,                // \BC\EC\B2⵽h264 ASO, \D0\E8Ҫ\C8\ED\BC\FE\D7\F6\C9ʽ\E2\C2\EB\D4\D9\C6\F4\B6\AFvde, 5202\B2\BB\D4\CA\D0\ED\B3\F6\CFִ\CB\C7\E9\BF\F6
+    VDE_STATUS_TIMEOUT              = -1,   // timeout
+    VDE_STATUS_STREAM_ERROR         = -2,   // \C2\EB\C1\F7\B3\F6\B4\ED        
+    VDE_STATUS_BUS_ERROR            = -3,   // \B7\C3\CE\CAddr\B3\F6\B4\ED, \BF\C9\C4\DC\CA\C7\D2\F2Ϊ\C5\E4\D6õķ\C7\CE\EF\C0\ED\C1\AC\D0\F8\C4ڴ\E6
+    VDE_STATUS_DEAD                 = -4,   // vpx\B9\D2\C1ˣ\AC\CE޷\A8\C5\E4\D6\C3\C8κμĴ\E6\C6\F7, video\D6м\E4\BC\FE\D0\E8Ҫ\B9ر\D5\CB\F9\D3\D0instance    
+    VDE_STATUS_UNKNOWN_ERROR        = -0x100       // \C6\E4\CB\FB\B4\ED\CE\F3        
+} VDE_Status_t;
+
+
+typedef struct vde_handle 
+{    
+    // \B6\C1\BCĴ\E6\C6\F7
+    unsigned int (*readReg)(struct vde_handle*, VDE_RegNO_t);
+    
+    // д\BCĴ\E6\C6\F7, ״̬\BCĴ\E6\C6\F7(reg1)\D3\C9\C7\FD\B6\AFͳһ\B9\DC\C0\ED, \B2\BB\C4\DCд, \B7\B5\BB\D8-1\A3\BB
+    int (*writeReg)(struct vde_handle*, VDE_RegNO_t, const unsigned int);
+
+    // \C6\F4\B6\AF\BD\E2\C2\EB, \B7\B5\BB\D8-1\A3\AC\B1\EDʾvde״̬\B4\ED\CE󣬲\BB\C4\DC\C6\F4\B6\AF;
+    int (*run)(struct vde_handle*);
+    
+    // \B2\E9ѯVDE״̬\A3\AC\B2\BB\D7\E8\C8\FB\B0汾\A3\ACvde\D5\FD\D4\DA\D4\CB\D0з\B5\BB\D8VDE_STATUS_RUNING
+    int (*query)(struct vde_handle*, VDE_Status_t*);    
+    
+    // \B2\E9ѯVDE״̬, \D7\E8\C8\FB\B0汾, ֱ\B5\BDVDE_STATUS_DEAD\BB\F2\D5\DFVDE\D6жϲ\FA\C9\FA, \B7\B5\BB\D8ֵ\BC\FBVDE_Status_t
+    int (*query_timeout)(struct vde_handle*, VDE_Status_t*);    
+    
+    // \BD\AB״̬תΪidle
+    int (*reset)(struct vde_handle*);   
+    
+} vde_handle_t;
+
+// \BB\F1ȡ\BE\E4\B1\FA. \B2\CE\CA\FD\B4\ED\CE\F3\BB\F2\D5ߴﵽ\D7\EE\B4\F3\B5\C4\D4\CB\D0\D0instance\B8\F6\CA\FD\A3\AC\B7\B5\BB\D8NULL;     
+vde_handle_t *vde_getHandle(void);
+
+// \B9رվ\E4\B1\FA    
+void vde_freeHandle(struct vde_handle*);
+
+// DEBUG, \B4\F2\BF\AA\C4ڲ\BF\B4\F2ӡ
+void vde_enable_log(void);
+
+// DEBUG, \B9ر\D5\C4ڲ\BF\B4\F2ӡ
+void vde_disable_log(void);
+
+// DEBUG \BB\F1ȡ\B5\B1ǰ\D4\CB\D0е\C4instance\D0\C5Ϣ\BA\CD\CB\F9\D3мĴ\E6\C6\F7\D0\C5Ϣ, \B5\A5\B4\CE\D3\D0Ч
+void vde_dump_info(void);
+
+
+
+/**********************************************************
+\C9\E8\BC\C6\C1\F7\B3\CC:  vd_h264.so  ----> libvde_core.so ----> vde_drv.ko
+
+\CF\DE\D6\C6\CC\F5\BC\FE\A3\BA \B2\BB\C4ܿ\E7\BD\F8\B3\CCʹ\D3ã\AC\BC\B4\B2\BBͬinstance\B1\D8\D0\EB\CA\C7\D4\DAͬһ\B8\F6\BD\F8\B3\CC\D6С\A3
+
+ʹ\D3÷\BD\B7\A8\A3\BA
+    Android.mk\D6\D0\D4\F6\BC\D3 LOCAL_SHARED_LIBRARIES := libvde_core
+    \B1\E0\D2\EBʱ\BB\E1\D7Զ\AF\C1\AC\BD\D3libvde_core.so, \BEͿ\C9\D2\D4\D7Զ\AF\BC\D3\D4\D8so, ʹ\D3\C3api\BA\AF\CA\FD, \B2\BB\D0\E8Ҫֱ\BDӵ\F7\D3\C3vde_drv.ko
+
+\B6\EE\CD\E2˵\C3\F7:  reg1(status\BCĴ\E6\C6\F7\A3\A9\B2\BB\C4\DCд
+
+Example code\A3\BA
+
+    int vde_close(void *codec_handle)
+    {
+        // ...
+        vde_freeHandle(codec_handle->vde_handle);
+        codec_handle->vde_handle = NULL;
+        // ...        
+    }
+    
+    int vde_init(void *codec_handle)
+    {
+        codec_handle->vde_handle == vde_getHandle();
+        if(codec_handle->vde_handle == NULL) return -1;
+        
+        if(DEBUG)
+            vde_enable_log();           
+        
+        // if you need to know about overload of VDE;
+        vde_dump_info();
+                
+        return 0;
+    }
+    
+    int vde_decode_one_frame(void *codec_handle)
+    {
+        int rt;        
+        unsigned int value;
+        int status;
+        
+        vde_handle_t *vde = codec_handle->vde_handle;                
+                      
+        vde->reset(vde);      
+        
+        value = vde->readReg(vde, REG10);                
+        value &= 0x2;
+        
+        rt = vde->writeReg(vde, REG10, value);
+        if(rt) goto SOMETHING_WRONG;
+        
+        rt = vde->run(vde);
+        if(rt) goto SOMETHING_WRONG;          
+                        
+#if USE_QUERY 
+        // \CB\C0\B2飬Ч\C2ʵ\CD    
+        while(timeout_ms < 10000)        
+            rt = vde->query(vde, &status);
+            if(rt) return -1;
+            
+            if(status != VDE_STATUS_RUNING && status != VDE_STATUS_IDLE) 
+                break;               
+        }
+#else                
+        // dosomthing else, \D4\D9\C0\B4\B2飬\C4ڲ\BF\D3\D0\C8\CE\CE\F1\B5\F7\B6ȣ\AC\BF\C9\CC\E1\B8\DFcpu\C0\FB\D3\C3\C2\CA
+        rt = vde->query_timeout(vde, &status);
+        if(rt) goto SOMETHING_WRONG;
+
+#endif
+        
+        if(status == VDE_STATUS_GOTFRAME) {                
+            return 0;
+        } else {
+            goto SOMETHING_WRONG;
+        }           
+           
+SOMETHING_WRONG:
+        
+        if(status == VDE_STATUS_DEAD) {
+            ACTAL_ERROR("VDE Died");            
+            return -1; //fatal error here.
+        } else {
+            ACTAL_ERROR("something wrong, check your code")
+            return -1;
+        }       
+                   
+    }
+
+**********************************************************/
+#ifdef __cplusplus
+}
+#endif
+
+#endif//_VDE_CORE_H_
+
diff --git a/drivers/video/fbdev/owl/vde/vde_drv.c b/drivers/video/fbdev/owl/vde/vde_drv.c
new file mode 100755
index 0000000..1ee7908
--- /dev/null
+++ b/drivers/video/fbdev/owl/vde/vde_drv.c
@@ -0,0 +1,1966 @@
+#include <linux/module.h>
+#include <linux/kernel.h>   /* printk() */
+#include <linux/errno.h>    /* error codes */
+#include <linux/vmalloc.h>
+#include <linux/slab.h>     /* kmalloc/kfree */
+#include <linux/init.h>     /* module_init/module_exit */
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/spinlock.h>
+#include <linux/sem.h>
+#include <linux/platform_device.h>
+#include <linux/time.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <linux/delay.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <asm/uaccess.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/of_device.h>
+#include <linux/io.h>
+#include <linux/regulator/consumer.h>
+
+#define ENABLE_COOLING 1
+#ifdef ENABLE_COOLING 
+#include <linux/cpu_cooling.h>
+#endif
+#define IC_TYPE_GL5203	 0x5203 // add macro to diff 5202 and 5203 IC
+#define IC_TYPE_GL5206	 0x5206 // add macro to diff 5202 and 5206 IC
+
+#ifndef IC_TYPE_GL5203
+#include <mach/clock.h>
+#include <mach/powergate.h>
+#include <mach/leopard_cpufreq.h>
+#include <mach/atc260x/atc260x.h>
+#include <mach/dma.h>
+#include <mach/gl5202_cmu.h>  
+#else
+#include <mach/module-owl.h>
+#include <mach/clkname.h>
+#include <mach/powergate.h>
+#include <mach/clock-owl.h>
+#endif
+
+#include "vde_core.h"
+#include "vde_drv.h"
+#define VDE_FREQ_EXTREME 			642 //for test only
+
+#define VDE_DRV_USE_SYSFS
+#define VDE_REG_BACKUP_NUM  		47
+#define VDE_INTTERUPT_MODE
+
+#define DEVDRV_NAME_VDE             "mali0" // "vde"       //device_driver.h
+#define DEV_CLK_INTERFACE_VDE_BIT   25
+
+#define VDE_REGISTER_BASE       	0xb0280000
+#define OWL_IRQ_VDE            		82 
+#define VDE_REG_BASE                VDE_REGISTER_BASE
+#define CMU_REG_BASE                CMU_CONTROL_REGISTER_BASE
+#define VDE_REG_STATUS              ((VDE_REG_BASE) + 0x4)
+#define VDE_REG_4                   ((VDE_REG_BASE) + 0x10)
+
+// 20141023 : set 5206 pll and clock source
+#define VDE_FREQ_DEFAULT 			300
+#define VDE_FREQ_D1      			150
+#define VDE_FREQ_720P    			240
+#define VDE_FREQ_1080P   			300
+#define VDE_FREQ_MULTI   			480 
+#define VDE_FREQ_4Kx2K   			600 
+
+#ifdef IC_TYPE_GL5203
+#define CLK_NAME_DEVPLL				CLKNAME_DEVPLL
+#define CLK_NAME_NANDPLL			CLKNAME_NANDPLL
+#define CLK_NAME_DISPLAYPLL			CLKNAME_DISPLAYPLL
+#define CLK_NAME_DDRPLL				CLKNAME_DDRPLL
+
+#define CLK_NAME_DEVCLK				CLKNAME_DEV_CLK
+#define CLK_NAME_VDE_CLK			CLKNAME_VDE_CLK
+#endif
+
+#ifdef IC_TYPE_GL5206
+void __iomem *Share_Mem_REG;
+#endif
+
+/*
+ SPS_PG_CTL,b0 VDE power on enable
+ VDE_CMU_VDE_CLK, VDE clock source and division
+ VDE_CMU_DEVCLKEN0, 25bit,VDE interface clock enable, switch AHB clock and VDE_CLK
+ VDE_CMU_DEVRST0, 19bit, VDE control block reset
+ */
+unsigned int sps_base = 0;
+unsigned int cmu_base = 0;
+void __iomem *VDE_SPS_PG_CTL;
+void __iomem *VDE_CMU_DEVRST0;
+void __iomem *VDE_CMU_DEVCLKEN0;
+void __iomem *VDE_CMU_VDE_CLK;
+void __iomem *VDE_CMU_COREPLL;
+              
+typedef struct {
+    unsigned int regs[VDE_REG_BACKUP_NUM];
+} vde_user_data_t;
+
+#define VDE_DEBUG_PRINTK    printk("%s %d\n",__FILE__,__LINE__)
+
+struct asoc_vde_dev {
+    struct device   *dev;
+    void __iomem    *base;
+    struct clk      *clk;
+    int             irq;
+    unsigned int    setting;
+	struct regulator *power;
+
+};
+struct asoc_vde_dev *gVDE;
+
+static void vde_write(struct asoc_vde_dev *vde, u32 val, u32 reg)
+{
+    void volatile *write_add = (void*)((unsigned int)vde->base + reg);
+    writel_relaxed(val, write_add);
+}
+
+static u32 vde_read(struct asoc_vde_dev *vde, u32 reg)
+{
+    unsigned int data = 0;   
+    data = readl_relaxed((void volatile *)((unsigned int)vde->base + reg));
+    return data;
+}
+
+typedef enum {SLOT_IDLE, SLOT_OCCUPIED, SLOT_COMPLETED} slot_state_e;
+
+
+#define VDD_0_9V     900000
+#define VDD_1_0V    1000000
+#define VDD_1_05V   1050000
+#define VDD_1_1V    1100000
+#define VDD_1_15V   1150000
+#define VDD_1_2V    1200000
+
+typedef struct slot_s{
+    struct completion isr_complete;
+    slot_state_e state;
+    unsigned int clientRegPtr;
+    unsigned int vde_status;
+    unsigned int slice_mode;
+    int pid;
+    vde_user_data_t user_data;
+} slot_t;
+
+static int vde_cur_slot_id = -1;
+static int vde_slice_slot_id = -1;
+static unsigned int vde_cur_slot_num = 0;
+static int vde_set_voltage_limit=0;
+static int vde_last_status = 0; // 0:normal, -1:error;
+
+static int multi_instance_mode = 0;
+static int debug_enable = 0;
+static int autoFreq_enable = 1;
+static int vde_pre_freq = 0;
+static int adjust_freq_flag = 1;
+static int ic_type = IC_TYPE_GL5203;
+
+#define VDE_DBG(...)     if(debug_enable==1) {printk(__VA_ARGS__);}
+#define VDE_DBG2(...)     if(debug_enable==2) {printk(__VA_ARGS__);}
+
+#define MAX_INSTANCE_NUM 8
+static slot_t slot[MAX_INSTANCE_NUM];
+
+static int slot_reset(int i) {   
+    init_completion(&slot[i].isr_complete);
+    slot[i].state = SLOT_IDLE; 
+    slot[i].clientRegPtr = 0; 
+    slot[i].slice_mode = 0;  
+    slot[i].pid = -1; 
+    if(vde_cur_slot_num > 0) 
+       vde_cur_slot_num--;
+    
+    return 0;
+}
+
+static int slot_get(void) 
+{        
+    int i;
+    for(i=0;i<MAX_INSTANCE_NUM;i++) {    
+        if(slot[i].state == SLOT_IDLE) {    
+            init_completion(&slot[i].isr_complete);   
+            slot[i].state = SLOT_OCCUPIED;
+            vde_cur_slot_num++;
+            slot[i].pid = task_tgid_vnr(current);
+            return i;
+        }
+    }
+		
+    if(i == MAX_INSTANCE_NUM){
+        printk("vde : no idle slot, max %d slots\n", MAX_INSTANCE_NUM);
+        return -1;
+    }
+    return -1;
+}
+struct ic_info {
+	int ic_type;
+};
+
+static struct ic_info  gl5203_data = {
+   .ic_type = IC_TYPE_GL5203,
+};
+ 
+static  struct ic_info gl5206_data = {
+   .ic_type = IC_TYPE_GL5206,
+};
+
+
+static const struct of_device_id gl520x_vde_of_match[] = {
+
+         {.compatible = "actions,atm7039c-vde", .data = &gl5203_data},
+
+         {.compatible = "actions,atm7059a-vde", .data = &gl5206_data},
+
+         {}
+};
+
+MODULE_DEVICE_TABLE(of, gl520x_vde_of_match);
+
+static int slot_complete(int i, unsigned int vde_status) 
+{        
+    if(slot[i].state != SLOT_OCCUPIED) {
+        printk("vde : slot is idle, staus error\n");
+        return -1;
+    }  
+    
+    slot[i].vde_status = vde_status;
+    slot[i].state = SLOT_COMPLETED;
+    return 0;
+}
+
+static int vde_irq_registered = 0;
+static int vde_open_count = 0;
+static unsigned long vde_cur_need_freq = 0;
+static int vde_occupied = 0;
+
+//for multi process
+static struct mutex m_mutex;
+static struct mutex m_freq_adjust_mutex;
+static DECLARE_WAIT_QUEUE_HEAD(waitqueue);
+static int vde_idle_flag = 1;
+static int vde_clk_isEnable = 0;
+
+#ifdef IC_TYPE_GL5203
+
+/* calculate VDE clk's divider  */
+static int vde_calculate_divider(unsigned long parent_pll, unsigned long rate)
+{
+	unsigned long clk_left, clk_right;
+	int tmp_divider;
+	if (parent_pll < rate) {
+		return 1;
+	}
+	
+	tmp_divider = parent_pll/rate;
+	tmp_divider = (tmp_divider>0) ? tmp_divider : 1;
+	clk_left = parent_pll/(tmp_divider + 1);
+	clk_right = parent_pll/tmp_divider;
+	if (rate == clk_right) {
+		return tmp_divider;
+	}
+	
+	if ((rate - clk_left) < (clk_right - rate)) {
+		return (tmp_divider + 1);
+	}else {
+		return tmp_divider;
+	}
+}
+
+static int vde_clk_notify(struct notifier_block *nb, unsigned long action, void *data)
+{
+	struct clk_notifier_data *cnd;
+	struct clk *vde_clk;
+	unsigned long rate;
+	unsigned long old_parent_rate, new_parent_rate;
+	
+	int old_divider, new_divider, old_divide_ratio, new_divide_ratio;
+	int ret, pll_is_changed;
+	
+	if (action == PRE_RATE_CHANGE) {
+		cnd = data;
+		
+		vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+		if (vde_clk != cnd->clk) {
+			printk("vde : notify_pre: vde_limit_notify: wrong vde clk value, and NOTIFY_BAD \n");
+			return NOTIFY_BAD;
+		}
+		
+		// 1. get cur parent pll or clk
+		old_parent_rate = owl_get_putaway_parent_rate(vde_clk);
+		new_parent_rate = owl_getparent_newrate(vde_clk);
+		pll_is_changed = owl_pll_in_change();
+		
+		if(pll_is_changed == 0 || new_parent_rate == 0)
+      			return NOTIFY_OK;
+
+		new_parent_rate = ((new_parent_rate == 0) &&(pll_is_changed == 0)) ? old_parent_rate : new_parent_rate;
+			
+		// 2. get divsion encoder, divider  must = 1/2/3/4(> 0), if not, owl_getdivider_index will return -1
+ 		old_divider = old_parent_rate/cnd->old_rate;
+		old_divide_ratio = owl_getdivider_index(vde_clk, old_divider);
+		new_divider = vde_calculate_divider(new_parent_rate, vde_cur_need_freq);
+		new_divide_ratio = owl_getdivider_index(vde_clk, new_divider);
+		
+		// 3. set dicsion
+		ret = owl_set_putaway_divsel(vde_clk, old_divide_ratio, new_divide_ratio);
+		if (ret == -1) {
+			printk("vde : notify_pre: owl_set_putaway_divsel() failed \n");
+		}
+
+		rate = new_parent_rate/new_divider;
+		rate = (rate > 0) ? rate : vde_cur_need_freq;
+		owl_update_notify_newrate(vde_clk, rate);
+	} else if (action == POST_RATE_CHANGE) {
+		cnd = data;
+	}else if (action == ABORT_RATE_CHANGE) {
+		cnd = data;
+		printk("vde : notify_abort: ABORT_RATE_CHANGE: rate: [%ld, %ld]\n", cnd->old_rate, cnd->new_rate);
+	}
+
+	return NOTIFY_OK;
+}
+
+#if 1 // only for dump jpeg reg when decoder stream error
+static void vde_dump(void)
+{
+	int i;
+	printk("vde : vde_dump In\n");
+	printk("[sps_pg_ctl, 0x%08x]", readl_relaxed(VDE_SPS_PG_CTL));  //sps_pg_ctl
+	printk("[cmu_devclken0, 0x%08x]", readl_relaxed(VDE_CMU_DEVCLKEN0)); //cmu_devclken0
+	printk("[cmu_devrst0, 0x%08x], ", readl_relaxed(VDE_CMU_DEVRST0)); //cmu_devrst0
+	printk("[vde_clk, 0x%08x] \n", readl_relaxed(VDE_CMU_VDE_CLK)); //cmu_vde_clk
+	for(i=0; i < 47; i++) {
+		if (i % 8 == 0) {
+			printk("0x%08x: ", VDE_REG_BASE + (i<<2));
+		}
+		//printk("[%02d, 0x%08x], ", i, act_readl(VDE_REG_BASE + (i<<2)));
+		//printk("%08x ", act_readl(VDE_REG_BASE + (i<<2)));
+		printk("%08x ", vde_read(gVDE,(i<<2)));
+		if (i % 8 == 7) {
+			printk("\n");
+		}
+    }
+	printk("\n");
+	printk("vde : vde_dump Out\n");
+}
+
+static void vde_dump_pre(int slotId)
+{
+	int i;
+	printk("vde : vde_dump_pre In\n");
+	printk("[sps_pg_ctl, 0x%08x]", readl_relaxed(VDE_SPS_PG_CTL));  //sps_pg_ctl
+	printk("[cmu_devclken0, 0x%08x]", readl_relaxed(VDE_CMU_DEVCLKEN0)); //cmu_devclken0
+	printk("[cmu_devrst0, 0x%08x], ", readl_relaxed(VDE_CMU_DEVRST0)); //cmu_devrst0
+	printk("[vde_clk, 0x%08x] \n", readl_relaxed(VDE_CMU_VDE_CLK)); //cmu_vde_clk
+	for(i=0; i < 47; i++) {
+		if (i % 8 == 0) {
+			printk("0x%08x: ", slot[slotId].user_data.regs[i]);
+		}
+		
+		printk("%08x ", slot[slotId].user_data.regs[i]);
+		if (i % 8 == 7) {
+			printk("\n");
+		}
+    	}
+
+	printk("\n");
+	printk("vde : vde_dump_pre Out\n");
+}
+
+static void vde_dump_ddr(int id)
+{
+	int i;
+	unsigned int * v_addr = NULL;
+	int addr = vde_read(gVDE, (id<<2));
+	if (addr == 0) {
+		printk("vde : vde_dump_ddr, In: id = %d, addr = 0x%08x, return.\n", id, addr);
+		return ;
+	}
+	
+	printk("vde : vde_dump_ddr, In: id = %d, addr = 0x%08x(0x%08x)\n", id, addr, addr & 0xFFFFFFFC);
+	addr =  addr & 0xFFFFFFFC;
+	
+	v_addr = (unsigned int * )ioremap(addr, 2048);
+	
+	for(i=0; i < 512; i++) { // will read 2K bytes
+		if (i % 8 == 0){
+			printk("0x%08x: ", (unsigned int)&v_addr[i]);
+		}
+		printk("%08x ", v_addr[i]);
+		if (i % 8 == 7){
+			printk("\n");
+		}
+    	}
+
+	printk("\n");
+	if (v_addr != NULL) {
+		iounmap(v_addr);
+		v_addr = NULL;
+	}
+	printk("vde : vde_dump_ddr Out\n");
+}
+#endif
+
+#endif // IC_TYPE_GS5203
+
+static int vde_query_interval(unsigned int reg4)
+{
+    unsigned int mb_w = (reg4 >> 23)&0x1ff;
+    unsigned int mb_h = (reg4 >> 15)&0xff;
+    unsigned int r = (mb_w *mb_h * 300)/(1000 * vde_pre_freq);
+    if(r < 5) {
+	r = 5;
+    }
+    return r;
+}
+
+static void vde_waitForIdle(void)
+{
+   int ctr=0;
+   int v = vde_read(gVDE, 0x4);//VDE_REG_STATUS
+   int v4 = vde_read(gVDE, 0x10);//VDE_REG_4
+ 
+   if((v&0x1) == 0x1) {
+      VDE_DBG("vde : vde is on air\n");
+      do{
+        msleep(vde_query_interval(v4));
+        ctr++;
+        if(ctr==100){
+           printk("vde : vde always busy\n");         
+           break;
+        }
+      } while(((vde_read(gVDE, 0x4)&0x1)) == 0x1);
+   }    
+}
+
+static int is_rlc_mode(unsigned int reg4)
+{
+    if(((reg4>>12) & 0x7) == 0x3)    
+        return 0;
+    return (reg4>>3)&0x1;
+}
+
+int get_mode(void)
+{
+    unsigned int v = act_readl(VDE_REG_4);   
+    if(((v>>12)&0x7) == 0x3) {        
+        return 1;
+    }   
+    if(is_rlc_mode(v)) {     
+        return 1;
+    }   
+    return 0;
+}
+
+#ifdef IC_TYPE_GL5203 
+/* when decoder finished, reset parent pll(Displaypll) = 720M */
+static void vde_reset_parent_pll(void)
+{
+	struct clk *pll_clk;
+	struct clk *vde_clk;
+	int ret;
+	unsigned long vde_rate, pll_rate;
+	
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+	pll_clk = clk_get_sys(NULL, (const char *)CLK_NAME_DISPLAYPLL);
+
+	vde_rate = clk_get_rate(vde_clk);
+	pll_rate = clk_get_rate(pll_clk);
+	
+	if ((vde_rate == VDE_FREQ_4Kx2K) && (pll_rate == VDE_FREQ_4Kx2K)) {
+		printk("vde : vde_reset_displaypll: vde: %lu displaypll: %lu\n", vde_rate, pll_rate);
+		vde_waitForIdle();
+		ret = clk_set_rate(pll_clk, 720000000);
+		if(ret != 0) {
+			printk("vde : set displaypll rate 720M,  failed!\n");
+			return ;       
+		}
+		clk_put(pll_clk);
+	}
+	
+	return;
+}
+#endif
+
+static void vde_do_reset(void) 
+{
+	int ctor = 0;
+	unsigned int value_assigned;  
+	unsigned int vde_state = vde_read(gVDE,0x4);//VDE_REG_STATUS
+
+	// avoid reset vde when vde is working
+	while((vde_state & 0x1) == 0x1) {
+		msleep(5);
+		
+		vde_state = vde_read(gVDE,0x4);//VDE_REG_STATUS
+		if (vde_state & 0xda000) {
+			printk("vde : warning, reset vde when working wrong. state: 0x%x\n", vde_state);
+			break;
+		}
+		if (ctor > 10) {
+			printk("vde : warning, reset vde when working. state: 0x%x, ctor(%d) > 10\n", vde_state, ctor);
+			break;
+		}
+		
+		ctor ++;
+	}
+	
+#ifndef IC_TYPE_GL5203 
+	struct clk *vde_clk;           
+	vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+	if (IS_ERR(vde_clk)){
+	printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+	return;      
+	} 
+
+	clk_reset(vde_clk);  
+#else
+	
+	module_reset(MOD_ID_VDE);
+
+	VDE_DBG("vde : %d checking reset .............\n", __LINE__);
+	value_assigned = readl_relaxed(VDE_CMU_DEVRST0);    
+
+	while(((value_assigned>>19) & 0x1) != 0x1) {      
+		printk("vde : Fail to reset vde, DEVEN0 = 0x%x,CMU_DEVRST0 = 0x%x PG_CTL = 0x%x\n", \
+						readl_relaxed(VDE_CMU_DEVCLKEN0), \
+						readl_relaxed(VDE_CMU_DEVRST0), readl_relaxed(VDE_SPS_PG_CTL));
+
+		value_assigned |= (0x1<<19);
+		writel_relaxed(value_assigned, VDE_CMU_DEVRST0);
+		usleep_range(50*1000, 50*1000);
+		value_assigned = readl_relaxed(VDE_CMU_DEVRST0);        
+	}
+#endif 
+		 
+	vde_idle_flag = 1;
+	vde_occupied = 0;    
+	vde_last_status = 0;
+
+	return;
+}
+
+static void vde_reset(void)
+{
+    usleep_range(5*1000,5*1000);
+    vde_do_reset();
+} 
+
+static void vde_power_on(void)
+{    
+	owl_powergate_power_on(OWL_POWERGATE_VDE); 
+	vde_reset();
+}
+
+static void vde_power_off(void)
+{    
+	owl_powergate_power_off(OWL_POWERGATE_VDE);
+}
+#ifdef IC_TYPE_GL5206
+static void share_mem_reg_enable(void)
+{
+	unsigned int value,value1;
+	
+	value = readl_relaxed(Share_Mem_REG);
+	value = value & (~0x2);	
+
+	writel_relaxed(value,Share_Mem_REG);
+	value1 = readl_relaxed(Share_Mem_REG);	
+}
+
+static void share_mem_reg_disable(void)
+{
+	unsigned int value,value1;
+	value = readl_relaxed(Share_Mem_REG);
+	value = value | 0x2;
+	writel_relaxed(value,Share_Mem_REG);
+	value1 = readl_relaxed(Share_Mem_REG);
+}
+#endif
+/* Enable VDE CLK */
+static void vde_clk_enable(void)
+{   
+	struct clk *vde_clk; 
+
+	if(vde_clk_isEnable!=0) {
+		return;
+	}
+
+#ifndef IC_TYPE_GL5203
+	vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+	if (IS_ERR(vde_clk)){
+		printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return;      
+	} 
+
+	clk_enable(vde_clk);  
+#else   
+
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+	if (IS_ERR(vde_clk)){
+		printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return;      
+	} 
+
+	clk_prepare(vde_clk); 
+	clk_enable(vde_clk); 
+	clk_put(vde_clk);
+	
+
+	module_clk_enable(MOD_ID_VDE);
+#endif
+	
+	vde_power_on();
+	vde_clk_isEnable = 1;
+}
+
+static void vde_clk_disable(void)
+{    
+	struct clk *vde_clk; 
+	
+	VDE_DBG("vde : vde_clk_disable, In\n");
+	if(vde_clk_isEnable == 0) {
+		return;
+	}
+
+	vde_waitForIdle(); 
+
+#ifndef IC_TYPE_GL5203
+	vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+	if (IS_ERR(vde_clk)) {
+		printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return;      
+	} 	
+	clk_disable(vde_clk);
+#else 
+	module_clk_disable(MOD_ID_VDE);
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+	if (IS_ERR(vde_clk)) {
+		printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return;      
+	} 	
+
+	clk_disable(vde_clk);
+	clk_unprepare(vde_clk);
+	clk_put(vde_clk);
+
+	vde_reset_parent_pll();
+#endif 
+
+	vde_power_off();
+	vde_clk_isEnable = 0;
+	VDE_DBG("vde : vde_clk_disable, Out\n");
+}
+
+// =------==============================================================
+
+#define MAX_VDE_REG_RETRY_TIME  5
+/* enable int */
+static inline void enable_vde_irq(void)
+{
+}
+    
+static inline void disable_vde_irq(void)
+{    
+	unsigned int v = vde_read(gVDE,0x4);//VDE_REG_STATUS 
+	int c = MAX_VDE_REG_RETRY_TIME;  
+
+	v &= ~(1<<8);
+	vde_write(gVDE,v,0x4);//Wr_Reg(VDE_REG_STATUS, v)
+	
+	while((vde_read(gVDE,0x4)) & (0x1<<8) && c-->0){
+	    	printk("vde : can not disable irq, write %x %x\n", VDE_REG_STATUS, vde_read(gVDE,0x4));
+	  	vde_write(gVDE,v,0x4);//Wr_Reg(VDE_REG_STATUS, v);
+	}
+}
+
+static void vde_drv_updateReg(int id)
+{
+    int i;
+    // we never handle reg0, reg1
+    for(i=1; i < VDE_REG_BACKUP_NUM; i++){
+        slot[id].user_data.regs[i] = (unsigned int)(vde_read(gVDE,i*4));
+    }
+}
+
+static void vde_drv_showReg(int id)
+{
+    if(id>=0) {
+        VDE_DBG("vde : (showReg-1) 0x%08x 0x%08x 0x%08x 0x%08x\n", 
+					slot[id].user_data.regs[1], slot[id].user_data.regs[2],
+         			slot[id].user_data.regs[3], slot[id].user_data.regs[4]);                      
+    }else{
+        VDE_DBG("vde : (showReg-2) 0x%08x 0x%08x 0x%08x 0x%08x\n", 
+        			(unsigned int)(vde_read(gVDE,1*4)), (unsigned int)(vde_read(gVDE,2*4)),
+        			(unsigned int)(vde_read(gVDE,3*4)), (unsigned int)(vde_read(gVDE,4*4)));        
+    }
+}
+
+/**
+ * This function is vde ISR.
+ */
+irqreturn_t vde_ISR(int irq, void *dev_id)
+{
+	disable_vde_irq();      
+	slot_complete(vde_cur_slot_id, vde_read(gVDE,0x4));//VDE_REG_STATUS
+	vde_drv_updateReg(vde_cur_slot_id);
+	
+	{
+		unsigned int s ;
+		s = vde_read(gVDE,0x4);//VDE_REG_STATUS
+		if(((s & (0x1<<17)) || (s & (0x1<<14))) && !(s & (0x1<<12))){        
+			slot[vde_cur_slot_id].slice_mode = 1;        
+			vde_slice_slot_id = vde_cur_slot_id;
+			slot[vde_slice_slot_id].state = SLOT_OCCUPIED;
+		}else {       
+			slot[vde_cur_slot_id].slice_mode = 0; 
+			vde_occupied = 0;
+		}
+	
+		slot[vde_cur_slot_id].vde_status = vde_read(gVDE,0x4);//VDE_REG_STATUS;
+		vde_idle_flag = 1;
+		
+		if(slot[vde_cur_slot_id].vde_status & 0xda000) { // when meet some error.
+			vde_drv_showReg(-1);
+			vde_last_status = -1;
+		}else{
+			//only if decoding normally, enable clk gating when decoder one frame.
+			unsigned int r2 = vde_read(gVDE,0x8);
+			r2 |= (0x1 << 10);
+			vde_write(gVDE,r2,0x8);
+		}
+	}
+
+	complete(&(slot[vde_cur_slot_id].isr_complete)); 	
+    	wake_up_interruptible(&waitqueue);
+
+	return IRQ_HANDLED;
+}
+
+static void vde_drv_writeReg(unsigned int regNo, unsigned int value)
+{       
+    unsigned int value_recover;
+    vde_write(gVDE,value,regNo*4);
+
+    value_recover = (unsigned int)(vde_read(gVDE,regNo*4));    
+    while(value_recover != value) {      
+        printk("vde : Fail to write reg 0x%x, (input,recover)=(0x%x, 0x%x), DEVEN0 = 0x%x,RST = 0x%x PG_CTL = 0x%x\n", \
+                        regNo, value, value_recover, readl_relaxed(VDE_CMU_DEVCLKEN0), \
+                        readl_relaxed(VDE_CMU_DEVRST0), readl_relaxed(VDE_SPS_PG_CTL));
+        vde_write(gVDE,value,regNo*4);
+        value_recover = (unsigned int)(vde_read(gVDE,regNo*4));
+    }
+}
+
+static void vde_drv_flushReg(int id, void __user *v)
+{
+	int i, rt; 
+#ifdef IC_TYPE_GL5203
+	unsigned int value, tmpval;
+	unsigned int width;
+	unsigned int mode;
+#endif
+
+	rt = copy_from_user(&(slot[id].user_data.regs[0]), v, sizeof(vde_user_data_t));
+	if(rt != 0) {
+		printk("vde : Warning: copy_from_user failed, rt=%d\n",rt);
+	}
+
+#ifdef IC_TYPE_GL5203
+	value = slot[id].user_data.regs[2];   
+	tmpval = slot[id].user_data.regs[4];  
+	width = ((tmpval >> 23) & 0x1ff) << 4;
+	mode = (tmpval >> 12) & 0x7;
+
+#ifdef IC_TYPE_GL5206
+	value &= (~(1<<23));
+#else
+	if (mode == 0) { // H264 all not only 4K &&((width > 2048))
+		value |= (1<<23); // enable timeout interrupt  ---  condition 1: enable timeout
+	}else {
+		value &= (~(1<<23));
+	}
+#endif
+	value &= (~(1<<10)); //disable clock gating
+	value &= (~(0xff));
+	slot[id].user_data.regs[2] = value; 
+#endif
+
+	// we never handle reg0, reg1
+	for(i=2; i < VDE_REG_BACKUP_NUM; i++) {
+		vde_drv_writeReg(i, slot[id].user_data.regs[i]);
+	}
+}
+
+VDE_Status_t vde_query_status(unsigned int vde_status)
+{
+	if(vde_status & (0x1<<12)) {        
+		VDE_DBG("vde : vde status gotframe, status: 0x%x\n", vde_status);
+		return VDE_STATUS_GOTFRAME;
+	} else if(vde_status & (0x1<<19)) {
+		VDE_DBG("vde : vde status directmv full, status: 0x%x\n", vde_status); 
+		return VDE_STATUS_DIRECTMV_FULL;
+	} else if(vde_status & (0x1<<18)) {
+		VDE_DBG("vde : vde status timeout, status: 0x%x\n", vde_status);
+		return VDE_STATUS_TIMEOUT;
+	} else if(vde_status & (0x1<<17)) {
+		return VDE_STATUS_JPEG_SLICE_READY;
+	} else if(vde_status & (0x1<<16)) {
+		VDE_DBG("vde : vde status stream error, status: 0x%x\n", vde_status);
+		return VDE_STATUS_STREAM_ERROR;
+	} else if(vde_status & (0x1<<15)) {
+		VDE_DBG("vde : vde status aso detected, status: 0x%x\n", vde_status);
+		return VDE_STATUS_ASO_DETECTED;
+	} else if(vde_status & (0x1<<14)) {
+		VDE_DBG("vde : vde status stream empty, status: 0x%x\n", vde_status);
+		return VDE_STATUS_STREAM_EMPTY;
+	} else if(vde_status & (0x1<<13)) {
+		printk("vde : vde status Bus error, status: 0x%x\n", vde_status);
+		return VDE_STATUS_BUS_ERROR;
+	} else {        
+		printk("vde : vde status unknow error, status: 0x%x\n", vde_status);
+		return VDE_STATUS_UNKNOWN_ERROR;
+	}
+}
+
+typedef unsigned long VDE_FREQ_T;
+
+static int vde_set_corevdd(struct regulator *power, int voltage)
+{
+
+	if (!IS_ERR(power)) {
+    	if(regulator_set_voltage(power, voltage, INT_MAX)) {
+			printk("cannot set corevdd to %duV !\n", voltage);
+			return -EINVAL;
+		}
+	}
+	return 0;
+}
+
+static int vde_set_parent_pll(const char* parent_name)
+{
+    struct clk *pre_parent;
+    struct clk *cur_parent;
+    struct clk *vde_clk;
+    int ret;
+
+ #ifndef IC_TYPE_GL5203
+    cur_parent = clk_get_sys((const char *)parent_name, NULL);
+ #else
+ 	cur_parent = clk_get_sys(NULL,(const char *)parent_name);
+ #endif	
+	if (IS_ERR(cur_parent)) {
+        printk("vde : clk_get_sys(..) failed\n");
+        return -1;
+	}
+
+ #ifndef IC_TYPE_GL5203	
+	vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+#else
+	vde_clk = clk_get_sys(NULL,(const char *)CLK_NAME_VDE_CLK);
+ #endif	
+    if (IS_ERR(vde_clk)) {
+        printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+        return -1;
+    }
+	pre_parent = clk_get_parent(vde_clk); 
+	
+	// Compare two clk sources like this??
+	if(pre_parent == cur_parent) {
+	    return 0;
+	}
+
+	ret = clk_set_parent(vde_clk, cur_parent); 
+	if(ret != 0) {
+	    printk("vde : clk_set_parent failed(%d)\n", ret);
+	    //fixme : now what?
+	    return -1;
+	}
+    return 0;
+}
+
+VDE_FREQ_T vde_do_set_freq(VDE_FREQ_T new_rate)
+{
+	unsigned long rate;
+	struct clk *vde_clk;
+	int ret; 
+
+#ifdef IC_TYPE_GL5203
+	struct clk *pll_clk;
+	long targetFreq, freq;
+#endif
+
+ #ifndef IC_TYPE_GL5203  
+    vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+ #else
+ 	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+ #endif
+    if (IS_ERR(vde_clk)){
+        printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+        return 0;
+    }
+
+#ifndef IC_TYPE_GL5203
+	ret = clk_set_rate(vde_clk, new_rate*1000*1000);
+#else
+	targetFreq = new_rate*1000*1000;
+	if (new_rate == VDE_FREQ_MULTI) {
+		printk("vde : targetFreq: %lu\n", targetFreq/30);
+		VDE_DBG("CMU_DISPLAYPLL=%x,CMU_DEVPLL=%x, CMU_VDECLK=%x\n", act_readl(CMU_DISPLAYPLL), act_readl(CMU_DEVPLL),act_readl(CMU_VDECLK));
+		pll_clk = clk_get_sys(NULL, (const char *)CLK_NAME_DISPLAYPLL);
+		if (IS_ERR(pll_clk)){
+	        printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+	        return 0;
+	    }
+		clk_set_parent(vde_clk, pll_clk);
+		printk("vde : vde_do_set_freq: set parent pll OK!\n");
+	}
+	
+	freq = clk_round_rate(vde_clk, targetFreq);
+	rate = clk_get_rate(vde_clk);
+	if (rate == targetFreq) {
+   	 	printk("vde : vde_do_set_freq: cur vde freq: %lu = %lu(target), no changed!\n", rate/30/1000/1000, targetFreq/30/1000/1000);    
+		return (rate/(1000*1000));  
+	}
+	
+	if (freq < targetFreq) {
+		if (rate == freq) {
+			printk("vde : vde_do_set_freq: cur vde freq: %lu = %ld(round), no changed!\n", rate/30/1000/1000,  freq/30/1000/1000); 	 
+			return (rate/(1000*1000));	
+		}
+		ret = clk_set_rate(vde_clk, freq);
+	}else {
+		ret = clk_set_rate(vde_clk, targetFreq);
+	}
+	VDE_DBG("CMU_DISPLAYPLL=%x,CMU_DEVPLL=%x, CMU_VDECLK=%x\n", act_readl(CMU_DISPLAYPLL), act_readl(CMU_DEVPLL),act_readl(CMU_VDECLK));
+	clk_put(vde_clk);
+#endif
+	
+	if(ret != 0) {
+		printk("vde : clk_set_rate new_rate %dM,  failed! \n", (unsigned int)new_rate);
+		//fixme : do we need handle vdd/parent?? 
+		return 0;       
+	}
+	
+    rate = clk_get_rate(vde_clk);
+    return (rate/(1000*1000));    
+}
+
+#ifndef IC_TYPE_GL5203 
+extern int asoc_run_config(void);
+#endif
+
+static VDE_FREQ_T vde_setFreq(VDE_FREQ_T freq_MHz) 
+{   
+ 	unsigned long new_rate;
+	
+ 	new_rate = freq_MHz;  
+#ifndef IC_TYPE_GL5203 
+    if(asoc_run_config() == 1 && new_rate>300) 
+#else
+	if(0)  //5203 not used this branch
+#endif
+	{
+             
+        // care this : 7023:1, 7029:0
+        if(vde_set_corevdd(gVDE->power, VDD_1_2V) != 0) {
+            return 0;
+        }        
+        if(vde_set_parent_pll(CLK_NAME_DEVCLK) != 0) {
+            return 0;
+        }    	
+        new_rate = 444; // 7023 dev          
+        
+    }else if(new_rate>=600) { 
+        /* 5206
+				*D1  150M    dev_clk     4    1.05v VDD_core\B5\E7ѹ\D3\F2
+				*720P 240M   dev_clk     2.5  1.05v 
+				*1080P 300M  dev_clk     2    1.05v 
+				*multi 480M  DISPLAY_PLL 1    1.05v
+				*4k 600M     dev_clk 	 1    1.2v
+        */     
+    	   VDE_DBG("vde : vde_setFreq: new_rate(%ld), 1.2V and devPLL \n", new_rate/30);
+       if(vde_set_corevdd(gVDE->power,VDD_1_2V) != 0) {
+            return 0;
+        } 
+		if(vde_set_parent_pll(CLK_NAME_DEVCLK) != 0) {            
+				return 0;
+        }        	
+    }else if(new_rate>=480) { 
+    		VDE_DBG("vde : vde_setFreq: new_rate(%ld), 1.05V and DISPLAYPLL \n", new_rate/30);
+        if(vde_set_corevdd(gVDE->power,VDD_1_05V) != 0) {
+            return 0;
+        }        
+        if(vde_set_parent_pll(CLK_NAME_DISPLAYPLL) != 0) { 
+            return 0;
+        }    	
+    }else if(new_rate>=300){
+    		VDE_DBG("vde : vde_setFreq: new_rate(%ld), 1.05V and devPLL \n", new_rate/30);
+        if(vde_set_corevdd(gVDE->power,VDD_1_05V) != 0) {
+            return 0;
+        }       
+        if(vde_set_parent_pll(CLK_NAME_DEVCLK) != 0) {
+            return 0;
+        }  
+    }else{ 
+    		VDE_DBG("vde : vde_setFreq: new_rate(%ld), 1.05V and devPLL \n", new_rate/30);
+        if(vde_set_corevdd(gVDE->power,VDD_1_05V) != 0) {
+            return 0;
+        }
+        if(vde_set_parent_pll(CLK_NAME_DEVCLK) != 0) {
+            return 0;
+        }            	
+    }   
+    
+    return vde_do_set_freq(new_rate);   
+}
+
+#ifndef IC_TYPE_GL5203
+static VDE_FREQ_T vde_getFreq(void) 
+{
+    struct clk *vde_clk;
+    unsigned long rate;
+		
+#ifdef IC_TYPE_GL5203	   
+    vde_clk = clk_get_sys((const char *)CLK_NAME_VDE_CLK, NULL);
+#else
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK);
+#endif   
+
+    rate = clk_get_rate(vde_clk);
+    if (IS_ERR(vde_clk)){
+        printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+        return 0;
+    }
+		
+    rate = clk_get_rate(vde_clk);
+    VDE_DBG("vde : cur vde freq : %d MHz\n", (int)rate/(1000*1000));
+		
+    return (rate/(1000*1000));   
+}
+#endif
+
+static int vde_adjust_freq(void)
+{
+	int f, ret;
+	unsigned int v; 
+	unsigned int width;
+	unsigned int height;
+	unsigned int jpeg_mode;
+	char * mode[8] = {"H264", "MPEG4", "H263", "JPEG", "VC-1", "RV89", "MPEG12", "Other"};
+	VDE_DBG("vde : vde_adjust_freq()\n");
+	v = vde_read(gVDE,0x10);//VDE_REG_4 
+	width = ((v >> 23) & 0x1ff) << 4;
+	height = ((v >> 15) & 0xff) << 4;
+	jpeg_mode = (v >> 12) & 0x7;
+
+	if(jpeg_mode == 0x11) {
+		//jpeg_mode
+		f = VDE_FREQ_1080P;
+	}else {
+	    if( width > (1280+1280)) {
+	#ifdef VDE_PLL_ALWAYS_BELOW_360M              
+		f = VDE_FREQ_1080P; 
+	#else
+		f = VDE_FREQ_4Kx2K; 
+	#endif        
+	    }else if( width > 1280) {
+		f = VDE_FREQ_1080P;
+	    } else if( width > 720) {
+		f = VDE_FREQ_720P;
+	    } else {
+		f = VDE_FREQ_D1;
+	    }
+	}
+
+	if(vde_cur_slot_num > 1 || multi_instance_mode == 1) {    
+		VDE_DBG("vde : vde_adjust_freq: vde_cur_slot_num: %d multi_instance_mode: %d", vde_cur_slot_num, multi_instance_mode);
+	#ifdef VDE_PLL_ALWAYS_BELOW_360M
+		if(f < VDE_FREQ_1080P) {
+	    		f = VDE_FREQ_1080P;
+		}
+	#else
+		if(f < VDE_FREQ_4Kx2K) {
+	    		f = VDE_FREQ_4Kx2K;
+		} 
+	#endif        
+	}
+
+	if(autoFreq_enable==0) {
+		f = VDE_FREQ_DEFAULT;                
+	}
+
+	if(autoFreq_enable==2) {
+	#ifdef VDE_PLL_ALWAYS_BELOW_360M
+		f = VDE_FREQ_1080P;
+	#else
+		f = VDE_FREQ_4Kx2K;    
+	#endif
+	}
+
+	if(autoFreq_enable==3) {
+		f = VDE_FREQ_MULTI;                
+	}
+
+	if(autoFreq_enable==4) {
+		f = VDE_FREQ_EXTREME;                
+	}
+
+	if(vde_pre_freq != f){  
+		vde_cur_need_freq = (unsigned long)f * 1000000;
+
+		if(get_mode() == 0)
+		{
+
+		}
+		// set frequency    
+		ret = vde_setFreq(f);
+		if(ret != 0) {
+			vde_pre_freq = f; 
+			printk("vde : adjust: [w, h, f] = [%d, %d, %s], autoFreq = %d, mulIns = %d, freq.[need, real] = [%d, %d] \n", 
+				width, height, mode[jpeg_mode], autoFreq_enable, multi_instance_mode, ((int)(vde_cur_need_freq/1000000))/30, ret/30);
+		}else{
+			printk("vde : set %dM Failed,-- %d \n", f/30, VDE_FREQ_DEFAULT);
+			vde_setFreq(VDE_FREQ_DEFAULT);
+			vde_pre_freq = VDE_FREQ_DEFAULT;
+		}   
+	}
+
+	return 0;
+}
+
+static long vde_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{  
+	int left_time, id, s, slot_id, jpeg_on_going; 
+#ifdef IC_TYPE_GL5203
+	int tag = 0; // to save delay flag for muilti instance
+	int check_pll_times;
+	volatile int pll_in_change = owl_pll_in_change();
+	check_pll_times = 0;
+	while (pll_in_change){
+		if (check_pll_times > 10) {
+			printk("vde : warning, asoc pll in change, check_pll_times: %d(> 2)! \n", check_pll_times);
+			break;
+		}
+		msleep(1);
+		pll_in_change = owl_pll_in_change();
+		check_pll_times ++;
+	}
+#endif
+
+    switch (cmd)
+    {
+       case VDE_RUN:    
+	   //return 0; // cathy added, for test decoder if is normal
+		
+        if(arg!=0) {            
+            jpeg_on_going=0;
+            //----------------------------------------------
+            mutex_lock(&m_mutex);   
+						
+	#ifdef IC_TYPE_GL5203
+            if((vde_read(gVDE,0x4) & 0x4000) == 0x4000) {
+				printk("vde : last frame stream empty, will delay 5ms\n");
+			    tag = 1;
+            }
+	#endif
+	
+            left_time = wait_event_interruptible_timeout(waitqueue, vde_idle_flag == 1, \
+                                    msecs_to_jiffies(5*1000) + 1);
+            if (unlikely(left_time == 0))  {	
+	            printk("vde : VDE_RUN --- wait_event_interruptible_timeout TIMEOUT 5s\n");
+                vde_reset();
+	            mutex_unlock(&m_mutex);
+	            return VDE_STATUS_UNKNOWN_ERROR;
+	        }  
+	        
+            if(vde_last_status==-1) {
+                vde_reset();
+            }
+			
+            if(vde_occupied == 1) {
+                if(arg != slot[vde_slice_slot_id].clientRegPtr) 
+                {         
+					printk("vde : VDE_RUN --- UNKNOWN_ERROR \n");          
+                    mutex_unlock(&m_mutex);
+                    return VDE_STATUS_UNKNOWN_ERROR;
+                }else {
+                    jpeg_on_going = 1;
+                }
+            }
+            
+            if(jpeg_on_going) {
+               id = vde_slice_slot_id;
+            } else {            
+                id = slot_get();
+                if(id < 0) {
+                    mutex_unlock(&m_mutex);
+                    return VDE_STATUS_UNKNOWN_ERROR;
+                }  
+            }
+						
+            vde_cur_slot_id = id;       
+            slot[id].clientRegPtr = arg;
+            vde_drv_flushReg(id, (void __user *)arg);  
+            
+            vde_occupied = 1;
+            vde_idle_flag = 0;  
+            
+            mutex_lock(&m_freq_adjust_mutex);           
+            if(adjust_freq_flag == 1)                   
+            		vde_adjust_freq();                         
+            
+            // let us go
+            s = 0;
+            s |= 1;   
+            enable_vde_irq();
+
+	#ifdef IC_TYPE_GL5203
+            if(tag==1) {
+               usleep_range(5000, 5000);
+            }
+	#endif
+            
+            vde_write(gVDE,s,0x4); 
+	    mutex_unlock(&m_freq_adjust_mutex);            
+	#ifdef IC_TYPE_GL5203
+		    usleep_range(100, 100); // make sure write success
+	#endif
+					
+            mutex_unlock(&m_mutex);
+            return id;
+            
+        } else {
+           printk("vde : Fail to execute VDE RUN, maybe arg (0x%x) wrong\n", (unsigned int)arg);                     
+           return VDE_STATUS_UNKNOWN_ERROR;
+        }
+        
+        break;        
+        
+        case VDE_QUERY:  
+        {
+            slot_id = (int)arg;
+            VDE_DBG("vde : --- VDE_QUERY --- 0. query NO.%d slot\n", slot_id);
+            //return VDE_STATUS_GOTFRAME; //cathy added for test vde decoder  if is normal
+            if (vde_irq_registered) 
+            {
+                VDE_Status_t s;
+                mutex_lock(&m_mutex);
+    	        left_time = wait_for_completion_timeout(&(slot[slot_id].isr_complete), \
+    	                                                msecs_to_jiffies(5*1000) + 1);
+    	        
+    	        if (unlikely(left_time == 0))  {	            
+		    		printk("vde : VDE_QUERY: wait timeout, VDE_STATUS_DEAD ---> vde_reset(%d, %d)\n", slot_id, vde_cur_slot_id);
+    	            vde_reset();
+    	            
+    	            s = VDE_STATUS_DEAD;
+    	        } else {
+				/* normal case */	       
+				int rt;     
+				rt = copy_to_user((void __user *)slot[slot_id].clientRegPtr, &(slot[slot_id].user_data.regs[0]), sizeof(vde_user_data_t));    
+				if(rt != 0) {
+					printk("vde : VDE_QUERY: ---> Warning: copy_to_user failed, rt=%d\n",rt);
+				}
+				s = vde_query_status(slot[slot_id].vde_status);   
+    	        }
+    	         
+    	        //\CAͷ\C5slot;
+    	        if ((slot[vde_cur_slot_id].slice_mode == 0) ||  (s == VDE_STATUS_DEAD)){
+    	            slot_reset(slot_id);	        
+    	        }
+		   
+    	        mutex_unlock(&m_mutex);
+    	        return s;
+    	    } else {
+    	        
+    	        printk("vde : should not be here\n");
+    	        return -1;
+    	    }
+   
+            break;
+       }     
+       case VDE_DISABLE_CLK:
+            break;
+        case VDE_ENABLE_CLK:
+            break;
+        case VDE_SET_FREQ:  
+            break;
+        case VDE_GET_FREQ:
+            break;
+        case VDE_SET_MULTI:
+            mutex_lock(&m_mutex);
+            if(arg>1) {
+                multi_instance_mode = 1;
+            }else {
+                multi_instance_mode = 0;
+            }
+            mutex_unlock(&m_mutex);
+            break;
+        case VDE_DUMP:
+		  	printk("vde : vde VDE_DUMP..., but do nothing\n");
+            vde_drv_showReg(-1);
+            break;
+                        
+        default:
+            printk("vde : no such cmd 0x%x\n",cmd);
+            return -EIO;
+    }
+    
+	//vde_reset_in_playing();
+    return 0;
+    
+}
+
+static int vde_open(struct inode *inode, struct file *file)
+{
+    mutex_lock(&m_mutex);  
+		VDE_DBG("\nvde : vde_open: In, vde_open_count: %d\n", vde_open_count);
+		
+    vde_open_count++;
+    if (vde_open_count >1){
+        printk("vde drv already open\n");
+        mutex_unlock(&m_mutex);
+        return 0;
+    }
+    vde_set_voltage_limit=0;
+
+    if(ic_type == IC_TYPE_GL5206){
+		share_mem_reg_enable();
+	}
+    vde_clk_enable();
+    disable_vde_irq();   
+#ifdef IC_TYPE_GL5203
+    enable_irq(gVDE->irq);
+#endif
+
+    vde_idle_flag = 1;
+
+	VDE_DBG("vde : vde_open: Out\n");
+    mutex_unlock(&m_mutex);
+    return 0;
+}
+
+static void vde_clear_parent_pll(void)
+{
+    VDE_DBG("vde : vde release now, set to default parent pll\n");
+
+#ifndef IC_TYPE_GL5203
+    if(vde_set_voltage_limit != 0){
+   	 	if(vdd_voltage_limit_control(CLR_VDD_LIMIT, vde_set_voltage_limit) != 0) {
+   	 	   printk("vde : ERROR: %d clear voltage limit failed \n",__LINE__);
+   	 	   return;    	  
+	    	}
+	    	vde_set_voltage_limit=0;
+    }
+#endif   
+}
+
+static int vde_release(struct inode *inode, struct file *file)
+{
+    int i;
+    mutex_lock(&m_mutex);
+	
+		VDE_DBG("vde : vde_release: In, vde_open_count: %d\n", vde_open_count); 
+    vde_open_count--;
+
+    if (vde_open_count > 0) {
+        printk("vde : vde_release: count:%d pid(%d)\n", vde_open_count, task_tgid_vnr(current));       
+        vde_waitForIdle();
+        
+        goto VDE_REL;
+    } else if (vde_open_count < 0) {
+        printk("vde : vde_release: module is closed before opened\n");
+        vde_open_count = 0;        
+    }
+
+#ifdef IC_TYPE_GL5203
+	if (vde_open_count == 0){
+		VDE_DBG("vde : vde_release: disable vde irq \n");       
+		disable_vde_irq();
+		VDE_DBG("vde : vde_release: disable IRQ_VDE\n"); 
+		disable_irq(gVDE->irq);	
+		VDE_DBG("vde : vde_release: disable vde irq ok!\n"); 
+ 		if(ic_type == IC_TYPE_GL5206){
+ 			int regulator_return = 0;
+			if (IS_ERR(gVDE->power))
+				printk("can not get corevdd regulator,may be this board not need, or lost in dts!\n");
+			else{
+		    	if(regulator_set_voltage(gVDE->power, VDD_1_0V, INT_MAX)) {
+					printk("cannot set corevdd to 1000000uV !\n");
+					return -EINVAL;
+				}
+				regulator_return=regulator_enable(gVDE->power);
+			}
+			share_mem_reg_disable();
+		}
+  }
+#endif
+    vde_clear_parent_pll();            
+    vde_clk_disable();
+    vde_pre_freq = 0;
+
+VDE_REL:    
+	for(i=0;i<MAX_INSTANCE_NUM;i++) {
+        if(slot[i].pid == task_tgid_vnr(current)){
+            printk("vde : vde slot is leak by pid(%d), reset it\n", task_tgid_vnr(current));           
+            if(slot[i].slice_mode == 1 && vde_occupied == 1)
+                vde_occupied = 0;
+           slot_reset(i);            
+        }
+    }
+	VDE_DBG("vde : vde_release: Out. vde_cur_slot_num: %d vde_open_count: %d\n", vde_cur_slot_num, vde_open_count); 
+	mutex_unlock(&m_mutex);
+    return 0;
+}
+
+
+static int vde_is_enable_before_suspend = 0;
+
+static int vde_suspend (struct platform_device * dev, pm_message_t state)
+{    
+	printk("vde : vde_suspend: In , vde_clk_isEnable=%d, RST0=0x%x\n", vde_clk_isEnable, readl_relaxed(VDE_CMU_DEVRST0));		    
+    if(vde_clk_isEnable != 0) {
+       mutex_lock(&m_mutex);
+       vde_waitForIdle(); 
+       disable_vde_irq();
+	   vde_clear_parent_pll();  
+       vde_clk_disable();
+       vde_is_enable_before_suspend = 1;       
+       
+       mutex_unlock(&m_mutex);
+    }
+	
+#ifdef IC_TYPE_GL5203
+    disable_irq(gVDE->irq);	
+#endif
+
+    vde_pre_freq = 0;
+    printk("vde : vde_suspend: Out\n");	
+    return 0;
+}
+
+static int vde_resume (struct platform_device * dev)
+{
+	printk(KERN_DEBUG"vde : vde_resume: In, vde_is_enable_before_suspend=%d, RST0=0x%x\n", \
+            vde_is_enable_before_suspend, readl_relaxed(VDE_CMU_DEVRST0));
+    if(vde_is_enable_before_suspend == 1){
+		if(ic_type == IC_TYPE_GL5206){
+			share_mem_reg_enable();
+		}
+        vde_clk_enable();
+        vde_is_enable_before_suspend = 0;
+    }else {
+    }
+
+#ifdef IC_TYPE_GL5203
+    enable_irq(gVDE->irq);	
+#endif
+    printk(KERN_DEBUG"vde : vde_resume: Out\n");
+    return 0;
+}
+
+#ifdef IC_TYPE_GL5203
+static struct notifier_block nb;
+#endif
+
+#ifdef ENABLE_COOLING    
+#include <linux/cpu_cooling.h>
+static bool is_cooling = 0;
+static int thermal_notifier(struct notifier_block *nb,
+								unsigned long event, void *data)
+{
+	printk("vde thermal_notifier event:%ld \n", event);
+	if(event == CPUFREQ_COOLING_START)
+	{	
+		int ret = 0;
+		if(is_cooling == 0)
+		{
+			mutex_lock(&m_freq_adjust_mutex); 
+			vde_waitForIdle();	
+			adjust_freq_flag = 0;	
+			printk("vde  CPUFREQ_COOLING_START,event:%ld,\n", event);		
+			if(vde_set_parent_pll(CLK_NAME_DEVCLK) != 0) {
+				 printk("set parent pll fail\n");
+    		 mutex_unlock(&m_freq_adjust_mutex);
+			     return 0;
+			}
+	    
+			ret = vde_do_set_freq(VDE_FREQ_DEFAULT);
+			
+			
+		    if(vde_set_corevdd(gVDE->power,VDD_1_05V) != 0) {
+				 printk("set vdd VDD_1_05V fail\n");
+    		 mutex_unlock(&m_freq_adjust_mutex);
+			     return 0;
+			}
+    		 mutex_unlock(&m_freq_adjust_mutex);
+			is_cooling = 1;
+		}
+		printk("-- CPUFREQ_COOLING_START --freq : %d",ret/30);
+      
+	}
+	
+	if(event == CPUFREQ_COOLING_STOP)
+	{
+		printk("vde  CPUFREQ_COOLING_STOP event:%ld\n", event);
+		if(is_cooling == 1){
+		mutex_lock(&m_freq_adjust_mutex); 
+			is_cooling = 0;
+			adjust_freq_flag = 1;
+		mutex_unlock(&m_freq_adjust_mutex); 
+		}
+	}
+	return 0;
+}
+static struct notifier_block thermal_notifier_block = {
+	.notifier_call = thermal_notifier,
+};
+
+#endif
+static int  vde_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *id;
+	struct asoc_vde_dev *vde;
+	struct resource		*iores;
+ 	int ret;
+#ifdef IC_TYPE_GL5203
+ 	struct clk *pll;
+	struct clk *vde_clk; 
+	unsigned long freq;
+#endif
+
+    dev_info(&pdev->dev, "Probe vde device\n");
+    
+	id = of_match_device(gl520x_vde_of_match, &pdev->dev);
+	if(id != NULL){
+		struct ic_info * info = (struct ic_info *)id->data;	
+		if(info != NULL){
+			ic_type = info->ic_type;
+			printk("info ic_type 0x%x \n",ic_type);
+		}else{
+			printk("info is null\n");
+		}
+	}
+	
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	//printk("platform_get_resource =%x\n",iores);
+	if (!iores)
+		return -EINVAL;
+
+	vde = devm_kzalloc(&pdev->dev, sizeof(*vde), GFP_KERNEL);
+	VDE_DBG("vde =%p\n",(void*)vde);
+	if (!vde)
+		return -ENOMEM;
+    
+	vde->base = devm_ioremap_resource(&pdev->dev, iores);
+	VDE_DBG("vde->base =%p\n",vde->base);
+	if (IS_ERR(vde->base))
+		return PTR_ERR(vde->base);
+
+	vde->irq = platform_get_irq(pdev, 0);
+	printk("vde->irq =%x\n",vde->irq);
+	if (vde->irq < 0)
+		return vde->irq;
+
+	ret = devm_request_irq(&pdev->dev, vde->irq, (void *)vde_ISR, 0, "vde_isr", 0);
+	if (ret) {
+		printk("vde_drv : register vde irq failed!\n");
+		return ret;
+	} else {
+		vde_irq_registered = 1;   
+	}
+	#ifdef IC_TYPE_GL5203
+	disable_irq(vde->irq);	
+	#endif
+
+#ifdef IC_TYPE_GL5203
+	vde_cur_need_freq = (unsigned long)VDE_FREQ_DEFAULT * 1000000;
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK); 
+	if (IS_ERR(vde_clk)){
+		printk("VDE DRV : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return 0; 		 
+	} 
+
+	nb.notifier_call = vde_clk_notify;
+	clk_notifier_register(vde_clk, &nb);
+#ifdef ENABLE_COOLING     
+	cputherm_register_notifier(&thermal_notifier_block,CPUFREQ_COOLING_START);
+#endif
+
+	ret = owl_pllsub_set_putaway(CLOCK__VDE_CLK, CLOCK__DEV_CLK);	
+	if(ret == -1) {
+		printk("vde_init: 2. owl_pllsub_set_putaway failed(%d)\n", ret);
+	}
+
+	pll = clk_get(NULL, (const char *)CLK_NAME_DEVPLL);
+	clk_set_parent(vde_clk, pll);
+	
+	freq = clk_round_rate(vde_clk, vde_cur_need_freq);
+	vde_cur_need_freq = freq;
+
+	clk_set_rate(vde_clk, freq);
+#endif
+
+	if(ic_type == IC_TYPE_GL5206){
+		int regulator_return = 0;
+		vde->power = devm_regulator_get(&pdev->dev,"corevdd");
+		if (IS_ERR(vde->power))
+			printk("can not get corevdd regulator,may be this board not need, or lost in dts!\n");
+		else {
+	    		if(regulator_set_voltage(vde->power, VDD_1_0V, INT_MAX)) {
+				printk("cannot set corevdd to 1000000uV !\n");
+				return -EINVAL;
+			}
+			regulator_return=regulator_enable(vde->power);
+		}
+	}
+	mutex_init(&m_mutex);
+	mutex_init(&m_freq_adjust_mutex);	
+	vde_cur_slot_num = 0;
+	vde_clk_isEnable = 0;
+    
+	dev_info(&pdev->dev, "resource: iomem: %pR mapping to %p, irq %d\n",
+		iores, vde->base, vde->irq);
+    
+  	//ioremap sps and cmu
+	sps_base = (unsigned int)ioremap_nocache(0xb01b0100, 0x10);
+	cmu_base = (unsigned int)ioremap_nocache(0xb0160000, 0x400);
+	Share_Mem_REG = ioremap_nocache(0xb0240004,0x10);
+	VDE_SPS_PG_CTL = (void __iomem *)sps_base;
+	VDE_CMU_COREPLL = (void __iomem *)cmu_base;
+	VDE_CMU_VDE_CLK = (void __iomem *)(cmu_base + 0x40);
+	VDE_CMU_DEVRST0 = (void __iomem *)(cmu_base + 0xa8);
+	VDE_CMU_DEVCLKEN0 = (void __iomem *)(cmu_base + 0xa0);
+
+	printk("sps base = 0x%x\n", (unsigned int)sps_base);
+	printk("cmu base = 0x%x\n", (unsigned int)cmu_base);
+	printk("SPS_PG_CTL = 0x%x\n", (unsigned int)VDE_SPS_PG_CTL);
+	printk("Share_Mem_REG = 0x%x\n", (unsigned int)Share_Mem_REG);	
+	printk("CMU_COREPLL = 0x%x\n", (unsigned int)VDE_CMU_COREPLL);
+	printk("CMU_VDE_CLK = 0x%x\n", (unsigned int)VDE_CMU_VDE_CLK);
+	printk("CMU_DEVRST0 = 0x%x\n", (unsigned int)VDE_CMU_DEVRST0);
+	printk("CMU_DEVCLKEN0 = 0x%x\n", (unsigned int)VDE_CMU_DEVCLKEN0);
+	
+	gVDE = vde;
+	
+	return 0;
+}
+
+static int vde_remove(struct platform_device *pdev)
+{
+#ifdef IC_TYPE_GL5203
+	struct clk *vde_clk;	 
+
+	vde_clk = clk_get_sys(NULL, (const char *)CLK_NAME_VDE_CLK); 
+	if (IS_ERR(vde_clk)) {
+		printk("vde : clk_get_sys(CLK_NAME_VDE_CLK, NULL) failed\n");
+		return -1; 		 
+	} 
+	clk_notifier_unregister(vde_clk, &nb);
+#endif
+
+	if(sps_base != 0){iounmap((void *)sps_base);sps_base = 0;}
+	if(cmu_base != 0){iounmap((void *)cmu_base);cmu_base = 0;};
+	if(Share_Mem_REG != 0){iounmap((void *)Share_Mem_REG);Share_Mem_REG = 0;}
+
+	return 0;
+}
+
+
+static const struct file_operations vde_fops = 
+{
+    .owner = THIS_MODULE,
+    .unlocked_ioctl = vde_ioctl,
+    .open = vde_open,
+    .release = vde_release,
+};
+
+#ifndef CONFIG_OF
+static void vde_platform_device_release(struct device * dev)
+{
+    return;
+}
+
+static struct resource asoc_vde_resource[] = {
+	[0] = {
+		.start = VDE_REGISTER_BASE,
+		.end   = VDE_REGISTER_BASE + (90*4),
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = OWL_IRQ_VDE,
+		.end   = OWL_IRQ_VDE,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device vde_platform_device = {
+	.name   = DEVDRV_NAME_VDE,
+	.id = -1,
+	.dev = {
+		.release = vde_platform_device_release,
+	}, 
+	.resource = asoc_vde_resource,
+    .num_resources = ARRAY_SIZE(asoc_vde_resource),	
+};
+#endif
+
+static struct platform_driver vde_platform_driver = {
+    .driver = {
+        .name = DEVDRV_NAME_VDE,
+        .owner = THIS_MODULE,
+        .of_match_table = gl520x_vde_of_match,
+    },
+    .probe = vde_probe,
+    .remove = vde_remove,
+    .suspend = vde_suspend,
+    .resume = vde_resume,
+};
+
+
+static struct miscdevice vde_miscdevice = {
+     .minor = MISC_DYNAMIC_MINOR,
+     .name = DEVDRV_NAME_VDE,
+      .fops = &vde_fops,
+};
+
+#ifdef VDE_DRV_USE_SYSFS
+
+// ----------------------------------- use sysfs ---------------------
+#define MAX_MESSAGE_LEN	256
+#ifdef IC_TYPE_GL5203
+static int vde_clk_isEnableControl = 0;
+#endif
+
+static void message_help(void) 
+{
+#ifdef IC_TYPE_GL5203
+	printk("  3 : show help info \n");
+	printk("  2 : show vde reg info \n");	
+	printk("  1 : enable debug info\n");
+	printk("  0 : disable debug info\n");
+#else
+    printk("  0 : show help info \n");		    
+    printk("  1 : enable debug info\n");
+    printk("  2 : disable debug info\n");
+    printk("  3 : enable auto freq adjust\n");
+    printk("  4 : disable auto freq adjust, always Freq %d\n", VDE_FREQ_DEFAULT);
+    printk("  5 : disable auto freq adjust, always Freq %d\n", VDE_FREQ_4Kx2K);
+    printk("  6 : disable auto freq adjust, always Freq %d\n", VDE_FREQ_MULTI);
+    printk("  7 : disable auto freq adjust, always Freq %d, for test only\n", VDE_FREQ_EXTREME);
+    printk("  8 : many debug info\n");
+    printk("  9 : show current vde reg \n");
+#endif
+}
+
+static ssize_t message_show(struct device *dev, struct device_attribute *attr, char *buf) {
+#ifdef IC_TYPE_GL5203
+	int len = 0;
+	len = sprintf(buf,"%d\n", vde_clk_isEnable);
+	return len;
+#else	 
+    char *t = "OVER.";    
+    strlcpy(buf, t, 6);  
+    printk("  enable debug info      = %s\n", (debug_enable==1)?"true":"false");    
+    printk("  enable autofreq adjust = %s\n", (autoFreq_enable==1)?"true":"false");    
+   
+    printk("\n");
+    printk("  ECHO CMD:\n");
+    message_help();
+    return 6;
+ #endif   
+}
+
+static ssize_t message_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) {
+#ifdef IC_TYPE_GL5203
+	int n = simple_strtol(buf, NULL, 10);  
+	printk("message_store: n: 0x%x count: 0x%x\n", n, count);
+
+	switch(n) { // level -> n
+		case 0:
+			if(vde_clk_isEnable != 0) {
+				mutex_lock(&m_mutex);
+				printk("will disable\n");	
+				vde_waitForIdle(); 
+				disable_vde_irq();
+				vde_clear_parent_pll();  
+				vde_clk_disable();
+				vde_clk_isEnableControl = 1;
+				mutex_unlock(&m_mutex);
+			}else {
+				printk("has disable\n");
+			}
+			break;
+		case 1:
+			if(vde_clk_isEnableControl == 1){
+				printk("will enable\n");	
+ 		        vde_clk_enable();
+ 		        vde_clk_isEnableControl = 0;
+ 		    }else {
+ 		    	printk("need not enable\n");	
+ 		    }
+			break;
+		case 2:
+			vde_dump();
+			vde_dump_pre(vde_cur_slot_num);
+			break;
+		case 3:
+			message_help();
+			break;
+		default:
+			vde_dump();
+			vde_dump_ddr(n);
+			break;
+	}
+#else
+	int level = *buf - 48;
+	if ((level < 0) || (level > 9))
+	{
+		printk("input (%d)error! \n", level);
+		return -EBADRQC;
+	}
+	
+	switch (level)
+	{
+	    default:
+	    case 0:
+		    message_help();		    
+		    break;
+		case 1:
+			debug_enable = 1;
+			printk("now debug print is open\n");
+			break;
+		case 2:
+			debug_enable = 0;
+			printk("now debug print is close\n");
+			break;
+		case 3:
+			autoFreq_enable = 1;
+			printk("now autoFreq is open\n");
+			break;
+		case 4:
+			autoFreq_enable = 0;
+			printk("now autoFreq is close\n");
+			break;
+		case 5:
+			autoFreq_enable = 2;
+			printk("now autoFreq is close, always %dM\n", VDE_FREQ_4Kx2K/30);
+			break;
+		case 6:
+			autoFreq_enable = 3;
+			printk("now autoFreq is close, always %dM\n", VDE_FREQ_MULTI/30);
+			break;
+        case 7:
+			autoFreq_enable = 4;
+			printk("now autoFreq is close, always %dM\n", VDE_FREQ_EXTREME/30);
+			break;
+		case 8:
+			debug_enable = 2;
+			printk("now backdoor print is open\n");
+			break;
+		case 9:
+		    if(vde_clk_isEnable != 0) {
+			    vde_drv_showReg(-1);			
+			} else {
+			    printk("vde_clk_isEnable = 0\n");    
+			}
+			break;
+	}
+#endif
+	return count;
+}
+
+#ifdef IC_TYPE_GL5203
+DEVICE_ATTR(enable, S_IRUGO | S_IWUSR, message_show, message_store); //0660
+#else
+DEVICE_ATTR(message, S_IRUGO | S_IWUSR, message_show, message_store); //0660
+#endif
+#endif
+
+// ----------------------------------- use sysfs ---------------------
+static int vde_init(void)
+{
+	int ret;
+     
+	printk("#### insmod vde driver!\n");  
+	 
+	ret = misc_register(&vde_miscdevice);
+	if (ret) {
+		printk("register vde misc device failed!\n");
+		goto err0;
+	}
+
+	#ifndef CONFIG_OF
+	ret = platform_device_register(&vde_platform_device);
+	if (ret){
+		printk("register vde_platform_device error!\n");
+		goto err1;
+	}
+	#endif
+
+	ret = platform_driver_register(&vde_platform_driver);
+	if (ret) {
+		printk("register gpu platform driver4pm error!\n");
+		goto err2;
+	} 
+
+	#ifdef VDE_DRV_USE_SYSFS    
+	/* create sysfs */
+	printk("device_create_file !\n");
+	ret = device_create_file(vde_miscdevice.this_device, &dev_attr_enable); //dev_attr_message
+	if (ret) {
+		pr_err("hello: failed to create sysfs file, ret = %d\n", ret);
+		goto err2;
+	}
+	#endif
+
+	return 0;
+
+err2:
+
+	#ifndef CONFIG_OF
+	platform_device_unregister(&vde_platform_device);
+err1:
+	#endif
+
+	misc_deregister(&vde_miscdevice);
+err0:
+	return ret;
+}
+
+static void vde_exit(void)
+{
+#ifdef VDE_DRV_USE_SYSFS
+    printk("device_remove_file!\n");
+    device_remove_file(vde_miscdevice.this_device, &dev_attr_enable);	 //dev_attr_message
+#endif
+
+	misc_deregister(&vde_miscdevice);
+#ifndef CONFIG_OF
+	platform_device_unregister(&vde_platform_device);
+#endif
+	platform_driver_unregister(&vde_platform_driver);
+
+	printk("vde module unloaded\n");
+}
+
+
+
+
+
+late_initcall(vde_init);
+module_exit(vde_exit);
+
+MODULE_AUTHOR("Actions Semi Inc");
+MODULE_DESCRIPTION("VDE kernel module");
+MODULE_LICENSE("GPL");
diff --git a/drivers/video/fbdev/owl/vde/vde_drv.h b/drivers/video/fbdev/owl/vde/vde_drv.h
new file mode 100755
index 0000000..103a633
--- /dev/null
+++ b/drivers/video/fbdev/owl/vde/vde_drv.h
@@ -0,0 +1,20 @@
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define VDE_MAGIC_NUMBER                'v'
+/******************************************************************************/
+
+#define VDE_QUERY                        _IOWR(VDE_MAGIC_NUMBER, 0xf0, unsigned int)
+#define VDE_ENABLE_CLK                   _IOWR(VDE_MAGIC_NUMBER, 0xf1, unsigned int)
+#define VDE_DISABLE_CLK                  _IOWR(VDE_MAGIC_NUMBER, 0xf2, unsigned int)
+#define VDE_RUN                     		_IOWR(VDE_MAGIC_NUMBER, 0xf3, unsigned int)
+#define VDE_DUMP                    		_IOWR(VDE_MAGIC_NUMBER, 0xf4, unsigned int)
+#define VDE_SET_FREQ                     _IOWR(VDE_MAGIC_NUMBER, 0xf5, unsigned int)
+#define VDE_GET_FREQ                    _IOWR(VDE_MAGIC_NUMBER, 0xf6, unsigned int)
+#define VDE_SET_MULTI                   _IOWR(VDE_MAGIC_NUMBER, 0xf7, unsigned int)
+
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig
old mode 100644
new mode 100755
index 0037104..0695a9b
--- a/drivers/video/logo/Kconfig
+++ b/drivers/video/logo/Kconfig
@@ -82,4 +82,14 @@ config LOGO_M32R_CLUT224
 	depends on M32R
 	default y
 
+config LOGO_ACTIONS_CLUT224
+  bool "224-color Action Linux logo"
+#	depends on 
+	default y
+
+config EXTRA_LOGO_ACTIONS_CLUT224
+  bool "EXTRA 224-color Action Linux logo"
+	depends on FB_LOGO_EXTRA
+	default y
+	
 endif # LOGO
diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile
old mode 100644
new mode 100755
index 3b43781..e525616
--- a/drivers/video/logo/Makefile
+++ b/drivers/video/logo/Makefile
@@ -15,6 +15,7 @@ obj-$(CONFIG_LOGO_SUPERH_MONO)		+= logo_superh_mono.o
 obj-$(CONFIG_LOGO_SUPERH_VGA16)		+= logo_superh_vga16.o
 obj-$(CONFIG_LOGO_SUPERH_CLUT224)	+= logo_superh_clut224.o
 obj-$(CONFIG_LOGO_M32R_CLUT224)		+= logo_m32r_clut224.o
+obj-$(CONFIG_LOGO_ACTIONS_CLUT224)		+= logo_actions_clut224.o
 
 obj-$(CONFIG_SPU_BASE)			+= logo_spe_clut224.o
 
diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c
old mode 100644
new mode 100755
index 10fbfd8..fce7cb7
--- a/drivers/video/logo/logo.c
+++ b/drivers/video/logo/logo.c
@@ -111,6 +111,9 @@ const struct linux_logo * __init_refok fb_find_logo(int depth)
 		/* M32R Linux logo */
 		logo = &logo_m32r_clut224;
 #endif
+#ifdef CONFIG_LOGO_ACTIONS_CLUT224
+		logo = &logo_actions_clut224;
+#endif
 	}
 	return logo;
 }
diff --git a/drivers/video/logo/logo_actions_clut224.ppm b/drivers/video/logo/logo_actions_clut224.ppm
new file mode 100755
index 0000000..3b2eee6
--- /dev/null
+++ b/drivers/video/logo/logo_actions_clut224.ppm
@@ -0,0 +1,123 @@
+P3
+120 120
+255
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 8 16 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 24 0 0 16 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 16 0 8 16 8 8 16 8 8 16 0 8 16 0 8 16 0 8 16 8 8 24 8 8 24 8 8 24 8 8 33 8 8 33 8 8 33 0 8 28 0 8 28 0 8 28 0 8 28 8 8 33 0 8 28 0 8 28 0 8 28 0 8 28 0 8 28 0 0 24 0 0 16 0 0 16 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 0 8 16 0 8 16 8 8 16 8 8 16 0 8 16 8 8 16 8 8 16 8 8 24 8 8 24 8 8 24 8 8 24 8 16 33 8 16 33 8 16 33 8 16 41 8 16 41 8 16 41 8 16 41 8 16 41 8 16 41 8 16 41 8 16 41 8 8 41 8 8 41 8 8 41 8 8 33 8 8 33 8 8 33 0 8 28 0 8 28 0 8 28 0 0 24 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 24 8 8 24 8 8 24 8 16 33 16 16 33 8 16 33 16 16 41 16 16 41 16 16 41 16 24 49 16 24 49 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 24 57 16 16 49 16 16 49 8 16 49 8 16 41 8 16 41 8 16 41 8 16 33 8 8 33 0 8 28 0 8 28 0 0 24 0 0 24 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 8 8 8 8 8 16 8 8 8 8 8 16 8 8 24 8 8 24 8 8 24 16 16 33 8 16 33 16 16 41 16 16 41 16 24 41 16 24 49 24 24 57 24 33 57 24 33 66 24 33 66 24 33 74 24 33 74 28 45 82 24 41 82 33 33 78 24 33 74 24 33 74 24 41 82 24 33 82 24 33 82 24 33 82 24 33 82 24 33 74 24 33 74 24 33 66 16 24 66 16 24 57 16 24 49 16 16 49 8 16 41 8 16 41 8 8 33 8 8 33 0 8 28 0 8 28 8 8 24 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 16 24 8 16 24 16 16 33 16 16 41 16 24 41 16 24 49 24 33 57 24 33 66 24 33 66 33 41 74 41 45 87 36 52 95 36 52 95 36 52 95 40 57 107 40 57 107 41 70 115 40 57 107 40 57 107 40 57 107 40 57 107 38 51 120 40 57 107 40 57 107 40 57 107 40 57 107 40 57 107 36 52 95 36 52 95 33 38 93 28 45 82 24 41 82 24 33 66 16 24 57 16 24 49 16 16 41 8 16 41 8 16 41 8 8 33 0 8 28 0 8 28 0 8 28 0 0 16 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 8 16 8 8 16 8 8 16 8 8 16 8 8 24 8 16 24 16 16 33 16 24 41 24 24 49 24 33 57 24 33 66 33 41 74 41 45 87 36 52 95 40 57 107 40 57 107 52 69 123 52 77 133 59 71 145 59 71 145 55 84 152 66 90 148 66 94 162 66 90 148 66 90 148 55 84 152 55 84 152 59 78 164 59 78 164 55 84 152 55 84 152 55 84 152 55 84 152 52 77 133 52 77 133 52 69 123 41 70 115 40 57 107 36 52 95 28 45 82 24 33 74 16 24 66 16 24 57 16 16 49 8 16 49 8 16 41 8 16 33 8 8 33 8 8 24 0 0 24 0 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 0 0 8 0 8 8 0 8 16 0 8 16 8 8 16 8 8 16 8 8 24 8 16 24 16 16 33 16 16 41 16 24 49 24 33 57 33 41 74 41 45 87 36 52 95 55 70 111 52 77 133 59 85 139 66 90 148 66 94 162 75 105 163 77 112 168 78 115 181 78 115 181 79 113 191 79 113 191 84 125 202 79 113 191 83 113 204 79 113 191 79 113 191 83 113 204 79 113 191 79 113 191 79 113 191 79 113 191 79 113 191 78 115 181 75 105 163 75 105 163 66 94 162 66 90 148 52 77 133 41 70 115 40 57 107 33 38 93 24 41 82 24 33 74 24 33 66 16 24 57 16 16 49 8 16 41 8 8 33 0 8 28 0 8 28 0 0 24 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 0 8 8 0 8 8 0 8 16 8 8 16 8 8 16 8 8 16 8 16 24 16 16 33 16 16 33 24 24 41 24 33 57 33 41 74 41 45 87 40 57 107 52 69 123 59 85 139 66 90 148 75 105 163 90 117 178 90 117 178 98 133 197 115 150 210 127 169 215 127 169 215 124 179 225 136 176 233 136 176 233 163 210 237 179 233 249 179 233 249 163 210 237 152 198 235 152 198 235 163 210 237 152 198 235 136 176 233 117 169 217 107 160 220 100 145 211 93 141 201 93 141 201 95 132 180 78 115 181 77 112 168 66 94 162 52 77 133 52 69 123 41 70 115 40 57 107 36 52 95 24 33 74 16 33 61 16 24 57 16 16 49 8 16 41 8 8 33 0 8 28 0 0 24 0 0 24 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 0 0 8 0 8 16 8 8 16 8 8 16 8 8 16 8 8 24 8 16 24 16 16 33 16 24 41 24 24 49 24 33 57 33 41 74 36 52 95 52 69 123 59 85 139 75 93 163 90 117 178 98 133 197 127 169 215 127 169 215 136 176 233 136 193 231 152 198 235 152 198 235 137 196 219 137 196 219 124 179 225 152 198 235 152 198 235 136 176 233 152 198 235 163 210 237 179 233 249 163 210 237 117 169 217 117 169 217 136 176 233 179 233 249 179 233 249 161 223 239 148 210 233 136 193 231 124 179 225 107 160 220 93 141 201 98 133 197 78 115 181 75 105 163 66 94 162 59 85 139 52 77 133 40 57 107 36 52 95 24 33 74 16 24 66 16 16 49 8 16 41 8 8 33 8 8 33 0 8 28 0 0 24 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 0 8 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 16 24 16 16 24 16 16 33 16 24 41 24 33 57 33 41 74 41 45 87 40 57 107 53 66 136 75 93 163 116 155 198 127 169 215 136 193 231 143 181 209 127 169 215 116 155 198 116 155 198 137 196 219 137 196 219 137 196 219 143 181 209 163 210 237 152 198 235 163 210 237 152 198 235 152 198 235 143 181 209 127 169 215 136 176 233 136 176 233 152 198 235 163 210 237 152 198 235 161 223 239 199 239 250 199 239 250 223 250 248 214 242 247 199 239 250 179 233 249 149 212 243 136 193 231 115 150 210 93 141 201 95 132 180 95 132 180 75 105 163 66 90 148 52 77 133 40 57 107 33 38 93 24 33 74 16 24 57 16 16 49 8 16 41 8 8 33 8 8 33 0 8 28 0 0 24 0 0 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 0 8 0 8 8 0 0 8 8 0 16 8 8 16 8 8 16 8 8 16 8 16 24 16 16 33 16 16 33 24 24 41 24 33 57 33 41 74 36 52 95 52 69 123 75 93 163 116 155 198 143 181 209 143 181 209 143 181 209 116 155 198 127 169 215 116 155 198 143 181 209 127 169 215 116 155 198 116 155 198 90 121 161 90 121 161 76 100 142 74 90 135 74 90 135 74 90 135 75 105 163 95 132 180 90 117 178 98 133 197 127 169 215 127 169 215 124 179 225 136 176 233 136 176 233 163 210 237 199 239 250 223 250 248 223 250 248 223 250 248 235 251 249 235 251 249 235 251 249 223 250 248 191 233 234 137 196 219 117 169 217 116 155 198 95 132 180 77 112 168 55 84 152 52 69 123 36 52 95 24 41 82 24 33 66 16 24 57 16 16 49 8 16 41 8 8 33 0 8 28 0 0 24 0 0 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 0 8 8 8 0 8 8 0 8 8 8 16 8 8 16 8 8 16 8 16 24 16 16 24 16 16 33 24 24 49 24 33 57 33 41 74 40 57 107 66 90 148 95 132 180 116 155 198 127 169 215 116 155 198 98 133 197 95 132 180 95 132 180 90 121 161 90 121 161 90 121 161 76 100 142 76 100 142 74 90 135 76 100 142 90 121 161 76 100 142 74 90 135 53 68 103 55 70 111 63 84 121 59 85 139 76 100 142 77 112 168 77 112 168 95 132 180 127 169 215 116 155 198 127 169 215 152 198 235 124 179 225 124 179 225 136 193 231 149 212 243 149 212 243 148 210 233 199 239 250 223 250 248 235 251 249 235 251 249 214 242 247 137 196 219 117 169 217 116 155 198 90 117 178 66 94 162 52 77 133 41 70 115 36 52 95 24 33 82 16 24 66 16 24 57 8 16 49 8 16 41 8 8 33 0 8 28 0 0 24 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 0 8 0 0 8 0 0 8 8 0 8 8 8 16 8 8 16 8 16 24 16 16 24 16 16 33 16 16 41 24 24 49 24 33 66 28 45 82 52 69 123 76 100 142 76 100 142 76 100 142 76 100 142 90 121 161 76 100 142 74 90 135 74 90 135 63 84 121 63 84 121 63 84 121 63 84 121 63 84 121 60 78 115 74 90 135 63 84 121 60 78 115 53 68 103 43 59 92 53 68 103 53 68 103 63 84 121 75 105 163 77 112 168 95 132 180 162 201 195 143 181 209 95 132 180 90 121 161 90 117 178 78 115 181 78 115 181 93 141 201 107 160 220 100 145 211 107 160 220 107 160 220 124 179 225 149 212 243 199 239 250 235 251 249 251 255 255 251 255 255 214 242 247 152 198 235 107 160 220 98 133 197 78 115 181 66 94 162 53 66 136 40 57 107 24 41 94 24 33 74 16 24 66 16 24 49 8 16 41 8 16 33 0 8 28 8 8 24 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 0 8 8 8 8 8 0 8 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 33 16 24 41 24 24 49 24 33 66 43 59 92 74 90 135 63 84 121 63 84 121 63 84 121 63 84 121 60 78 115 53 68 103 53 68 103 43 59 92 43 59 92 43 59 92 43 59 92 43 59 92 43 59 92 53 68 103 53 68 103 60 78 115 63 84 121 63 84 121 60 78 115 60 78 115 63 84 121 74 90 135 76 100 142 76 100 142 88 120 127 148 174 163 90 121 161 59 85 139 52 77 133 59 85 139 66 94 162 75 105 163 77 112 168 90 117 178 88 120 127 90 121 161 90 117 178 98 133 197 117 169 217 148 210 233 177 228 227 191 233 234 235 251 249 251 255 255 251 255 255 251 255 255 214 242 247 137 196 219 116 155 198 90 117 178 66 94 162 55 84 152 52 69 123 40 57 107 24 41 94 24 33 74 16 24 57 8 16 49 8 16 33 8 8 33 0 0 24 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 0 8 8 0 8 8 0 0 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 24 16 16 33 16 24 49 24 33 57 33 33 78 53 68 103 43 59 92 43 59 92 53 68 103 53 68 103 43 59 92 45 57 82 45 57 82 37 45 74 41 41 57 41 41 57 41 49 70 41 49 70 45 57 82 43 59 92 60 63 86 43 59 92 53 68 103 60 78 115 60 78 115 60 78 115 74 90 135 74 90 135 76 100 142 76 100 142 74 90 135 76 100 142 55 70 111 53 68 103 43 59 92 40 57 107 36 52 95 41 70 115 52 69 123 52 77 133 66 90 148 62 84 92 91 90 91 110 107 105 88 120 127 148 174 163 150 185 180 150 185 180 160 207 214 217 237 230 185 218 206 191 233 234 223 250 248 235 251 249 248 251 243 251 255 255 191 233 234 115 150 210 93 141 201 78 115 181 66 94 162 55 84 152 41 70 115 36 52 95 24 33 74 16 24 66 8 16 49 8 8 41 0 8 28 0 0 24 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 0 8 8 8 8 8 8 16 8 16 16 8 16 24 16 16 33 16 16 33 24 24 49 24 24 57 33 41 74 43 59 92 26 43 70 26 43 70 41 49 70 41 49 70 41 49 70 41 49 70 46 54 70 46 54 70 41 49 70 41 41 57 41 41 57 41 49 70 46 54 70 60 63 86 60 63 86 62 84 92 45 57 82 45 57 82 53 68 103 60 78 115 60 63 86 45 57 82 60 63 86 53 68 103 55 70 111 46 54 70 45 57 82 37 45 74 37 45 74 45 57 82 43 59 92 45 57 82 45 57 82 46 54 70 51 68 68 53 68 103 60 78 115 62 84 92 89 94 83 91 90 91 106 129 110 129 158 144 148 174 163 162 201 195 162 201 195 160 207 214 160 207 214 185 218 206 191 233 234 191 233 234 214 242 247 235 251 249 235 251 249 137 196 219 116 155 198 93 141 201 77 112 168 66 90 148 41 70 115 36 52 95 24 33 82 16 24 66 8 16 49 8 8 41 8 8 33 0 0 24 0 0 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 0 8 8 8 8 8 8 0 8 8 8 16 8 8 16 8 16 16 16 16 24 16 16 33 16 24 41 24 24 49 24 33 66 33 41 74 24 41 57 24 33 49 24 33 49 33 33 53 37 39 51 41 41 57 41 41 57 41 49 70 41 49 70 41 49 70 41 41 57 46 54 70 46 54 70 46 54 70 46 54 70 60 63 86 60 63 86 59 55 68 41 49 70 46 54 70 46 54 70 46 54 70 45 57 82 45 57 82 41 41 57 45 57 82 51 68 68 46 54 70 33 33 41 33 33 41 33 41 41 43 51 51 43 51 51 43 51 51 43 51 51 43 51 51 43 51 51 55 70 57 80 76 72 77 85 72 91 90 91 91 90 91 110 107 105 110 107 105 148 174 163 150 185 180 192 198 180 185 218 206 146 199 195 150 185 180 162 201 195 217 237 230 214 242 247 217 237 230 214 242 247 235 251 249 163 210 237 117 169 217 93 141 201 78 115 181 55 84 152 42 63 138 35 46 109 24 33 82 16 24 66 8 16 49 8 8 41 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 0 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 24 16 16 33 16 24 41 24 24 57 24 33 74 33 41 74 24 33 49 16 24 41 24 24 41 24 24 41 24 24 41 24 24 41 24 33 41 24 24 41 24 24 41 33 33 41 41 41 57 41 41 57 33 33 41 33 33 53 41 41 57 37 39 51 41 41 57 33 33 53 24 33 49 24 24 41 33 33 53 33 33 53 41 41 57 41 41 57 37 39 51 43 51 51 43 51 51 43 51 51 37 39 51 24 33 41 24 33 41 24 33 41 33 41 41 33 41 41 37 39 51 43 51 51 43 51 51 58 75 69 51 68 68 43 51 51 55 70 57 55 70 57 68 68 68 66 78 70 87 107 89 87 107 89 127 132 122 150 185 180 185 218 206 185 218 206 185 218 206 162 201 195 162 201 195 185 218 206 185 218 206 177 228 227 177 228 227 214 242 247 191 233 234 117 169 217 93 141 201 78 115 181 55 90 164 39 55 130 33 38 93 20 24 78 16 24 66 8 16 49 8 8 41 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 16 16 16 16 24 16 16 33 16 24 41 24 24 57 24 33 74 24 33 57 16 24 33 16 24 33 16 24 33 16 24 33 16 16 33 16 16 33 16 24 33 16 16 33 24 24 33 33 33 41 41 41 57 37 39 51 37 39 51 41 41 57 37 39 51 24 33 41 24 24 33 16 16 33 24 24 33 24 24 41 24 24 41 24 24 41 37 39 51 37 39 51 37 39 51 37 39 51 37 39 51 37 39 51 37 39 51 24 33 41 24 24 33 24 24 33 24 24 33 33 33 33 33 41 41 37 39 51 60 54 57 43 51 51 33 41 41 33 49 41 43 51 51 43 51 51 43 51 51 45 49 45 55 70 57 66 78 70 66 78 70 77 85 72 106 129 110 148 174 163 148 174 163 129 158 144 148 174 163 150 185 180 146 199 195 185 218 206 160 207 214 177 228 227 191 233 234 214 242 247 223 250 248 127 169 215 93 141 201 71 101 189 55 84 152 38 51 120 33 38 93 24 33 82 16 16 66 8 16 49 8 8 41 0 8 28 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 16 16 16 16 24 16 16 33 16 24 41 24 24 57 24 33 74 24 33 49 16 16 33 16 16 24 16 16 24 16 16 24 16 16 24 24 24 33 16 16 24 16 24 33 24 24 33 24 24 33 33 33 41 33 33 41 33 33 41 33 33 41 33 33 41 24 24 41 33 33 33 16 16 24 16 16 24 24 24 24 16 16 33 24 24 33 24 16 33 24 33 41 33 33 41 33 33 41 33 33 41 24 33 41 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 33 33 33 33 33 33 33 33 41 33 41 41 43 51 51 33 41 41 33 41 41 33 49 41 43 51 51 33 49 41 45 49 45 45 49 45 46 54 70 77 85 72 66 87 71 127 132 122 91 119 96 91 119 96 91 119 96 91 119 96 105 134 126 150 185 180 146 199 195 146 199 195 146 199 195 177 228 227 191 233 234 214 242 247 223 250 248 127 169 215 84 125 202 71 101 189 55 84 152 39 55 130 24 41 94 20 24 78 10 18 60 8 16 49 0 8 41 0 8 28 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 0 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 24 24 41 24 33 66 33 33 78 24 24 49 16 16 24 8 16 24 8 16 24 16 16 24 16 24 33 16 16 24 8 16 24 8 16 24 16 24 24 16 24 24 8 16 24 33 33 41 33 33 33 33 33 33 33 33 33 33 33 33 24 24 33 16 16 24 8 16 24 16 16 24 16 16 16 16 16 24 16 16 24 16 16 24 24 24 33 24 24 33 24 33 41 24 24 33 16 24 24 16 24 24 16 24 24 16 24 24 24 24 24 24 24 33 24 24 33 24 24 33 33 33 33 33 33 41 33 41 41 33 41 41 33 41 41 43 51 51 51 68 68 51 68 68 55 70 57 55 70 57 66 78 70 58 75 69 66 78 70 74 97 78 74 97 78 74 97 78 66 78 70 87 107 89 106 129 110 91 119 96 88 120 127 124 170 165 146 199 195 124 170 165 146 199 195 160 207 214 160 207 214 177 228 227 214 242 247 124 179 225 84 125 202 71 101 189 59 71 145 35 46 109 24 41 94 20 24 78 10 18 60 8 8 49 0 8 41 0 0 24 0 0 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 16 33 16 24 41 24 24 57 33 33 78 24 33 49 16 16 24 8 16 16 8 16 16 24 24 24 8 16 24 29 29 27 29 29 27 16 16 24 29 29 27 45 49 45 8 16 16 8 16 16 16 24 24 24 24 24 29 29 27 16 24 24 16 16 24 41 41 41 24 24 33 16 16 24 16 16 24 16 16 16 16 16 16 24 24 33 24 24 33 16 16 24 16 24 24 16 24 24 16 24 33 16 24 24 16 16 24 24 24 24 33 33 33 24 24 24 24 24 33 33 33 41 33 41 41 33 41 41 33 33 33 33 33 41 24 33 41 43 51 51 51 68 68 51 68 68 66 87 71 77 85 72 74 97 78 66 87 71 58 75 69 66 78 70 74 97 78 66 87 71 74 97 78 66 87 71 62 84 92 74 97 78 74 97 78 87 107 89 110 151 136 110 151 136 124 170 165 124 170 165 150 185 180 160 207 214 160 207 214 177 228 227 199 239 250 136 176 233 83 113 204 66 94 162 53 66 136 35 46 109 24 41 94 18 21 71 10 18 60 8 8 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 16 24 41 24 24 57 28 45 82 24 33 49 8 16 24 8 16 16 8 16 16 8 16 16 24 24 24 16 16 24 33 33 33 24 24 24 29 29 27 24 24 24 24 24 24 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 16 16 24 16 16 16 16 16 16 16 16 24 16 16 24 24 24 24 16 16 16 16 16 24 16 24 24 33 33 33 33 33 33 24 24 24 16 16 24 16 16 24 16 24 24 24 24 33 33 33 33 41 41 41 49 49 49 49 49 49 45 49 45 43 51 51 45 49 45 29 29 27 43 51 51 33 41 41 43 51 51 51 68 68 58 75 69 66 78 70 87 107 89 74 97 78 58 75 69 47 60 50 43 51 51 58 75 69 58 75 69 58 75 69 58 75 69 58 75 69 58 75 69 66 87 71 66 87 71 74 97 78 105 134 126 129 158 144 124 170 165 110 151 136 124 170 165 160 207 214 177 228 227 177 228 227 199 239 250 107 160 220 83 113 204 55 90 164 42 63 138 35 46 109 20 28 90 18 21 71 8 16 57 8 8 41 0 0 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 24 24 41 24 24 57 33 33 78 24 33 57 16 16 24 16 16 24 8 8 16 8 8 16 8 8 16 8 16 16 16 16 24 29 29 27 24 24 24 16 24 24 8 8 16 8 16 16 8 16 16 8 16 16 24 24 33 8 16 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 16 16 16 16 16 16 16 16 16 60 54 57 24 24 24 24 24 24 24 24 33 24 24 24 41 41 41 24 24 33 49 41 49 49 41 49 60 54 57 68 68 68 59 55 68 45 49 45 45 49 45 41 41 41 47 60 50 43 51 51 55 70 57 55 70 57 55 70 57 55 70 57 66 78 70 55 70 57 66 78 70 58 75 69 55 70 57 47 60 50 55 70 57 66 87 71 74 97 78 58 75 69 66 87 71 66 87 71 66 87 71 87 107 89 66 87 71 66 87 71 91 119 96 110 151 136 105 134 126 110 151 136 110 151 136 124 170 165 146 199 195 177 228 227 199 239 250 214 242 247 115 150 210 71 101 189 59 78 164 39 55 130 35 46 109 20 28 90 16 16 66 8 16 49 0 8 41 0 0 24 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 16 41 24 24 57 33 33 78 24 33 57 16 16 24 33 33 33 8 16 16 8 8 16 8 8 16 8 8 16 29 29 27 24 24 24 33 33 33 8 16 16 8 8 16 8 16 16 8 16 16 8 16 16 8 16 16 16 24 24 8 16 16 8 8 16 8 16 16 16 16 24 16 16 16 16 16 24 8 16 16 8 8 16 24 24 24 37 39 30 24 24 33 24 24 33 16 16 24 24 24 24 24 24 33 49 49 49 49 41 49 33 33 41 33 33 33 24 24 24 24 24 24 24 24 33 24 24 33 33 33 33 41 41 41 33 33 33 29 29 27 29 29 27 41 41 41 60 54 57 80 76 72 55 70 57 55 70 57 55 70 57 58 75 69 55 70 57 66 78 70 66 78 70 74 97 78 89 94 83 77 85 72 74 97 78 91 119 96 91 119 96 106 129 110 87 107 89 74 97 78 91 119 96 105 134 126 110 151 136 105 134 126 110 151 136 110 151 136 150 185 180 160 207 214 223 250 248 214 242 247 90 129 215 71 101 189 59 78 164 42 63 138 26 39 109 20 24 78 10 18 60 8 8 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 16 33 24 24 49 33 33 78 26 43 70 16 16 24 16 24 24 45 49 45 0 8 8 8 8 16 8 8 16 16 16 24 29 29 27 16 16 16 16 16 16 8 8 16 16 16 16 16 16 24 16 16 16 8 16 16 8 16 16 8 8 16 8 8 16 16 24 24 16 8 16 16 16 16 8 8 16 8 8 16 24 24 24 16 16 16 16 16 16 16 24 24 24 24 33 29 29 27 29 29 27 24 24 33 24 24 33 33 33 41 16 16 24 16 16 24 24 24 24 29 29 27 24 24 33 24 24 33 24 24 24 29 29 27 33 33 33 33 41 41 41 41 41 57 53 45 66 66 49 68 68 68 68 68 68 60 54 57 60 54 57 68 68 68 66 78 70 77 85 72 77 85 72 109 106 89 89 94 83 77 85 72 88 95 75 89 94 83 106 129 110 108 126 97 91 119 96 87 107 89 74 97 78 87 107 89 87 107 89 91 119 96 106 129 110 106 129 110 88 120 127 129 158 144 160 207 214 191 233 234 191 233 234 191 233 234 90 129 215 70 108 192 49 70 152 38 51 120 20 28 90 18 21 71 8 16 57 8 8 41 0 0 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 24 24 24 41 24 33 66 37 45 74 16 24 24 16 16 24 57 53 45 29 29 27 16 16 16 29 29 27 24 24 24 33 33 33 16 16 16 37 39 30 16 16 16 24 24 24 16 24 24 24 24 24 33 33 33 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 8 8 16 8 8 16 8 8 16 24 24 24 16 16 16 24 24 24 33 33 41 24 24 33 24 24 33 24 24 33 24 24 24 24 24 33 41 41 41 24 24 33 24 24 33 24 24 33 24 24 33 33 33 33 29 29 27 29 29 27 33 33 33 60 54 57 45 49 45 66 66 49 49 49 49 60 54 57 60 54 57 60 54 57 60 54 57 68 68 68 74 74 61 80 76 72 80 76 72 77 85 72 89 94 83 88 95 75 86 86 74 89 94 83 89 94 83 89 94 83 87 107 89 87 107 89 108 126 97 74 97 78 58 75 69 66 87 71 87 107 89 87 107 89 106 129 110 110 151 136 150 185 180 162 201 195 143 181 209 191 233 234 152 198 235 90 129 215 66 91 183 42 63 138 35 46 109 24 33 82 16 16 66 8 8 49 0 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 0 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 41 24 24 57 33 33 78 16 24 33 8 8 16 29 29 27 57 53 45 33 33 33 66 57 49 57 53 45 24 20 16 16 16 16 29 29 27 29 29 27 16 16 16 24 24 24 33 33 33 16 16 16 16 16 16 16 16 16 8 8 16 16 16 16 8 8 16 8 8 16 24 24 24 8 8 16 16 16 16 24 16 24 16 16 16 29 29 27 16 16 16 24 16 24 24 24 33 16 16 24 16 16 24 24 24 33 24 24 33 33 33 41 24 24 33 59 55 68 33 33 41 33 33 41 41 33 41 41 33 41 24 24 33 33 33 33 49 49 49 80 76 72 45 49 45 41 41 41 49 49 49 57 53 45 60 54 57 80 76 72 86 86 74 80 76 72 86 86 74 89 94 83 88 95 75 89 94 83 89 94 83 86 86 74 88 95 75 89 94 83 109 106 89 119 115 103 108 126 97 108 126 97 74 97 78 55 70 57 66 87 71 77 85 72 125 124 107 130 152 124 166 162 140 106 129 110 129 158 144 112 157 169 116 155 198 160 207 214 214 242 247 107 160 220 83 113 204 55 90 164 39 55 130 33 38 93 18 21 71 10 18 60 8 8 41 0 8 28 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 24 24 49 24 33 74 24 33 49 8 8 8 8 8 8 16 16 16 33 33 33 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 16 16 16 16 16 24 24 24 24 24 24 24 16 16 16 16 16 24 8 8 16 16 16 16 8 8 16 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 29 29 27 16 16 24 29 29 27 29 29 27 16 16 24 16 16 24 16 16 24 16 16 24 49 49 49 33 33 41 33 24 41 33 24 41 24 24 33 24 24 33 49 41 49 59 55 68 41 41 41 33 33 33 49 49 49 49 49 49 49 41 41 57 53 45 66 57 49 91 90 91 91 90 91 125 124 107 119 115 103 119 115 103 125 124 107 143 138 118 151 152 132 143 138 118 143 138 118 143 138 118 151 152 132 143 138 118 125 124 107 109 106 89 108 126 97 108 126 97 77 85 72 76 82 60 66 87 71 91 119 96 143 138 118 192 198 180 192 198 180 148 174 163 129 158 144 150 185 180 160 207 214 160 207 214 160 207 214 199 239 250 100 145 211 71 101 189 59 71 145 35 46 109 24 33 82 18 21 71 8 16 57 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 41 24 33 66 26 43 70 8 16 16 0 8 8 16 16 16 16 16 24 24 24 24 16 16 16 24 24 24 24 24 24 24 24 24 29 29 27 24 20 16 24 24 24 24 24 24 33 33 33 8 8 8 16 16 16 8 8 16 0 0 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 24 16 24 16 8 16 29 29 27 16 16 16 33 33 33 16 16 24 16 16 24 16 16 16 16 16 24 16 16 33 16 16 33 24 24 33 24 24 33 24 24 33 33 33 41 41 33 41 41 33 41 49 41 49 49 41 49 68 68 68 80 76 72 68 68 68 80 76 72 91 90 91 109 106 89 127 132 122 125 124 107 119 115 103 143 138 118 151 152 132 151 152 132 166 162 140 151 152 132 166 162 140 151 152 132 166 162 140 166 162 140 151 152 132 151 152 132 119 115 103 86 86 74 88 95 75 89 94 83 125 124 107 127 132 122 130 152 124 166 162 140 192 198 180 192 198 180 150 185 180 217 237 230 217 237 230 160 207 214 223 250 248 163 210 237 83 113 204 66 94 162 53 66 136 35 46 109 24 33 82 16 16 66 8 8 49 0 0 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 16 41 24 24 57 33 33 78 16 24 33 0 0 0 0 0 0 16 16 16 16 16 16 24 24 24 29 29 27 24 24 24 24 24 24 24 20 16 24 20 16 16 16 16 24 20 16 16 16 16 16 16 16 16 16 16 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 8 8 8 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 16 16 24 16 16 16 16 16 24 16 16 16 16 16 16 16 16 24 16 16 24 24 24 33 24 24 33 24 16 24 16 16 33 24 24 41 33 33 41 33 41 41 60 54 57 49 49 49 49 41 49 49 41 49 49 41 41 45 49 45 49 49 49 60 54 57 86 86 74 110 107 105 151 152 132 166 162 140 151 152 132 125 124 107 125 124 107 151 152 132 125 124 107 143 138 118 129 158 144 166 162 140 166 162 140 119 115 103 109 106 89 77 85 72 88 95 75 89 94 83 127 132 122 166 162 140 192 198 180 151 152 132 192 198 180 236 241 223 213 223 206 248 251 243 217 237 230 236 241 223 248 251 243 248 251 243 117 169 217 83 113 204 59 78 164 39 55 130 24 41 94 18 21 71 8 16 49 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 24 24 41 24 33 74 24 33 57 8 8 8 0 0 0 0 0 0 24 24 24 8 8 8 24 20 16 24 24 24 29 29 27 29 29 27 29 29 27 8 8 8 8 8 8 8 8 8 8 8 8 24 24 24 16 16 16 8 8 8 8 8 8 8 8 16 16 16 24 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 16 16 16 8 8 8 0 0 8 8 8 8 16 16 16 24 20 16 16 16 16 16 16 16 24 24 24 24 24 24 24 16 24 16 16 24 24 16 33 24 24 41 33 33 53 33 33 53 33 33 53 49 41 49 49 41 49 33 33 41 41 33 41 49 41 49 49 49 49 49 41 49 45 49 45 68 68 68 68 68 68 60 54 57 89 94 83 109 106 89 125 124 107 166 162 140 166 162 140 151 152 132 125 124 107 88 95 75 86 86 74 109 106 89 143 138 118 143 138 118 109 106 89 89 94 83 88 95 75 89 94 83 109 106 89 125 124 107 151 152 132 192 198 180 166 162 140 192 198 180 213 223 206 213 223 206 248 251 243 248 251 243 248 251 243 248 251 243 248 251 243 217 237 230 90 129 215 66 91 183 53 66 136 35 46 109 20 24 78 10 18 60 8 16 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 24 24 57 24 33 74 16 16 16 16 16 16 24 24 24 24 24 24 24 24 24 29 29 27 43 46 35 24 20 16 8 8 8 29 29 27 29 29 27 16 16 16 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 8 8 8 8 8 8 8 8 8 16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 24 16 24 16 16 24 24 24 33 33 33 41 16 16 33 24 24 33 24 24 41 59 55 68 59 55 68 59 55 68 80 76 72 91 90 91 110 107 105 110 107 105 110 107 105 109 106 89 80 76 72 60 54 57 80 76 72 125 124 107 151 152 132 151 152 132 143 138 118 125 124 107 86 86 74 76 82 60 70 70 52 74 74 61 74 74 61 74 74 61 55 70 57 76 82 60 76 82 60 77 85 72 89 94 83 89 94 83 108 126 97 127 132 122 151 152 132 148 174 163 213 223 206 236 241 223 236 241 223 217 237 230 217 237 230 236 241 223 248 251 243 248 251 243 136 176 233 83 113 204 59 78 164 39 55 130 24 41 94 18 21 71 8 16 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 24 24 41 24 33 66 24 24 41 16 16 16 16 16 16 16 8 16 24 24 24 49 41 41 8 8 0 0 0 0 8 8 8 8 8 8 29 29 27 33 33 33 24 24 24 24 24 24 0 0 0 8 8 8 8 8 16 16 16 16 8 8 16 16 16 16 8 8 16 16 16 16 24 24 24 8 8 8 0 0 8 8 8 8 0 0 8 0 0 8 8 8 8 8 8 8 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 16 16 8 16 16 8 16 16 16 24 16 16 24 24 24 41 59 55 68 60 63 86 80 76 72 91 90 91 110 107 105 110 107 105 110 107 105 110 107 105 119 115 103 80 76 72 68 68 68 80 76 72 109 106 89 119 115 103 109 106 89 109 106 89 109 106 89 70 70 52 57 53 45 57 53 45 57 53 45 66 66 49 70 70 52 80 76 72 110 107 105 119 115 103 125 124 107 125 124 107 127 132 122 166 162 140 166 162 140 192 198 180 192 198 180 213 223 206 236 241 223 236 241 223 236 241 223 236 241 223 236 241 223 248 251 243 248 251 243 199 239 250 90 129 215 70 108 192 55 84 152 35 46 109 24 33 82 10 18 60 8 16 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 24 33 24 24 57 24 33 66 8 16 16 8 8 16 24 24 24 24 24 24 16 16 16 16 16 16 0 0 0 0 0 0 16 16 16 0 0 0 0 0 0 16 16 16 16 16 16 24 24 24 33 33 33 8 8 8 8 8 16 24 24 24 8 8 8 8 8 8 8 8 8 8 8 8 24 24 24 29 29 27 16 16 16 16 16 16 29 29 27 8 8 8 8 8 16 8 8 16 8 0 8 8 8 8 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 8 16 16 16 24 16 16 24 24 24 24 49 49 49 41 41 57 46 54 70 60 63 86 80 76 72 91 90 91 91 90 91 91 90 91 110 107 105 91 90 91 80 76 72 80 76 72 91 90 91 89 94 83 119 115 103 86 86 74 109 106 89 74 74 61 66 66 49 66 66 49 66 66 49 70 70 52 70 70 52 66 66 49 86 86 74 88 95 75 109 106 89 119 115 103 125 124 107 143 138 118 151 152 132 192 198 180 192 198 180 192 198 180 213 223 206 236 241 223 236 241 223 217 237 230 213 223 206 217 237 230 236 241 223 248 251 243 248 251 243 235 251 249 136 176 233 84 125 202 55 90 164 42 63 138 24 41 94 20 24 78 8 16 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 24 16 24 41 24 33 66 24 24 49 16 16 16 16 16 16 16 16 24 37 39 30 8 8 8 0 0 0 0 0 0 0 0 0 8 8 8 0 0 0 16 16 16 8 8 8 24 20 16 8 8 8 0 0 0 8 8 8 16 16 16 24 20 16 16 16 16 0 0 0 24 24 24 16 16 16 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 24 16 24 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 24 24 24 16 16 24 24 16 33 29 29 27 16 16 33 33 33 53 46 54 70 41 49 70 59 55 68 80 76 72 59 55 68 59 55 68 59 55 68 60 54 57 41 33 41 49 41 41 49 41 49 60 54 57 66 57 49 66 57 49 70 70 52 57 49 41 57 53 45 57 49 41 49 49 49 80 76 72 91 90 91 89 94 83 109 106 89 88 95 75 109 106 89 125 124 107 143 138 118 143 138 118 151 152 132 166 162 140 192 198 180 192 198 180 213 223 206 236 241 223 236 241 223 236 241 223 213 223 206 162 201 195 185 218 206 248 251 243 248 251 243 223 250 248 191 233 234 100 145 211 79 113 191 55 84 152 38 51 120 24 33 82 16 24 57 8 16 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 33 66 16 16 24 8 8 8 33 33 33 24 24 24 8 8 8 24 24 24 8 8 8 16 16 16 8 8 8 24 24 24 8 8 8 24 24 24 41 41 41 0 0 0 0 0 0 0 0 0 8 8 8 16 16 16 16 16 16 16 16 16 8 8 8 8 8 8 16 16 16 8 8 16 16 16 16 8 8 16 16 16 24 8 8 16 24 24 24 16 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 8 8 16 8 8 16 24 24 24 29 29 27 24 24 24 16 16 24 16 16 24 33 33 33 24 24 33 33 33 53 33 33 53 41 41 57 49 41 49 60 54 57 41 33 41 41 41 41 49 41 49 41 33 41 41 33 41 57 53 45 49 49 49 49 41 49 57 49 41 66 57 49 66 57 49 66 66 49 66 57 49 57 53 45 66 57 49 86 86 74 109 106 89 119 115 103 109 106 89 109 106 89 119 115 103 119 115 103 143 138 118 143 138 118 166 162 140 166 162 140 166 162 140 192 198 180 213 223 206 236 241 223 213 223 206 213 223 206 213 223 206 148 174 163 185 218 206 248 251 243 217 237 230 223 250 248 136 193 231 93 141 201 66 94 162 42 63 138 24 41 94 16 24 66 8 16 49 0 8 28 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 24 16 24 41 24 33 66 24 33 49 8 8 8 0 0 0 8 8 8 16 16 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 16 29 29 27 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 0 0 0 8 8 8 0 0 0 8 8 8 0 0 0 8 8 8 8 8 16 8 8 8 16 16 16 24 24 24 16 8 16 16 16 24 16 16 24 16 16 24 16 16 16 16 16 24 16 16 16 16 16 16 16 16 24 16 16 24 16 16 24 24 16 24 33 33 33 49 49 49 60 54 57 33 33 33 41 33 41 41 41 57 37 39 51 33 24 41 33 24 41 33 33 41 60 54 57 41 33 41 41 33 41 49 41 49 49 41 49 49 49 49 66 57 49 57 53 45 66 57 49 57 53 45 57 49 41 60 54 57 60 54 57 66 66 49 74 74 61 110 107 105 127 132 122 125 124 107 119 115 103 127 132 122 127 132 122 127 132 122 143 138 118 143 138 118 151 152 132 192 198 180 213 223 206 213 223 206 192 198 180 192 198 180 192 198 180 148 174 163 213 223 206 217 237 230 217 237 230 191 233 234 100 145 211 78 115 181 55 84 152 35 46 109 16 33 78 8 16 49 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 33 24 24 49 24 33 66 16 24 33 8 8 8 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 16 24 20 16 0 0 0 24 20 16 16 16 24 16 16 16 8 16 16 16 16 24 24 24 24 16 8 16 16 8 16 24 24 24 16 16 24 16 16 24 24 24 24 24 24 24 33 33 33 24 24 24 33 33 41 33 33 41 24 24 33 33 24 41 24 24 33 24 24 33 24 24 33 33 24 41 33 33 41 41 33 41 41 33 41 41 33 41 41 33 41 41 33 41 49 41 41 49 41 41 49 41 41 57 49 41 57 49 41 57 53 45 57 53 45 49 49 33 37 39 30 43 46 35 66 66 49 86 86 74 110 107 105 109 106 89 109 106 89 119 115 103 119 115 103 143 138 118 151 152 132 151 152 132 166 162 140 192 198 180 192 198 180 129 158 144 129 158 144 129 158 144 124 170 165 124 170 165 160 207 214 191 233 234 235 251 249 117 169 217 84 125 202 55 90 164 38 51 120 24 33 82 16 24 57 8 8 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 33 66 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 8 8 16 16 8 16 16 16 24 33 33 33 16 16 16 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 37 39 30 33 33 33 16 16 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 16 16 24 41 41 41 24 24 33 16 16 24 16 16 16 16 16 24 24 16 24 24 24 33 24 24 33 49 41 49 24 24 33 33 24 41 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 33 33 41 41 33 41 41 33 41 41 33 41 41 33 41 49 41 41 49 41 41 49 41 41 57 53 45 66 57 49 57 53 45 66 66 49 70 70 52 66 66 49 57 53 45 43 46 35 68 68 68 89 94 83 109 106 89 109 106 89 119 115 103 119 115 103 143 138 118 166 162 140 143 138 118 143 138 118 192 198 180 166 162 140 129 158 144 148 174 163 110 151 136 110 151 136 112 157 169 146 199 195 191 233 234 223 250 248 152 198 235 93 141 201 66 94 162 42 63 138 24 41 94 16 24 66 8 16 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 16 24 16 24 41 24 24 57 24 33 49 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 8 0 0 8 8 8 8 24 16 24 16 8 16 8 8 16 16 16 16 8 8 8 8 8 8 8 8 8 0 0 0 16 16 16 0 0 8 8 8 8 0 0 0 24 24 24 68 68 68 33 33 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 41 41 41 16 16 24 24 24 24 49 49 49 24 24 33 24 24 33 37 39 51 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 33 33 41 41 33 41 49 41 49 49 41 49 49 49 49 60 54 57 60 54 57 57 53 45 60 54 57 57 53 45 74 74 61 80 76 72 70 70 52 74 74 61 66 66 49 57 53 45 57 53 45 74 74 61 109 106 89 109 106 89 119 115 103 125 124 107 125 124 107 125 124 107 125 124 107 143 138 118 127 132 122 148 174 163 162 201 195 150 185 180 129 158 144 112 157 169 162 201 195 177 228 227 223 250 248 191 233 234 93 141 201 71 101 189 53 66 136 35 46 109 16 24 66 8 16 49 0 8 28 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 24 24 41 24 33 66 24 33 41 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 16 16 16 16 16 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 16 16 8 8 16 16 16 24 16 16 24 45 49 45 29 29 27 16 8 16 16 16 24 24 24 24 8 8 16 8 8 16 16 16 24 8 8 16 16 16 24 16 16 24 8 16 16 16 8 16 8 8 16 16 16 16 16 16 24 16 16 16 33 33 41 33 33 41 41 41 41 16 16 24 24 24 24 24 24 33 24 24 33 24 24 33 33 33 41 33 33 41 24 24 33 24 24 33 24 24 33 33 24 41 49 41 49 41 41 41 49 41 49 49 41 49 49 49 49 57 53 45 57 53 45 60 54 57 66 57 49 70 70 52 66 66 49 70 70 52 74 74 61 74 74 61 70 70 52 70 70 52 45 49 45 55 70 57 66 78 70 89 94 83 119 115 103 119 115 103 119 115 103 109 106 89 127 132 122 105 134 126 129 158 144 148 174 163 217 237 230 162 201 195 124 170 165 162 201 195 191 233 234 223 250 248 214 242 247 107 160 220 79 113 191 55 84 152 35 46 109 24 33 74 8 16 49 8 8 33 0 0 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 33 24 24 49 24 33 66 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 16 16 24 29 29 27 8 8 16 8 8 16 16 16 16 16 16 16 24 24 24 8 8 16 8 8 16 8 8 16 16 16 24 8 8 16 8 8 16 16 16 16 16 16 16 16 8 16 16 16 24 24 24 33 68 68 68 8 8 16 8 8 16 24 24 33 24 24 33 41 41 41 24 24 33 24 24 33 33 33 33 24 24 24 24 16 24 24 24 33 24 24 33 24 24 33 33 33 41 33 33 41 41 41 41 41 33 41 49 49 49 49 49 49 60 54 57 60 54 57 66 57 49 66 57 49 74 74 61 86 86 74 86 86 74 89 94 83 86 86 74 76 82 60 76 82 60 74 74 61 57 63 46 47 60 50 66 78 70 89 94 83 127 132 122 151 152 132 192 198 180 129 158 144 129 158 144 110 151 136 150 185 180 185 218 206 148 174 163 150 185 180 223 250 248 214 242 247 199 239 250 136 176 233 84 125 202 55 90 164 38 51 120 24 33 82 16 24 57 8 8 33 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 33 57 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 16 8 16 8 8 16 8 8 16 16 8 16 16 8 16 16 8 16 8 8 16 29 29 27 29 29 27 8 8 16 8 8 16 0 0 8 8 8 8 16 16 24 8 8 16 16 16 16 8 8 16 8 8 16 16 16 24 16 16 16 8 8 16 8 8 16 16 16 24 24 24 33 16 16 24 16 16 24 29 29 27 8 8 16 8 8 16 16 16 24 33 33 33 33 33 41 24 24 33 24 24 33 33 33 41 33 24 41 24 24 33 24 24 33 24 24 33 24 24 33 41 33 41 41 41 41 41 33 41 41 41 41 49 41 49 57 53 45 57 49 41 57 53 45 68 68 68 80 76 72 80 76 72 86 86 74 86 86 74 80 76 72 86 86 74 88 95 75 89 94 83 88 95 75 109 106 89 87 107 89 88 95 75 87 107 89 91 119 96 130 152 124 130 152 124 130 152 124 130 152 124 129 158 144 105 134 126 148 174 163 185 218 206 217 237 230 177 228 227 223 250 248 163 210 237 84 125 202 66 94 162 39 55 130 24 41 94 16 24 57 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 33 24 24 57 24 24 49 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 16 16 16 16 16 8 8 16 45 49 45 49 49 49 8 8 8 0 0 0 0 0 0 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 24 24 33 49 49 49 8 8 16 8 8 16 16 16 16 16 16 16 16 16 24 68 68 68 33 33 41 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 33 33 33 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 33 33 41 33 33 41 41 33 41 41 41 41 49 41 49 49 41 41 57 53 45 57 53 45 70 70 52 74 74 61 74 74 61 74 74 61 74 74 61 80 76 72 80 76 72 74 74 61 86 86 74 88 95 75 109 106 89 125 124 107 108 126 97 125 124 107 130 152 124 130 152 124 91 119 96 106 129 110 106 129 110 106 129 110 129 158 144 148 174 163 185 218 206 185 218 206 160 207 214 214 242 247 199 239 250 100 145 211 78 115 181 49 70 152 35 46 109 16 24 66 8 16 41 0 8 28 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 41 24 33 66 16 24 33 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 16 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 16 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 16 16 16 8 8 16 41 41 41 8 8 16 8 8 8 0 0 0 0 0 0 8 8 16 8 8 16 24 24 24 8 8 16 8 8 16 8 8 16 16 16 24 24 24 24 16 16 16 33 33 33 60 54 57 16 16 16 24 24 24 49 41 49 16 16 24 49 41 49 8 8 16 8 8 16 24 24 33 80 76 72 49 49 49 8 8 16 16 16 24 16 16 24 16 16 24 24 24 33 24 24 33 33 24 41 46 54 70 41 41 57 24 33 41 33 33 41 49 41 41 49 41 41 66 57 49 68 68 68 66 57 49 57 53 45 66 66 49 66 57 49 66 66 49 70 70 52 70 70 52 76 82 60 86 86 74 88 95 75 109 106 89 119 115 103 119 115 103 130 152 124 106 129 110 108 126 97 91 119 96 106 129 110 106 129 110 105 134 126 110 151 136 124 170 165 146 199 195 177 228 227 199 239 250 107 160 220 78 115 181 55 84 152 35 46 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 33 24 24 49 24 33 66 16 16 24 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 8 8 16 8 8 16 8 8 16 16 16 16 8 8 16 8 8 16 0 0 0 0 0 0 8 8 8 24 24 24 16 16 16 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 16 24 16 16 24 49 41 49 24 16 33 16 16 24 24 16 33 16 16 33 16 16 24 24 24 33 24 24 33 37 39 51 37 39 51 33 33 41 41 41 41 49 49 49 16 16 24 16 16 24 16 16 24 16 16 33 41 49 70 33 33 41 24 33 41 33 33 53 45 57 82 33 33 53 45 49 45 49 41 41 57 53 45 57 53 45 57 53 45 57 53 45 57 53 45 57 53 45 66 66 49 70 70 52 74 74 61 74 74 61 86 86 74 88 95 75 109 106 89 109 106 89 108 126 97 74 97 78 91 119 96 66 87 71 127 132 122 130 152 124 106 129 110 88 120 127 110 151 136 146 199 195 161 223 239 179 233 249 117 169 217 79 113 191 55 90 164 38 51 120 24 33 82 16 16 49 8 8 33 8 0 16 0 0 16 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 49 24 33 57 16 16 24 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 16 8 16 16 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 0 0 0 0 24 24 24 24 24 24 8 8 16 16 16 16 8 16 16 8 8 16 8 8 16 16 8 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 33 16 16 24 16 16 24 16 16 24 24 24 33 24 16 33 24 16 33 24 24 33 24 24 33 24 24 33 33 33 41 16 16 24 8 8 16 16 16 33 16 16 33 33 33 41 16 16 24 59 55 68 45 57 82 41 41 57 24 33 49 33 33 33 37 39 30 49 41 41 57 49 41 49 49 33 57 49 41 57 49 41 57 53 45 74 74 61 86 86 74 76 82 60 88 95 75 88 95 75 76 82 60 108 126 97 66 90 148 75 105 163 79 113 191 90 121 161 108 126 97 148 174 163 106 129 110 105 134 126 105 134 126 143 181 209 161 223 239 148 210 233 136 193 231 93 141 201 66 94 162 42 63 138 24 41 94 16 24 57 8 8 33 0 8 16 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 33 57 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 8 16 8 8 16 8 8 16 8 16 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 16 16 16 41 41 41 33 33 33 16 16 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 33 16 16 24 16 16 24 16 16 24 16 16 24 16 16 33 24 16 33 24 24 33 24 24 33 24 24 41 24 24 33 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 24 24 41 16 24 33 16 24 33 16 24 33 24 24 49 24 33 49 33 33 33 37 39 30 43 46 35 57 49 41 57 49 41 49 49 33 57 53 45 66 66 49 76 82 60 76 82 60 76 82 60 66 78 70 90 121 161 75 105 163 66 94 162 66 94 162 66 91 183 116 155 198 192 198 180 106 129 110 106 129 110 129 158 144 124 170 165 149 212 243 149 212 243 136 193 231 93 141 201 71 101 189 42 63 138 24 41 94 16 24 57 8 8 33 0 8 16 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 33 49 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 16 8 16 16 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 8 8 8 41 41 41 24 24 24 16 16 16 8 8 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 24 16 33 16 16 24 16 16 24 16 16 24 16 16 33 24 24 33 24 24 33 24 24 33 24 24 33 16 16 33 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 33 16 16 33 24 24 33 16 16 33 16 24 41 24 33 49 24 33 57 33 33 41 37 39 30 49 49 33 49 49 33 43 46 35 57 63 46 70 70 52 57 63 46 70 70 52 74 74 61 53 68 103 75 105 163 66 94 162 66 94 162 66 94 162 66 94 162 71 101 189 106 129 110 105 134 126 105 134 126 129 158 144 150 185 180 137 196 219 161 223 239 148 210 233 100 145 211 78 115 181 49 70 152 35 46 109 16 24 66 8 16 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 57 24 24 41 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 16 16 8 16 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 16 16 16 45 49 45 16 16 24 16 16 16 8 8 16 16 16 16 8 8 16 16 16 16 16 16 24 16 16 33 16 16 24 16 16 24 16 16 33 24 16 33 24 16 33 24 24 33 24 16 33 16 16 24 24 16 33 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 33 8 16 24 8 16 24 16 16 33 16 24 33 16 24 41 24 33 49 24 33 57 33 33 33 49 41 41 49 49 33 43 46 35 66 57 49 74 74 61 70 70 52 70 70 52 53 68 103 43 59 92 76 100 142 66 90 148 66 94 162 75 105 163 55 84 152 78 115 181 90 121 161 90 121 161 106 129 110 129 158 144 124 170 165 143 181 209 148 210 233 148 210 233 100 145 211 78 115 181 49 70 152 35 46 109 18 21 71 8 16 41 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 16 33 24 24 57 16 24 41 8 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 8 16 16 8 16 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 33 33 33 8 8 16 16 16 24 8 8 16 8 8 16 16 16 24 8 8 16 16 8 16 16 16 16 16 16 24 16 16 24 16 16 33 16 16 33 33 33 41 24 24 33 16 16 24 16 16 24 8 8 8 8 8 16 8 8 16 16 8 16 16 16 24 16 16 24 16 16 24 16 16 24 8 8 24 8 16 24 8 16 24 16 16 33 16 16 24 16 16 33 16 24 41 24 33 57 33 33 41 37 39 30 57 49 41 57 53 45 70 70 52 66 66 49 59 55 68 37 45 74 41 45 87 53 68 103 59 85 139 52 69 123 52 77 133 75 105 163 78 115 181 70 108 192 70 108 192 84 125 202 88 120 127 112 157 169 124 170 165 146 199 195 161 223 239 161 223 239 100 145 211 79 113 191 49 70 152 35 46 109 18 21 71 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 24 41 24 24 57 16 24 33 0 0 8 0 0 8 0 0 8 0 0 16 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 24 24 24 16 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 8 0 0 0 0 0 0 0 0 8 8 8 8 16 16 24 16 8 16 8 8 16 8 16 16 8 8 16 16 16 24 16 8 16 16 16 16 16 16 24 16 16 16 16 16 16 16 16 24 16 16 33 16 16 24 16 16 16 8 8 16 16 16 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 16 24 16 16 24 8 16 24 8 16 24 16 16 33 16 24 41 24 24 49 24 33 57 33 33 33 49 49 33 66 57 49 70 70 52 66 66 49 59 55 68 24 33 66 33 41 74 60 78 115 40 57 107 40 57 107 59 85 139 78 115 181 78 115 181 77 112 168 55 90 164 70 108 192 76 100 142 107 160 220 112 157 169 160 207 214 161 223 239 161 223 239 100 145 211 79 113 191 49 70 152 35 46 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 24 41 24 24 57 16 24 33 0 0 8 0 0 8 0 0 8 0 0 16 0 0 8 0 0 16 8 0 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 8 8 8 16 8 8 16 0 0 16 8 0 16 8 0 16 8 0 8 8 8 16 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 16 8 8 16 8 8 16 0 0 8 0 0 0 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 16 16 16 16 16 8 16 16 16 24 8 8 16 8 8 16 8 8 16 8 8 8 16 16 24 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 24 24 33 16 16 24 8 16 24 8 16 24 16 24 41 16 24 49 24 33 49 24 41 57 29 29 27 57 49 41 57 53 45 57 63 46 51 68 68 24 33 66 24 33 66 43 59 92 40 57 107 55 70 111 41 70 115 90 117 178 98 133 197 95 132 180 49 70 152 70 108 192 90 117 178 107 160 220 124 179 225 161 223 239 179 233 249 179 233 249 100 145 211 79 113 191 59 78 164 35 46 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 24 41 24 24 57 16 24 33 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 0 0 8 0 0 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 8 0 0 16 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 16 16 16 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 8 16 16 16 16 16 16 24 16 16 24 16 16 16 8 8 8 8 8 16 16 16 24 16 16 24 24 16 33 24 24 41 24 24 33 8 8 16 16 16 16 8 8 16 16 16 24 24 16 33 59 55 68 59 55 68 37 39 51 37 39 51 41 41 57 16 24 41 24 33 49 24 33 57 24 33 57 33 33 41 37 39 30 49 49 33 66 57 49 46 54 70 24 33 57 24 33 66 28 45 82 43 59 92 53 68 103 52 69 123 75 105 163 66 90 148 78 115 181 55 84 152 70 108 192 90 121 161 117 169 217 161 223 239 179 233 249 179 233 249 161 223 239 100 145 211 71 101 189 49 70 152 26 39 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 24 41 24 24 57 16 24 33 0 0 8 0 0 8 8 8 8 0 0 8 0 0 8 8 8 16 0 0 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 0 8 0 0 8 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 16 8 16 16 8 16 16 16 16 16 16 16 16 16 16 8 8 16 8 8 8 8 8 16 16 16 24 24 24 33 24 24 33 16 16 24 16 16 24 24 16 33 8 8 16 8 8 16 16 16 16 33 33 41 24 24 33 16 16 33 37 39 51 33 33 53 24 24 41 24 33 49 41 49 70 24 24 49 33 41 74 33 41 41 66 57 49 66 57 49 45 57 82 24 33 57 24 33 57 37 45 74 43 59 92 59 85 139 66 90 148 59 85 139 52 77 133 78 115 181 55 84 152 70 108 192 93 141 201 146 199 195 179 233 249 179 233 249 161 223 239 191 233 234 100 145 211 71 101 189 49 70 152 35 46 109 20 24 78 8 8 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 24 41 24 24 57 16 24 33 0 0 0 0 0 8 8 8 8 8 8 16 8 8 8 8 8 8 8 8 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 16 8 16 16 8 24 8 8 16 16 8 16 8 8 16 16 16 16 8 8 16 8 8 8 8 8 8 16 16 24 16 16 24 16 16 33 16 16 24 16 16 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 8 8 16 8 8 16 24 24 33 41 41 57 41 41 57 24 24 49 24 24 49 24 33 49 33 41 74 41 49 70 49 49 49 37 45 74 41 41 57 43 51 51 33 41 74 45 57 82 28 45 82 28 45 82 60 78 115 59 85 139 66 90 148 90 117 178 98 133 197 117 169 217 136 193 231 160 207 214 160 207 214 149 212 243 179 233 249 148 210 233 100 145 211 71 101 189 49 70 152 26 39 109 18 21 71 8 8 49 0 0 33 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 24 33 24 24 57 16 24 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 16 16 33 24 24 41 24 24 41 24 24 33 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 33 16 24 41 16 24 41 16 24 41 16 24 49 24 33 57 24 33 66 24 33 66 41 41 57 43 46 35 37 45 74 37 45 74 45 57 82 28 45 82 36 52 95 52 77 133 59 85 139 59 85 139 107 160 220 88 120 127 116 155 198 137 196 219 116 155 198 148 210 233 199 239 250 148 210 233 90 129 215 66 91 183 42 63 138 26 39 109 18 21 71 8 8 49 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 16 33 24 24 57 16 24 33 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 0 8 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 24 16 16 24 16 16 33 24 24 49 16 24 41 16 24 49 24 24 49 24 33 49 24 24 49 24 33 57 24 33 57 37 45 74 33 41 74 41 45 87 41 45 87 28 45 82 59 85 139 116 155 198 75 105 163 136 193 231 107 160 220 88 120 127 112 157 169 116 155 198 149 212 243 191 233 234 148 210 233 90 129 215 66 91 183 42 63 138 26 39 109 18 21 71 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 16 33 24 24 57 24 24 41 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 8 24 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 24 8 16 24 16 16 33 8 16 33 24 24 49 16 24 41 16 24 41 16 24 41 24 24 49 24 24 41 16 24 41 16 24 41 24 33 49 33 41 74 53 68 103 53 68 103 43 59 92 66 90 148 90 117 178 95 132 180 76 100 142 66 90 148 93 141 201 112 157 169 112 157 169 179 233 249 161 223 239 148 210 233 84 125 202 66 91 183 42 63 138 24 41 94 16 16 66 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 16 33 24 24 49 24 24 41 0 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 16 24 16 16 33 16 16 24 16 16 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 24 16 16 24 8 8 24 8 16 24 16 16 24 16 16 33 24 33 49 16 24 41 16 24 41 16 24 41 24 24 41 16 24 41 16 24 41 24 24 41 33 33 53 41 41 57 24 33 57 24 33 66 37 45 74 52 69 123 76 100 142 53 68 103 40 57 107 52 69 123 98 133 197 90 121 161 90 121 161 137 196 219 161 223 239 136 193 231 84 125 202 66 91 183 42 63 138 24 41 94 16 16 66 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 8 16 16 16 24 16 16 33 24 24 49 24 24 49 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 0 0 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 16 0 0 8 0 0 16 0 0 16 8 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 24 24 33 16 16 33 16 16 24 8 8 16 8 8 16 16 16 24 16 16 24 8 8 24 8 8 24 8 16 24 16 16 24 16 16 33 24 24 49 33 33 53 16 24 41 16 24 33 16 16 33 16 16 33 16 16 33 16 24 33 24 24 41 24 24 49 24 33 57 24 33 66 24 33 57 36 52 95 36 52 95 36 52 95 53 68 103 52 69 123 75 105 163 95 132 180 112 157 169 136 193 231 148 210 233 136 193 231 84 125 202 66 91 183 42 63 138 24 41 94 10 18 60 8 8 41 0 0 24 0 0 16 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 24 16 16 33 24 24 49 24 24 49 8 8 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 0 8 8 8 16 8 8 16 8 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 0 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 24 24 33 16 16 24 16 16 24 8 8 16 8 8 16 16 16 24 16 16 24 8 8 16 8 8 16 16 16 24 33 24 41 24 24 41 33 33 53 24 33 49 16 16 33 16 16 24 16 16 33 16 16 24 16 16 33 16 16 33 16 24 41 33 33 53 24 33 49 24 33 57 24 33 66 36 52 95 28 45 82 28 45 82 28 45 82 36 52 95 36 52 95 93 141 201 98 133 197 124 179 225 148 210 233 117 169 217 83 113 204 59 78 164 39 55 130 20 28 90 10 18 60 8 8 33 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 41 24 24 57 16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 0 0 8 0 0 8 8 8 16 8 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 16 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 0 8 8 8 8 16 8 8 16 24 16 33 16 16 24 8 8 16 8 8 16 8 8 16 16 16 24 8 8 24 16 16 24 8 8 24 16 16 33 37 39 51 33 33 53 41 49 70 16 24 41 8 16 24 16 16 33 16 16 33 16 16 24 16 16 33 16 16 33 16 24 33 16 16 33 16 16 33 16 24 41 24 33 57 36 52 95 28 45 82 28 45 82 26 43 70 24 33 74 36 52 95 52 69 123 79 113 191 100 145 211 136 193 231 100 145 211 71 101 189 49 70 152 38 51 120 24 33 82 8 16 57 0 0 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 33 24 24 57 16 16 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 16 16 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 0 0 8 0 0 8 0 0 8 8 8 16 0 0 8 0 0 8 16 16 16 16 16 16 0 0 8 0 0 8 0 0 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 8 8 8 16 16 24 24 16 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 8 8 24 8 8 24 16 16 24 16 16 33 45 57 82 24 24 41 16 16 24 24 24 33 37 39 51 33 33 41 16 16 33 16 16 33 16 24 41 16 24 33 16 24 33 16 24 41 24 33 57 28 45 82 26 43 70 28 45 82 26 43 70 43 59 92 24 41 82 40 57 107 59 85 139 100 145 211 124 179 225 90 129 215 66 91 183 49 70 152 35 46 109 20 24 78 8 16 49 0 0 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 33 24 24 57 16 24 33 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 0 0 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 8 8 16 16 16 24 24 24 33 16 16 33 16 16 24 16 8 24 16 8 24 8 8 24 8 16 24 16 16 24 16 24 41 16 24 33 37 39 51 46 54 70 60 63 86 41 41 57 33 33 53 41 41 57 33 33 53 16 24 41 16 24 41 16 24 41 24 33 57 41 45 87 28 45 82 36 52 95 43 59 92 36 52 95 36 52 95 59 85 139 77 112 168 107 160 220 124 179 225 84 125 202 66 91 183 42 63 138 26 39 109 18 21 71 8 16 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 24 24 49 24 24 41 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 8 8 8 8 0 8 0 0 8 8 0 8 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 16 8 16 16 16 24 16 16 24 16 16 24 8 8 16 8 8 24 8 8 24 8 16 24 16 16 41 16 16 33 24 24 33 24 24 33 24 24 33 24 24 33 24 24 33 24 24 41 37 39 51 16 24 33 24 24 49 16 24 41 24 24 49 33 41 74 37 45 74 43 59 92 43 59 92 36 52 95 43 59 92 59 85 139 98 133 197 90 117 178 136 193 231 124 179 225 84 125 202 66 91 183 42 63 138 24 41 94 16 16 66 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 24 24 41 24 24 49 8 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 8 8 16 8 8 16 8 16 16 8 8 16 16 16 24 16 16 33 16 24 41 16 16 33 8 16 24 8 16 24 8 16 24 8 16 24 16 24 33 24 33 41 16 16 33 16 24 33 41 49 70 41 49 70 33 33 53 33 41 74 33 41 74 43 59 92 43 59 92 40 57 107 52 77 133 66 90 148 98 133 197 127 169 215 161 223 239 124 179 225 84 125 202 66 91 183 39 55 130 20 28 90 16 16 66 8 8 41 0 0 24 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 24 24 41 24 24 57 16 16 24 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 24 24 41 16 16 41 16 16 33 8 16 24 8 8 16 8 16 24 8 16 24 16 16 24 24 24 41 24 24 41 37 39 51 41 41 57 41 49 70 16 24 49 16 24 49 26 43 70 24 33 57 26 43 70 43 59 92 52 69 123 52 69 123 66 90 148 98 133 197 136 193 231 179 233 249 100 145 211 79 113 191 59 78 164 38 51 120 20 28 90 8 16 57 8 8 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 24 33 24 24 57 24 24 41 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 24 33 24 41 37 39 51 24 24 41 24 24 33 16 24 33 33 33 41 24 33 41 16 24 33 24 24 41 24 24 41 24 33 41 24 24 41 16 24 41 16 24 41 16 24 49 24 33 66 16 24 49 26 43 70 43 59 92 41 70 115 52 77 133 66 90 148 115 150 210 148 210 233 161 223 239 90 129 215 71 101 189 49 70 152 35 46 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 16 33 24 24 49 24 24 49 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 8 0 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 24 24 33 24 24 33 16 16 24 16 16 24 16 16 24 16 16 24 16 24 33 16 24 33 16 24 33 16 24 33 16 24 41 24 33 49 24 33 57 26 43 70 24 41 82 24 33 57 16 24 49 16 33 61 36 52 95 41 70 115 52 77 133 66 90 148 117 169 217 179 233 249 136 176 233 84 125 202 66 91 183 42 63 138 24 41 94 16 24 66 8 8 41 0 0 24 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 16 41 24 24 57 16 16 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 16 16 16 16 16 16 24 16 24 33 24 24 33 24 24 33 16 24 33 16 33 41 16 33 49 24 33 49 16 33 49 26 43 70 28 45 82 16 24 49 16 24 49 16 24 57 28 45 82 41 70 115 59 85 139 66 94 162 136 193 231 199 239 250 100 145 211 79 113 191 59 78 164 38 51 120 20 28 90 10 18 60 8 8 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 16 33 24 24 49 16 24 41 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 16 16 24 16 16 24 8 16 24 16 16 33 8 16 33 16 24 33 16 33 41 16 33 49 24 33 49 24 41 57 26 43 70 36 52 95 24 33 57 16 24 49 24 33 66 41 45 87 52 69 123 75 105 163 98 133 197 148 210 233 191 233 234 84 125 202 71 101 189 49 70 152 35 46 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 16 24 49 24 24 49 16 16 16 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 16 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 16 24 16 16 24 16 16 33 16 24 33 16 24 41 24 33 49 24 41 57 26 43 70 36 52 95 28 45 82 24 33 57 24 33 66 24 33 74 36 52 95 52 77 133 66 94 162 93 141 201 148 210 233 136 176 233 84 125 202 66 91 183 42 63 138 24 41 94 16 24 66 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 24 33 24 24 57 16 24 33 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 0 0 8 0 0 8 0 0 8 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 0 8 0 0 8 8 8 8 8 8 8 16 8 16 16 16 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 24 16 16 24 16 16 24 16 16 33 16 16 33 16 16 33 16 16 33 16 33 49 24 41 57 37 45 74 36 52 95 26 43 70 24 33 66 24 33 74 28 45 82 40 57 107 66 90 148 79 113 191 117 169 217 148 210 233 100 145 211 71 101 189 49 70 152 38 51 120 24 33 82 16 16 49 8 8 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 16 16 16 16 16 24 16 16 33 24 24 49 24 24 49 16 16 16 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 16 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 16 0 0 8 0 0 8 0 0 8 0 0 8 8 8 16 16 16 16 8 8 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 0 8 8 0 8 8 8 16 16 16 16 16 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 16 24 8 16 24 16 16 24 16 16 24 16 16 33 16 16 33 16 16 33 16 16 33 24 24 49 33 41 74 26 43 70 36 52 95 24 33 66 24 33 66 24 33 74 36 52 95 52 69 123 78 115 181 93 141 201 137 196 219 124 179 225 84 125 202 66 91 183 42 63 138 26 39 109 18 21 71 8 16 41 8 8 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 24 41 24 24 57 16 24 33 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 16 8 8 16 0 8 8 0 8 8 0 0 8 0 0 16 0 8 16 0 8 8 0 0 8 0 0 8 8 8 16 8 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 0 8 8 8 8 8 8 16 16 16 16 16 16 24 8 8 16 8 8 16 8 16 24 8 16 24 8 16 24 8 16 24 16 16 33 16 16 33 16 16 33 16 16 33 16 16 33 16 24 49 24 33 49 26 43 70 28 45 82 24 33 66 26 43 70 28 45 82 41 70 115 75 105 163 78 115 181 107 160 220 137 196 219 100 145 211 70 108 192 59 78 164 39 55 130 20 28 90 10 18 60 8 8 33 0 0 24 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 16 33 16 24 49 24 24 49 8 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 16 0 0 8 8 8 16 8 0 8 0 0 8 0 0 8 0 0 8 0 0 16 0 0 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 0 0 0 16 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 0 8 8 8 16 16 16 16 16 16 16 16 16 24 8 8 16 8 16 24 8 16 24 8 16 24 16 16 24 16 16 33 16 16 33 16 24 41 16 24 41 16 24 49 16 24 41 24 33 57 28 45 82 28 45 82 28 45 82 36 52 95 41 70 115 52 77 133 115 150 210 93 141 201 124 179 225 117 169 217 84 125 202 66 91 183 42 63 138 26 39 109 20 24 78 8 16 49 0 8 28 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 8 8 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 24 41 24 24 49 16 24 33 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 0 8 8 8 16 8 8 16 8 8 16 0 8 8 0 8 16 8 8 16 0 0 8 8 8 8 8 8 16 16 16 16 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 16 8 16 16 8 16 16 16 16 24 16 16 24 8 16 24 8 16 24 8 16 24 16 16 33 16 24 41 16 24 41 16 16 41 16 24 41 16 24 49 16 24 49 24 33 66 36 52 95 28 45 82 36 52 95 41 70 115 66 90 148 78 115 181 84 125 202 115 150 210 136 193 231 90 129 215 71 101 189 49 70 152 38 51 120 20 28 90 10 18 60 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 24 16 16 33 16 24 41 24 24 49 16 16 16 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 0 16 0 0 16 8 8 16 8 8 8 29 29 27 24 24 24 8 8 8 16 16 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 16 8 8 16 8 16 16 16 16 24 16 16 24 16 16 24 8 16 24 8 16 24 16 16 33 16 24 41 16 24 41 16 24 41 16 24 41 16 24 49 16 24 49 24 33 66 36 52 95 40 57 107 41 70 115 52 77 133 78 115 181 98 133 197 100 145 211 137 196 219 115 150 210 83 113 204 59 78 164 42 63 138 26 39 109 18 21 71 8 16 49 8 8 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 0 0 8 8 0 8 8 0 0 8 0 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 24 33 24 24 49 24 24 41 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 16 8 8 16 8 8 16 8 8 16 8 0 8 8 8 16 16 16 24 45 49 45 33 33 33 16 16 16 8 8 16 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 24 16 16 33 16 24 33 16 16 33 16 24 33 16 24 41 16 24 41 16 24 41 16 24 49 24 33 57 16 24 57 24 41 82 36 52 95 36 52 95 40 57 107 52 77 133 77 112 168 152 198 235 124 179 225 124 179 225 98 133 197 71 101 189 49 70 152 35 46 109 24 33 82 10 18 60 8 8 41 0 0 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 24 41 24 24 49 16 24 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 16 0 0 8 0 0 8 8 8 16 8 16 16 8 8 16 8 8 16 16 16 16 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 24 16 24 33 16 24 41 24 33 49 24 24 49 16 24 49 16 24 41 16 24 49 16 24 49 16 24 49 24 33 66 28 45 82 28 45 82 36 52 95 41 70 115 59 85 139 100 145 211 152 198 235 136 193 231 100 145 211 79 113 191 55 90 164 42 63 138 24 41 94 16 24 66 8 16 49 8 8 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 16 8 16 16 16 24 16 16 33 16 24 41 24 24 49 16 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 0 0 8 0 0 16 0 0 16 0 8 8 0 0 8 8 0 16 0 0 8 0 0 8 24 24 24 24 20 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 16 16 24 16 24 33 16 24 41 16 24 41 16 24 41 24 33 49 16 24 49 16 33 49 24 33 57 24 33 66 24 33 74 24 41 82 28 45 82 40 57 107 52 77 133 77 112 168 136 193 231 136 193 231 115 150 210 79 113 191 59 78 164 42 63 138 35 46 109 24 33 82 16 24 57 8 8 33 0 0 16 0 0 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 24 24 49 16 24 41 8 8 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 29 29 27 0 0 8 0 0 8 8 8 8 0 0 8 0 0 8 8 8 8 8 8 8 0 0 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 16 16 24 16 16 33 16 24 33 16 24 33 16 24 41 16 24 49 16 33 49 16 33 49 24 33 57 24 33 57 24 33 66 24 33 74 28 45 82 36 52 95 52 69 123 66 90 148 115 150 210 163 210 237 107 160 220 83 113 204 66 91 183 53 66 136 35 46 109 24 33 82 16 24 66 8 16 41 8 8 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 16 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 24 24 49 16 24 33 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 16 16 16 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 24 8 16 24 16 24 33 24 33 41 24 33 49 24 41 57 33 41 74 37 45 74 24 33 66 24 33 66 24 33 66 24 33 74 28 45 82 36 52 95 52 69 123 66 90 148 98 133 197 163 210 237 136 176 233 83 113 204 66 91 183 53 66 136 35 46 109 20 28 90 16 24 66 8 16 49 8 8 33 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 24 24 49 16 16 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 8 16 24 16 24 33 16 33 41 24 33 49 24 41 57 26 43 70 37 45 74 53 68 103 55 70 111 55 70 111 60 78 115 52 69 123 52 77 133 66 90 148 95 132 180 152 198 235 163 210 237 90 129 215 66 91 183 53 66 136 38 51 120 33 38 93 18 21 71 16 16 49 8 8 33 8 8 24 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 33 16 24 41 24 24 49 8 16 24 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 16 24 33 16 33 41 16 33 49 16 33 49 16 33 49 24 33 57 26 43 70 36 52 95 63 84 121 75 105 163 95 132 180 115 150 210 95 132 180 127 169 215 152 198 235 115 150 210 66 91 183 59 71 145 38 51 120 33 38 93 18 21 71 16 16 49 8 16 41 8 8 24 8 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 24 16 16 33 16 24 41 16 24 41 8 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 8 8 0 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 16 24 33 16 33 41 16 33 49 24 33 49 16 24 49 24 33 66 24 33 66 24 41 82 55 70 111 75 105 163 98 133 197 136 176 233 127 169 215 127 169 215 115 150 210 71 101 189 59 78 164 38 51 120 33 38 93 18 21 71 16 24 57 8 16 41 8 8 24 8 8 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 0 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 16 16 41 24 24 41 8 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 16 16 33 16 24 33 16 33 41 16 33 49 16 24 41 16 24 49 24 33 57 24 33 66 28 45 82 40 57 107 52 77 133 98 133 197 143 181 209 136 176 233 115 150 210 66 91 183 59 71 145 39 55 130 33 38 93 24 33 74 16 24 57 8 16 41 8 8 24 0 8 16 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 24 16 16 33 16 16 41 16 24 41 8 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 16 16 8 16 24 8 16 24 16 24 33 16 24 41 16 33 49 24 33 49 16 24 49 24 33 57 24 33 57 26 43 70 36 52 95 52 69 123 90 117 178 116 155 198 163 210 237 115 150 210 75 93 163 59 71 145 38 51 120 33 38 93 24 33 74 16 24 57 8 16 41 8 8 24 8 8 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 33 16 16 41 16 24 41 16 16 16 0 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 16 8 8 8 8 8 16 8 8 16 8 16 16 8 16 24 8 16 24 16 24 33 16 24 41 16 33 49 16 33 49 24 33 49 24 24 49 24 33 57 33 41 74 53 68 103 66 90 148 95 132 180 152 198 235 115 150 210 75 93 163 53 66 136 40 57 107 33 38 93 24 33 66 16 24 49 16 16 41 8 8 24 8 8 16 0 0 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 24 16 16 33 16 16 41 24 24 41 16 16 24 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 8 8 8 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 8 16 24 8 16 24 16 24 33 16 33 41 16 33 49 24 33 49 24 33 49 24 33 57 26 43 70 43 59 92 60 78 115 75 105 163 116 155 198 98 133 197 59 78 164 53 66 136 35 46 109 33 33 78 24 33 66 16 16 49 16 16 33 8 8 24 8 8 16 0 8 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 16 16 16 24 16 16 24 16 16 33 16 24 41 16 16 33 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 8 8 8 8 8 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 8 16 24 8 16 24 16 24 33 16 33 41 24 33 49 24 33 57 24 33 57 33 41 74 45 57 82 53 68 103 76 100 142 95 132 180 90 117 178 59 71 145 52 69 123 36 52 95 33 33 78 24 24 57 16 16 49 16 16 33 8 8 24 8 8 16 0 8 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 33 16 24 41 16 24 33 8 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 16 16 8 16 16 8 16 16 8 16 16 8 16 24 16 24 33 16 33 49 24 41 57 24 41 57 33 41 74 45 57 82 55 70 111 76 100 142 90 117 178 66 90 148 53 66 136 40 57 107 41 45 87 24 33 74 24 24 57 16 16 41 16 16 33 8 8 24 8 8 16 8 8 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 16 16 33 16 24 41 16 24 41 16 16 24 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 8 16 24 16 16 33 24 33 41 24 33 57 33 41 74 45 57 82 55 70 111 75 105 163 75 105 163 53 66 136 40 57 107 36 52 95 33 33 78 24 33 66 24 24 49 16 16 41 16 16 33 8 8 24 8 8 16 8 8 16 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 16 16 41 16 24 41 16 24 41 16 16 16 8 8 8 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 8 16 24 16 16 33 16 24 41 24 41 57 37 45 74 55 70 111 74 90 135 52 69 123 40 57 107 36 52 95 41 45 87 24 33 66 24 24 57 16 16 41 16 16 33 8 16 24 8 8 16 8 8 16 0 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 0 8 8 0 8 8 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 16 24 16 16 24 16 16 24 16 16 33 16 24 41 24 24 49 16 24 33 8 16 16 8 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 16 16 33 16 24 41 24 33 57 43 59 92 74 90 135 63 84 121 36 52 95 41 45 87 41 45 87 33 41 74 24 33 66 16 24 49 16 16 41 16 16 33 8 16 24 8 8 16 8 8 16 0 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 8 8 8 8 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 16 33 16 16 41 24 24 41 24 24 41 16 24 33 16 16 16 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 16 8 8 16 8 8 16 8 16 16 8 16 16 8 16 24 8 16 24 16 16 33 24 24 41 41 49 70 53 68 103 53 68 103 41 45 87 41 45 87 33 41 74 24 33 66 24 24 57 24 24 49 16 16 41 16 16 33 16 16 24 8 8 24 8 8 16 8 8 16 0 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 8 8 8 8 8 0 0 8 0 0 8 0 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 24 16 16 24 16 16 33 16 24 41 24 24 49 24 24 49 16 24 33 8 16 24 8 8 16 8 8 16 8 8 16 8 8 8 8 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 16 8 8 16 8 8 16 8 16 24 8 16 24 8 16 24 8 16 24 16 24 33 24 41 57 60 63 86 43 59 92 33 41 74 24 33 66 24 33 66 24 33 57 24 33 57 24 24 49 16 24 41 16 16 33 16 16 33 8 16 24 8 8 16 8 8 16 8 8 16 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 0 8 0 0 8 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 16 16 16 16 24 16 16 33 16 16 33 16 24 41 24 24 49 24 24 49 24 24 41 16 16 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 0 8 8 0 8 0 0 8 8 8 8 8 0 8 8 8 8 8 8 16 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 16 24 8 16 24 24 24 41 41 41 57 45 57 82 41 45 87 24 33 74 24 33 66 24 33 57 24 24 49 24 24 49 16 24 41 16 16 41 16 16 33 16 16 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 8 0 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 8 8 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 16 16 16 16 16 16 16 24 16 16 24 16 16 33 16 24 41 24 24 49 24 24 49 24 33 49 24 24 49 16 24 33 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 24 16 16 24 24 24 41 24 33 57 37 45 74 41 45 87 33 33 78 24 24 57 24 24 57 16 24 49 16 24 41 16 24 41 16 24 41 16 16 33 16 16 33 8 16 24 8 16 24 8 8 24 8 8 16 8 8 16 8 8 8 0 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 33 16 24 41 16 24 41 24 24 49 24 24 57 24 33 57 24 33 57 24 24 49 16 24 33 16 24 33 16 16 24 16 16 24 16 16 24 16 16 24 16 16 16 16 16 16 16 16 16 8 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 24 16 16 33 16 24 33 24 33 57 33 41 74 33 41 74 28 45 82 33 33 78 24 24 57 24 24 57 24 24 49 16 24 41 16 16 41 16 16 33 16 16 33 16 16 33 16 16 33 16 16 33 8 8 24 8 8 24 8 8 16 8 8 16 8 8 16 0 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 33 16 16 33 24 24 41 24 24 49 24 24 49 24 24 57 24 33 57 24 33 66 24 33 66 24 33 66 24 33 57 24 33 57 24 33 57 24 33 49 24 33 49 24 33 49 24 33 49 24 33 57 24 33 57 24 33 66 33 41 74 33 41 74 33 41 74 28 45 82 33 33 78 33 33 78 24 33 74 24 24 57 24 24 57 24 24 49 16 24 41 16 16 41 16 16 33 16 16 33 16 16 24 16 16 24 16 16 24 8 16 24 8 16 24 8 8 24 8 8 16 8 8 16 8 8 16 0 8 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 8 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 33 16 16 33 16 24 33 24 24 41 24 24 49 24 24 49 24 24 57 24 24 57 24 24 57 24 33 66 24 33 66 24 33 74 33 33 78 33 33 78 33 33 78 24 33 74 24 33 74 24 33 66 24 33 66 24 24 57 24 24 57 24 24 49 24 24 49 24 24 41 16 24 41 16 16 33 16 16 33 16 16 33 16 16 24 16 16 24 16 16 24 16 16 24 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 16 8 16 16 8 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 24 16 16 33 16 16 33 16 16 33 16 24 33 24 24 41 24 24 41 24 24 41 24 24 41 24 24 49 24 24 41 24 24 41 24 24 41 24 24 41 24 24 41 16 24 41 16 24 33 16 16 33 16 16 33 16 16 33 16 16 33 16 16 24 16 16 24 16 16 24 16 8 24 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 8 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 16 8 16 16 8 16 16 16 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 33 16 16 24 16 16 24 16 16 33 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 16 24 16 8 24 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 8 8 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 24 16 16 24 16 16 16 16 16 16 16 16 16 16 16 24 16 8 16 16 16 16 16 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 16 8 8 8 8 8 16 8 8 16 8 0 8 0 0 8 0 8 8 0 0 8 0 0 8 0 0 8 0 0 8 0 8 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 0 8 0 0 8 8 8 8 8 0 8 8 8 8 0 8 8 0 0 8 0 0 8 8 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 0 0 0 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 8 0 0 8 0 0 8 0 0 8 0 0 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
diff --git a/include/linux/fb.h b/include/linux/fb.h
old mode 100644
new mode 100755
index 043f328..09d9d1f
--- a/include/linux/fb.h
+++ b/include/linux/fb.h
@@ -777,6 +777,7 @@ struct fb_videomode {
 	u32 sync;
 	u32 vmode;
 	u32 flag;
+	u32 vid;		/*optional*/
 };
 
 struct dmt_videomode {
diff --git a/include/linux/linux_logo.h b/include/linux/linux_logo.h
old mode 100644
new mode 100755
index ca5bd91..524cb1b
--- a/include/linux/linux_logo.h
+++ b/include/linux/linux_logo.h
@@ -47,6 +47,7 @@ extern const struct linux_logo logo_superh_vga16;
 extern const struct linux_logo logo_superh_clut224;
 extern const struct linux_logo logo_m32r_clut224;
 extern const struct linux_logo logo_spe_clut224;
+extern const struct linux_logo logo_actions_clut224;
 
 extern const struct linux_logo *fb_find_logo(int depth);
 #ifdef CONFIG_FB_LOGO_EXTRA
diff --git a/include/trace/events/owlfb_trace_events.h b/include/trace/events/owlfb_trace_events.h
new file mode 100755
index 0000000..8b6a2ed
--- /dev/null
+++ b/include/trace/events/owlfb_trace_events.h
@@ -0,0 +1,98 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM owlfb_trace_events
+
+#if !defined(_TRACE_OWLFB_DC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_OWLFB_DC_H
+
+#include <linux/tracepoint.h>
+
+DECLARE_EVENT_CLASS(dc_in,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg),
+
+	    TP_STRUCT__entry(
+		  __field(void * , callbackarg )
+	    ),
+
+	    TP_fast_assign(
+		     __entry->callbackarg = callbackarg;
+	    ),
+	
+	    TP_printk("dc_in callbackarg %p", __entry->callbackarg)
+);
+
+DEFINE_EVENT(dc_in, owlfb_dc_in,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg)
+);
+
+DECLARE_EVENT_CLASS(dc_to_de,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg),
+
+	    TP_STRUCT__entry(
+		  __field(void * , callbackarg )
+	    ),
+
+	    TP_fast_assign(
+		     __entry->callbackarg = callbackarg;
+	    ),
+	
+	    TP_printk("dc_in callbackarg %p", __entry->callbackarg)
+);
+
+DEFINE_EVENT(dc_to_de, owlfb_dc_to_de,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg)
+);
+
+DECLARE_EVENT_CLASS(dc_out,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg),
+
+	    TP_STRUCT__entry(
+		    __field(void * , callbackarg )
+	    ),
+
+	    TP_fast_assign(
+		    __entry->callbackarg = callbackarg;
+	    ),
+		
+		TP_printk("dc_out callbackarg =%p",
+			  __entry->callbackarg)
+);
+
+DEFINE_EVENT(dc_out, owlfb_dc_out,
+	    TP_PROTO(void * callbackarg),
+	    TP_ARGS(callbackarg)
+);
+
+
+
+DECLARE_EVENT_CLASS(vsync,
+	    TP_PROTO(int index, long long timestamp),
+	    TP_ARGS(index,timestamp),
+
+	    TP_STRUCT__entry(
+		    __field(int  , index )
+		    __field(long long , timestamp)
+	    ),
+
+	    TP_fast_assign(
+		    __entry->index = index;
+		    __entry->timestamp = timestamp;
+	    ),
+		
+		TP_printk("vsync index %d timestamp %llu",__entry->index,
+			  __entry->timestamp)
+);
+
+DEFINE_EVENT(vsync, owlfb_vsync,
+	    TP_PROTO(int index, long long timestamp),
+	    TP_ARGS(index,timestamp)
+);
+
+
+#endif /* _TRACE_STAND_HOTPLUG_H */
+
+#include <trace/define_trace.h>
diff --git a/include/video/omapdss.h b/include/video/omapdss.h
old mode 100644
new mode 100755
index f001a35..9b22309
--- a/include/video/omapdss.h
+++ b/include/video/omapdss.h
@@ -160,6 +160,12 @@ enum omap_display_caps {
 	OMAP_DSS_DISPLAY_CAP_TEAR_ELIM		= 1 << 1,
 };
 
+enum omap_dss_update_mode {
+	OMAP_DSS_UPDATE_DISABLED = 0,
+	OMAP_DSS_UPDATE_AUTO,
+	OMAP_DSS_UPDATE_MANUAL,
+};
+
 enum omap_dss_display_state {
 	OMAP_DSS_DISPLAY_DISABLED = 0,
 	OMAP_DSS_DISPLAY_ACTIVE,
@@ -801,6 +807,11 @@ struct omap_dss_driver {
 	void (*disable)(struct omap_dss_device *display);
 	int (*run_test)(struct omap_dss_device *display, int test);
 
+	int (*set_update_mode)(struct omap_dss_device *dssdev,
+			enum omap_dss_update_mode);
+	enum omap_dss_update_mode (*get_update_mode)(
+			struct omap_dss_device *dssdev);
+
 	int (*update)(struct omap_dss_device *dssdev,
 			       u16 x, u16 y, u16 w, u16 h);
 	int (*sync)(struct omap_dss_device *dssdev);
diff --git a/include/video/owldisplay.h b/include/video/owldisplay.h
new file mode 100755
index 0000000..351d143
--- /dev/null
+++ b/include/video/owldisplay.h
@@ -0,0 +1,197 @@
+/*************************************************************************/ /*!
+ at Copyright      Copyright (c) Imagination Technologies Ltd. All Rights Reserved
+ at License        Strictly Confidential.
+*/ /**************************************************************************/
+
+#ifndef __OWL_DISPLAY_H__
+#define __OWL_DISPLAY_H__
+
+#define __bool signed char
+
+typedef struct {__u8  alpha;__u8 red;__u8 green; __u8 blue; }__disp_color_t;
+typedef struct {__s32 x; __s32 y; __u32 width; __u32 height;}__disp_rect_t;
+typedef struct {__u32 width;__u32 height;                   }__disp_rectsz_t;
+typedef struct {__s32 x; __s32 y;                           }__disp_pos_t;
+
+
+#define MAX_CALLBACK_NUM 10
+
+#define OWL_DCQ_DEPTH	 11
+
+typedef void (*callback)(void *, int);
+
+typedef void * callback_arg;
+
+typedef enum
+{
+    DISP_MOD_INTERLEAVED        =0x1,
+    DISP_MOD_NON_MB_PLANAR      =0x0,
+    DISP_MOD_NON_MB_UV_COMBINED =0x2,
+    DISP_MOD_MB_PLANAR          =0x4,
+    DISP_MOD_MB_UV_COMBINED     =0x6,
+}__disp_pixel_mod_t;
+
+typedef enum
+{
+    DISP_SEQ_ARGB   =0x0,
+    DISP_SEQ_BGRA   =0x2,
+    
+    DISP_SEQ_UYVY   =0x3,  
+    DISP_SEQ_YUYV   =0x4,
+    DISP_SEQ_VYUY   =0x5,
+    DISP_SEQ_YVYU   =0x6,
+    
+    DISP_SEQ_AYUV   =0x7,  
+    DISP_SEQ_VUYA   =0x8,
+    
+    DISP_SEQ_UVUV   =0x9,  
+    DISP_SEQ_VUVU   =0xa,
+    
+    DISP_SEQ_P10    = 0xd,
+    DISP_SEQ_P01    = 0xe,
+    
+    DISP_SEQ_P3210  = 0xf,
+    DISP_SEQ_P0123  = 0x10,
+    
+    DISP_SEQ_P76543210  = 0x11,
+    DISP_SEQ_P67452301  = 0x12,
+    DISP_SEQ_P10325476  = 0x13,
+    DISP_SEQ_P01234567  = 0x14,
+    
+    DISP_SEQ_2BPP_BIG_BIG       = 0x15,
+    DISP_SEQ_2BPP_BIG_LITTER    = 0x16,
+    DISP_SEQ_2BPP_LITTER_BIG    = 0x17,
+    DISP_SEQ_2BPP_LITTER_LITTER = 0x18,
+    
+    DISP_SEQ_1BPP_BIG_BIG       = 0x19,
+    DISP_SEQ_1BPP_BIG_LITTER    = 0x1a,
+    DISP_SEQ_1BPP_LITTER_BIG    = 0x1b,
+    DISP_SEQ_1BPP_LITTER_LITTER = 0x1c,
+}__disp_pixel_seq_t;
+
+typedef enum
+{
+    DISP_3D_SRC_MODE_TB = 0x0,
+    DISP_3D_SRC_MODE_FP = 0x1,
+    DISP_3D_SRC_MODE_SSF = 0x2,
+    DISP_3D_SRC_MODE_SSH = 0x3,
+    DISP_3D_SRC_MODE_LI = 0x4,
+}__disp_3d_src_mode_t;
+
+typedef enum
+{
+    DISP_3D_OUT_MODE_CI_1 = 0x5,
+    DISP_3D_OUT_MODE_CI_2 = 0x6,
+    DISP_3D_OUT_MODE_CI_3 = 0x7,
+    DISP_3D_OUT_MODE_CI_4 = 0x8,
+    DISP_3D_OUT_MODE_LIRGB = 0x9,
+
+    DISP_3D_OUT_MODE_TB = 0x0,
+    DISP_3D_OUT_MODE_FP = 0x1,
+    DISP_3D_OUT_MODE_SSF = 0x2,
+    DISP_3D_OUT_MODE_SSH = 0x3,
+    DISP_3D_OUT_MODE_LI = 0x4,
+    DISP_3D_OUT_MODE_FA = 0xa,
+}__disp_3d_out_mode_t;
+
+typedef enum
+{
+    DISP_BT601  = 0,
+    DISP_BT709  = 1,
+    DISP_YCC    = 2,
+    DISP_VXYCC  = 3,
+}__disp_cs_mode_t;
+
+typedef enum
+{
+	OWL_TV_MOD_720P_50HZ           = 1,
+    OWL_TV_MOD_720P_60HZ           = 2,
+    OWL_TV_MOD_1080P_50HZ          = 3,
+    OWL_TV_MOD_1080P_60HZ          = 4, 
+    OWL_TV_MOD_576P                = 5,
+    OWL_TV_MOD_480P                = 6,
+    OWL_TV_MOD_DVI 				   = 7,
+    OWL_TV_MOD_PAL                 = 8,
+    OWL_TV_MOD_NTSC                = 9,
+    OWL_TV_MOD_4K_30HZ             = 10,
+    OWL_TV_MODE_NUM               =  10,    
+}__owl_tv_mode_t;
+
+typedef enum
+{
+    DISP_LAYER_WORK_MODE_NORMAL     = 0,
+    DISP_LAYER_WORK_MODE_PALETTE    = 1,
+    DISP_LAYER_WORK_MODE_INTER_BUF  = 2,
+    DISP_LAYER_WORK_MODE_GAMMA      = 3,
+    DISP_LAYER_WORK_MODE_SCALER     = 4,
+}__disp_layer_work_mode_t;
+
+typedef struct
+{
+    __u32                   addr[3];
+    __u64                   buffer_id;
+    __disp_rectsz_t         size;
+    __u32                   format;
+    __disp_pixel_seq_t      seq;
+    __disp_pixel_mod_t      mode;
+    __bool                  br_swap;
+    __disp_cs_mode_t        cs_mode;
+    __bool                  b_trd_src;
+    __disp_3d_src_mode_t    trd_mode;
+    __u32                   trd_right_addr[3];
+    __bool                  pre_multiply;
+}__disp_fb_t;
+
+typedef struct
+{
+    __disp_layer_work_mode_t    mode;
+    __bool                      b_from_screen;
+    __u8                        pipe;
+    __u8                        prio;
+    __bool                      alpha_en;
+    __u16                       alpha_val;
+    __bool                      ck_enable;
+    __disp_rect_t               src_win;
+    __disp_rect_t               scn_win;
+    __disp_fb_t                 fb;
+    __bool                      b_trd_out;
+    __disp_3d_out_mode_t        out_trd_mode;
+    __u8                        rotate;
+}__disp_layer_info_t;
+
+typedef struct
+{   
+    int                 post2_layers;
+    __disp_layer_info_t layer_info[8];
+    __disp_rect_t       fb_scn_win;
+
+    int                 primary_display_layer_num;
+    int                 show_black[2];
+    int                 time_stamp;
+}setup_dispc_data_t;
+
+struct owl_disp_info
+{
+	spinlock_t info_lock;
+	int state;
+	int index;
+	setup_dispc_data_t psDispcData;
+	callback mCallBack;
+	callback_arg mCallBackArg;
+	struct list_head list;	
+};
+struct owlfb_dc
+{	
+	struct device * dev;	   
+    struct mutex dc_lock;
+    struct work_struct dc_work;
+    struct workqueue_struct * dc_workqueue;
+    struct owl_disp_info dc_queue[OWL_DCQ_DEPTH];
+    struct owl_overlay_manager * primary_manager;
+    struct owl_overlay_manager * external_manager;
+    struct list_head q_list;
+    bool working;  
+      	
+};
+
+#endif
diff --git a/include/video/owldss.h b/include/video/owldss.h
new file mode 100755
index 0000000..7afeaac
--- /dev/null
+++ b/include/video/owldss.h
@@ -0,0 +1,597 @@
+/*
+ * Copyright (C) 2014 Actions Corporation
+ * Author: Hui Wang  <wanghui at actions-semi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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/>.
+ */
+
+#ifndef __OWL_OWLDSS_H
+#define __OWL_OWLDSS_H
+
+#include <linux/list.h>
+#include <linux/kobject.h>
+#include <linux/device.h>
+
+/* act TRM gives bitfields as start:end, where start is the higher bit number. For example 7:0 */
+#define REG_MASK(start, end)	(((1 << ((start) - (end) + 1)) - 1) << (end))
+#define REG_VAL(val, start, end) (((val) << (end)) & REG_MASK(start, end))
+#define REG_GET_VAL(val, start, end) (((val) & REG_MASK(start, end)) >> (end))
+#define REG_SET_VAL(orig, val, start, end) (((orig) & ~REG_MASK(start, end)) | REG_VAL(val, start, end))
+
+
+struct owl_dss_device;
+struct owl_overlay_manager;
+
+enum owl_display_type {
+	OWL_DISPLAY_TYPE_NONE		= 0,
+	OWL_DISPLAY_TYPE_LCD		= 1 << 0,
+	OWL_DISPLAY_TYPE_DSI		= 1 << 1,
+	OWL_DISPLAY_TYPE_EDP		= 1 << 2,
+	OWL_DISPLAY_TYPE_CVBS		= 1 << 3,
+	OWL_DISPLAY_TYPE_YPBPR		= 1 << 4,
+	OWL_DISPLAY_TYPE_HDMI		= 1 << 5,
+};
+
+enum owl_plane_effect_parameter {
+	OWL_DSS_VIDEO_LIGHTNESS	 = 0,
+	OWL_DSS_VIDEO_SATURATION = 1,
+	OWL_DSS_VIDEO_CONSTRAST	 = 2,
+	OWL_DSS_DEF_EFFECT       = 3,
+};
+enum owl_plane {
+	OWL_DSS_VIDEO1	= 0,
+	OWL_DSS_VIDEO2	= 1,
+	OWL_DSS_VIDEO3	= 2,
+	OWL_DSS_VIDEO4	= 3,
+};
+
+enum owl_de_path_id {	
+	OWL_DSS_PATH1_ID	= 0,
+	OWL_DSS_PATH2_ID = 1,	
+};
+
+enum owl_boot_mode {	
+	OWL_DSS_BOOT_NORMAL   = 0,
+	OWL_DSS_BOOT_CHARGER	= 1,
+	OWL_DSS_BOOT_RECOVERY   = 2,
+};
+
+enum owl_color_mode {
+	OWL_DSS_COLOR_RGB16	    = 0,  /* RGB16  */
+	OWL_DSS_COLOR_BGR16	    = 1,  /* RGB16 */
+	OWL_DSS_COLOR_ARGB32    = 4,  /* ARGB32*/
+	OWL_DSS_COLOR_ABGR32    = 5,  /* ARGB32 */
+	OWL_DSS_COLOR_RGBA32    = 6,  /* RGBA32 */
+	OWL_DSS_COLOR_BGRA32	= 7,  /* RGBA32 */
+	OWL_DSS_COLOR_NV21	    = 8,  /* YUV 4:2:0 sp */	
+	OWL_DSS_COLOR_NU21	    = 9,  /* YVU 4:2:0 sp */
+	OWL_DSS_COLOR_YU12	    = 10,  /* YUV 4:2:0 */
+	OWL_DSS_COLOR_ARGB16	= 12,  /* ARGB16 */
+	OWL_DSS_COLOR_ABGR16	= 13, /* ABGR16 */
+	OWL_DSS_COLOR_RGBA16	= 14, /* RGBA16 */
+	OWL_DSS_COLOR_BGRA16	= 15, /* BGRA16 */	
+	OWL_DSS_COLOR_RGB24U	= 16,  /* RGB24, 32-bit container */
+	OWL_DSS_COLOR_RGB24P	= 17, /* RGB24, 24-bit container */
+	OWL_DSS_COLOR_RGBX32	= 18, /* RGBx32 */
+	OWL_DSS_COLOR_NV12	= 19,  /* YVU 4:2:0  */
+	OWL_DSS_COLOR_XBGR32	= 20, /* XBGR32 */
+	OWL_DSS_COLOR_XRGB32 = 21,
+};
+
+enum owl_dither_mode {
+	DITHER_24_TO_16 = 0,
+	DITHER_24_TO_18,
+};
+
+enum owl_lcd_display_type {
+	OWL_DSS_LCD_DISPLAY_RGB,
+	OWL_DSS_LCD_DISPLAY_LVDS,
+};
+
+enum owl_dss_trans_key_type {
+	OWL_DSS_COLOR_KEY_GFX_DST = 0,
+	OWL_DSS_COLOR_KEY_VID_SRC = 1,
+};
+
+
+enum owl_display_caps {
+	OWL_DSS_DISPLAY_CAP_MANUAL_UPDATE	= 1 << 0,
+	OWL_DSS_DISPLAY_CAP_TEAR_ELIM		= 1 << 1,
+};
+
+enum owl_dss_display_state {
+	OWL_DSS_DISPLAY_DISABLED = 0,
+	OWL_DSS_DISPLAY_ACTIVE,
+	OWL_DSS_DISPLAY_SUSPENDED,
+};
+
+/* XXX perhaps this should be removed */
+enum owl_dss_managers_id {
+	OWL_DSS_OVL_MGR_PRIMARY,
+	OWL_DSS_OVL_MGR_EXTERNAL,
+};
+
+/* clockwise rotation angle */
+enum owl_dss_rotation_angle {
+	OWL_DSS_ROT_0   = 0,
+	OWL_DSS_ROT_90  = 1,
+	OWL_DSS_ROT_180 = 2,
+	OWL_DSS_ROT_270 = 3,
+};
+
+enum owl_overlay_caps {
+	OWL_DSS_OVL_CAP_SCALE = 1 << 0,
+	OWL_DSS_OVL_CAP_GLOBAL_ALPHA = 1 << 1,
+	OWL_DSS_OVL_CAP_PRE_MULT_ALPHA = 1 << 2,
+	OWL_DSS_OVL_CAP_ZORDER = 1 << 3,
+};
+
+enum owl_overlay_manager_caps {
+	OWL_DSS_DUMMY_VALUE, /* add a dummy value to prevent compiler error */
+};
+
+enum owl_dss_clk_source {
+	OWL_DSS_CLK_SRC_DEV_PLL = 0,		
+						
+	OWL_DSS_CLK_SRC_DISPLAY_PLL,	
+						
+	OWL_DSS_CLK_SRC_NAND_PLL,	
+};
+
+
+
+enum owl_dss_signal_level {
+	OWLDSS_SIG_ACTIVE_HIGH	= 0,
+	OWLDSS_SIG_ACTIVE_LOW	= 1,
+};
+
+struct owl_video_timings {
+	/* Unit: pixels */
+	u16 x_res;
+	/* Unit: pixels */
+	u16 y_res;
+	/* Unit: KHz */
+	u32 pixel_clock;
+	/* Unit: pixel clocks */
+	u16 hsw;	/* Horizontal synchronization pulse width */
+	/* Unit: pixel clocks */
+	u16 hfp;	/* Horizontal front porch */
+	/* Unit: pixel clocks */
+	u16 hbp;	/* Horizontal back porch */
+	/* Unit: line clocks */
+	u16 vsw;	/* Vertical synchronization pulse width */
+	/* Unit: line clocks */
+	u16 vfp;	/* Vertical front porch */
+	/* Unit: line clocks */
+	u16 vbp;	/* Vertical back porch */
+	
+	/* Vsync logic level */
+	enum owl_dss_signal_level vsync_level;
+	/* Hsync logic level */
+	enum owl_dss_signal_level hsync_level;
+	/* Interlaced or Progressive timings */
+	bool interlace;
+	/*Vsync start line */
+	int vstart;
+	/*video data repetetion*/
+	bool repeat;	
+
+	u16 data_width;
+};
+
+struct owl_gamma_info {
+	u8 value[256];
+	bool enabled;
+};
+
+struct owl_ovl_priv_info {
+	int 	lightness;
+	int 	saturation;
+	int 	contrast;
+};
+
+
+struct owl_overlay_info {
+	unsigned long paddr;
+	unsigned long vaddr;	/* for MMU */
+	u64 buffer_id;			/* for ION MMU */
+	bool enable_mmu;
+	
+	unsigned short screen_width;	
+	enum owl_color_mode color_mode;		
+	unsigned short img_width;
+	unsigned short img_height;
+		
+	unsigned short xoff;	
+	unsigned short yoff;
+	unsigned short width;
+	unsigned short height;
+	
+	unsigned char rotation;
+	
+	unsigned short pos_x;
+	unsigned short pos_y;
+	unsigned short out_width;	/* if 0, out_width == width */
+	unsigned short out_height;	/* if 0, out_height == height */
+	
+	unsigned char lightness;
+	unsigned char saturation;
+	unsigned char contrast;
+	bool global_alpha_en;
+	unsigned char global_alpha;
+	
+	bool pre_mult_alpha_en;
+	
+	unsigned char zorder;
+};
+
+struct ovl_priv_data {
+
+	bool user_info_dirty;
+	struct owl_overlay_info user_info;
+
+	bool info_dirty;
+	struct owl_overlay_info info;
+
+	bool shadow_info_dirty;
+
+	bool extra_info_dirty;
+	bool shadow_extra_info_dirty;
+
+	bool enabled;
+	enum owl_dss_managers_id channel;
+	u32 fifo_low, fifo_high;
+
+	/*
+	 * True if overlay is to be enabled. Used to check and calculate configs
+	 * for the overlay before it is enabled in the HW.
+	 */
+	bool enabling;
+};
+
+struct owl_overlay {
+	struct kobject kobj;
+	struct list_head list;
+
+	/* static fields */
+	const char *name;
+	enum owl_plane id;
+	enum owl_color_mode supported_modes;
+	enum owl_overlay_caps caps;
+	
+	struct ovl_priv_data priv_data;
+
+	/* dynamic fields */	
+	struct owl_overlay_manager *manager;
+
+	/*
+	 * The following functions do not block:
+	 *
+	 * is_enabled
+	 * set_overlay_info
+	 * get_overlay_info
+	 *
+	 * The rest of the functions may block and cannot be called from
+	 * interrupt context
+	 */
+
+	int (*enable)(struct owl_overlay *ovl);
+	int (*disable)(struct owl_overlay *ovl);
+	bool (*is_enabled)(struct owl_overlay *ovl);
+
+	int (*set_manager)(struct owl_overlay *ovl,
+		struct owl_overlay_manager *mgr);
+	int (*unset_manager)(struct owl_overlay *ovl);
+
+	int (*set_overlay_info)(struct owl_overlay *ovl,
+			struct owl_overlay_info *info);
+	void (*get_overlay_info)(struct owl_overlay *ovl,
+			struct owl_overlay_info *info);
+	int (*apply_overlay_info)(struct owl_overlay *ovl);
+	
+	int (*write_hw_regs)(struct owl_overlay *ovl);
+	
+	int (*enable_overlay_mmu)(struct owl_overlay *ovl,bool enable);
+
+	int (*wait_for_go)(struct owl_overlay *ovl);
+};
+
+static inline struct ovl_priv_data *get_ovl_priv(struct owl_overlay *ovl)
+{
+	return &ovl->priv_data;
+}
+
+struct owl_cursor_info {
+	bool enable;
+	unsigned short pos_x;
+	unsigned short pos_y;
+	void * paddr;
+	unsigned short stride;
+
+};
+
+struct owl_overlay_manager_info {
+	u16 out_width;
+	u16 out_height;		
+	u32 default_color;
+	
+	enum owl_dss_trans_key_type trans_key_type;
+	u32 trans_key;
+	bool trans_enabled;
+	
+	bool partial_alpha_enabled;
+
+};
+
+#define MMU_STATE_NO_ENABLE              0
+#define MMU_STATE_PRE_ENABLE             1
+#define MMU_STATE_ENABLED                2
+struct mgr_priv_data {
+
+	bool user_info_dirty;
+	struct owl_overlay_manager_info user_info;
+
+	bool info_dirty;
+	struct owl_overlay_manager_info info;
+	
+	bool user_cursor_dirty;
+	struct owl_cursor_info user_cursor;
+	
+	bool cursor_dirty;
+	struct owl_cursor_info cursor;
+
+	bool shadow_info_dirty;
+	
+	/*this mark we need switch to mmu , in uboot mmu is disable 
+	,before first frame we check if need switch to mmu
+	,after first frame we make sure mmu is enabled
+    */
+	int mmu_state;
+
+	/* If true, GO bit is up and shadow registers cannot be written.
+	 * Never true for manual update displays */
+	bool busy;	
+    
+	/* If true, dispc output is enabled */
+	bool updating;
+
+	/* If true, a display is enabled using this manager */
+	bool enabled;
+	
+	/* this for hw vsync */
+	struct device *dev; // this for vsync event 
+	bool hw_sync_enable;
+	ktime_t timestamp;				
+	atomic_t vsync_avail;
+	struct work_struct  vsync_work;	
+	wait_queue_head_t wait_vsync;	
+};
+
+struct owl_overlay_manager {
+	struct kobject kobj;
+
+	/* static fields */
+	const char *name;
+	
+	enum owl_dss_managers_id id;
+	
+	/* this depath config */
+		
+	enum owl_de_path_id de_path_id;
+	
+	enum owl_overlay_manager_caps caps;
+	struct list_head overlays;
+	enum owl_display_type supported_displays;
+	
+	struct mgr_priv_data priv_data;
+	
+	struct mutex apply_lock;
+	/* dynamic fields */
+	struct owl_dss_device * device;
+	bool mirror_context;
+	struct fb_info * link_fbi;
+	/* 
+         * gamma setting is not controlled by FCR bit,
+	 * so we should wait for vsync to update gamma info
+	 */
+	struct owl_gamma_info gamma_info;
+	bool gamma_info_dirty;
+	struct mutex gamma_lock;
+
+	/*
+	 * The following functions do not block:
+	 *
+	 * set_manager_info
+	 * get_manager_info
+	 * apply
+	 *
+	 * The rest of the functions may block and cannot be called from
+	 * interrupt context
+	 */
+
+	int (*set_device)(struct owl_overlay_manager *mgr,	struct owl_dss_device *dssdev);
+	int (*unset_device)(struct owl_overlay_manager *mgr);
+
+	int (*set_manager_info)(struct owl_overlay_manager *mgr, struct owl_overlay_manager_info *info);
+	void (*get_manager_info)(struct owl_overlay_manager *mgr, struct owl_overlay_manager_info *info);
+	int (*apply_manager_info)(struct owl_overlay_manager *mgr);
+	
+	int (*set_cursor_info)(struct owl_overlay_manager *mgr, struct owl_cursor_info *info);
+	void (*get_cursor_info)(struct owl_overlay_manager *mgr, struct owl_cursor_info *info);
+
+	int (*apply)(struct owl_overlay_manager *mgr);
+	
+	int (*set_mmu_state)(struct owl_overlay_manager *mgr, int mmu_state);
+		
+	int (*enable_hw_vsync)(struct owl_overlay_manager *mgr, bool enabled, struct device *dev);
+	
+	int (*wait_for_go)(struct owl_overlay_manager *mgr);
+	
+	int (*wait_for_vsync)(struct owl_overlay_manager *mgr,long long i64TimeStamp);
+};
+struct owl_dss_device {
+	struct device dev;
+
+	enum owl_display_type type;
+
+	enum owl_dss_managers_id channel;
+	
+	struct owl_video_timings timings;
+	
+	u8 data_lines;
+
+	const char *name;
+
+	/* used to match device to driver */
+	const char *driver_name;
+
+	void *data;
+
+	struct owl_dss_driver *driver;
+
+	/* helper variable for driver suspend/resume */
+	bool activate_after_resume;
+	
+	enum owl_display_caps caps;
+
+	struct owl_overlay_manager *manager;
+
+	enum owl_dss_display_state state;
+
+	/* platform specific  */
+	int (*platform_enable)(struct owl_dss_device *dssdev);
+	void (*platform_disable)(struct owl_dss_device *dssdev);
+	int (*set_backlight)(struct owl_dss_device *dssdev, int level);
+	int (*get_backlight)(struct owl_dss_device *dssdev);
+};
+static inline struct mgr_priv_data *get_mgr_priv(struct owl_overlay_manager *mgr)
+{
+	return &mgr->priv_data;
+}
+struct owl_dss_driver {
+	struct device_driver driver;
+
+	int (*probe)(struct owl_dss_device *);
+	void (*remove)(struct owl_dss_device *);
+
+	int (*enable)(struct owl_dss_device *display);
+	void (*disable)(struct owl_dss_device *display);
+	
+	int (*suspend)(struct owl_dss_device *display);
+	int (*resume)(struct owl_dss_device *display);
+	int (*run_test)(struct owl_dss_device *display, int test);
+
+	void (*get_resolution)(struct owl_dss_device *dssdev,	u16 *xres, u16 *yres);
+	void (*get_dimensions)(struct owl_dss_device *dssdev,	u32 *width, u32 *height);
+	int (*get_recommended_bpp)(struct owl_dss_device *dssdev);
+
+	int (*check_timings)(struct owl_dss_device *dssdev, struct owl_video_timings *timings);
+	void (*set_timings)(struct owl_dss_device *dssdev,	struct owl_video_timings *timings);
+	void (*get_timings)(struct owl_dss_device *dssdev,	struct owl_video_timings *timings);
+	void (*get_over_scan)(struct owl_dss_device *dssdev, u16 * scan_width,  u16 * scan_height);
+	void (*set_over_scan)(struct owl_dss_device *dssdev, u16 scan_width,  u16 scan_height);
+	int (*get_effect_parameter)(struct owl_dss_device *dssdev,	enum owl_plane_effect_parameter parameter_id);
+	void (*set_effect_parameter)(struct owl_dss_device *dssdev,	enum owl_plane_effect_parameter parameter_id,int value);
+	void (*set_vid)(struct owl_dss_device *dssdev, int vid);
+	void (*get_vid)(struct owl_dss_device *dssdev, int *vid);
+	void (*enable_hpd)(struct owl_dss_device *dssdev, bool enable);
+	void (*enable_hdcp)(struct owl_dss_device *dssdev, bool enable);
+	int (*get_vid_cap)(struct owl_dss_device *dssdev, int *vid_cap);
+	int (*get_cable_status)(struct owl_dss_device *dssdev);
+	
+	int (*read_edid)(struct owl_dss_device *dssdev, u8 *buf, int len);	
+	int (*dump)(struct owl_dss_device *dssdev);
+	
+	int (*hot_plug_nodify)(struct owl_dss_device *dssdev, int state);
+	
+};
+
+int owl_dss_register_driver(struct owl_dss_driver *);
+void owl_dss_unregister_driver(struct owl_dss_driver *);
+
+void owl_dss_get_device(struct owl_dss_device *dssdev);
+void owl_dss_put_device(struct owl_dss_device *dssdev);
+#define for_each_dss_dev(d) while ((d = owl_dss_get_next_device(d)) != NULL)
+struct owl_dss_device *owl_dss_get_next_device(struct owl_dss_device *from);
+struct owl_dss_device *owl_dss_find_device(void *data, int (*match)(struct owl_dss_device *dssdev, void *data));
+struct owl_dss_device *owl_dss_find_device_by_type(enum owl_display_type type);
+
+int owl_dss_start_device(struct owl_dss_device *dssdev);
+void owl_dss_stop_device(struct owl_dss_device *dssdev);
+int owl_dss_get_num_overlay_managers(void);
+struct owl_overlay_manager *owl_dss_get_overlay_manager(int num);
+bool owl_dss_is_devices_suspended(void);
+
+int owl_dss_get_num_overlays(void);
+struct owl_overlay *owl_dss_get_overlay(int num);
+
+void owl_default_get_resolution(struct owl_dss_device *dssdev, 	u16 *xres, u16 *yres);
+int owl_default_get_recommended_bpp(struct owl_dss_device *dssdev);
+
+#define to_dss_driver(x) container_of((x), struct owl_dss_driver, driver)
+#define to_dss_device(x) container_of((x), struct owl_dss_device, dev)
+
+enum owl_display_type get_current_display_type(void);
+
+int owl_lcdc_display_enable(struct owl_dss_device *dssdev);
+void owl_lcdc_display_disable(struct owl_dss_device *dssdev);
+void owl_lcdc_set_timings(struct owl_dss_device *dssdev,struct owl_video_timings *timings);
+int owl_lcdc_check_timings(struct owl_dss_device *dssdev,	struct owl_video_timings *timings);
+int owl_lcdc_init_platform(void);
+int owl_lcdc_uninit_platform(void);
+void owl_lcdc_display_dump(void);
+void owl_lcdc_set_effect_parameter(struct owl_dss_device *dssdev,enum owl_plane_effect_parameter parameter_id ,int value);
+int owl_lcdc_get_effect_parameter(struct owl_dss_device *dssdev, enum owl_plane_effect_parameter parameter_id);
+void owl_lcdc_select_video_timings(struct owl_dss_device *dssdev, u32 num,
+                                   struct owl_video_timings *timings);
+
+int owl_edp_display_enable(struct owl_dss_device *dssdev);
+void owl_edp_display_disable(struct owl_dss_device *dssdev);
+int owl_edp_init_platform(void);
+int owl_edp_uninit_platform(void);
+void owl_edp_display_dump(void);
+
+
+int owl_dsi_display_enable(struct owl_dss_device *dssdev);
+void owl_dsi_display_disable(struct owl_dss_device *dssdev);
+int owl_dsi_init_platform(void);
+int owl_dsi_uninit_platform(void);
+void owl_dsi_display_dump(void);
+bool dss_check_channel_boot_inited(enum owl_de_path_id channel);
+
+int owl_cvbs_init_platform(void);
+int owldss_cvbs_display_enable(struct owl_dss_device *dssdev);
+//void cvbs_panel_enable(struct owl_dss_device *dssdev);
+
+
+void owl_de_get_histogram_info(u32 * hist, u32 * totaly);
+int owl_de_get_boot_mode(void);
+bool owl_de_is_atm7059tc(void);
+
+void dss_mgr_set_gamma_table(enum owl_de_path_id channel,
+				struct owl_gamma_info *gamma_info);
+void dss_mgr_get_gamma_table(enum owl_de_path_id channel,
+				struct owl_gamma_info *gamma_info);
+void trace_buffer_release(void * args);
+
+void trace_buffer_put_to_queue(void * args);
+
+void trace_buffer_put_to_dehw(void * args);
+
+void trace_vsync_point(int index, long long timestamp);
+
+#define DEF_LIGHTNESS   0x80
+#define DEF_SATURATION  0x07
+#define DEF_CONTRAST    0x07
+
+#endif
diff --git a/include/video/owlfb.h b/include/video/owlfb.h
new file mode 100755
index 0000000..08f3e28
--- /dev/null
+++ b/include/video/owlfb.h
@@ -0,0 +1,332 @@
+/*
+ * File: include/linux/owlfb.h
+ *
+ * Framebuffer driver for ACTS OWL boards
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Imre Deak <imre.deak at nokia.com>
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+#ifndef __LINUX_OWLFB_H__
+#define __LINUX_OWLFB_H__
+
+#include <linux/fb.h>
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#include "owldss.h"
+
+/* IOCTL commands. */
+
+#define OWL_IOW(num, dtype)	_IOW('O', num, dtype)
+#define OWL_IOR(num, dtype)	_IOR('O', num, dtype)
+#define OWL_IOWR(num, dtype)	_IOWR('O', num, dtype)
+#define OWL_IO(num)		_IO('O', num)
+
+#define OWLFB_MIRROR		          OWL_IOW(31, int)
+#define OWLFB_SYNC_GFX		          OWL_IO(37)
+#define OWLFB_VSYNC		              OWL_IO(38)
+
+#define OWLFB_OVERLAY_REQUEST	      OWL_IOR(41, struct owlfb_overlay_args)
+#define OWLFB_OVERLAY_RELEASE		  OWL_IOR(42, struct owlfb_overlay_args)
+#define OWLFB_OVERLAY_ENABLE	      OWL_IOR(43, struct owlfb_overlay_args)
+#define OWLFB_OVERLAY_DISABLE		  OWL_IOR(45, struct owlfb_overlay_args)
+#define OWLFB_OVERLAY_GETINFO	      OWL_IOW(46, struct owlfb_overlay_args)
+#define OWLFB_OVERLAY_SETINFO         OWL_IOW(47, struct owlfb_overlay_args)
+
+#define OWLFB_SET_COLOR_KEY	          OWL_IOW(50, struct owlfb_color_key)
+#define OWLFB_GET_COLOR_KEY	          OWL_IOW(51, struct owlfb_color_key)
+#define OWLFB_SETUP_PLANE	          OWL_IOW(52, struct owlfb_plane_info)
+#define OWLFB_QUERY_PLANE	          OWL_IOW(53, struct owlfb_plane_info)
+#define OWLFB_UPDATE_WINDOW	          OWL_IOW(54, struct owlfb_update_window)
+#define OWLFB_SETUP_MEM	              OWL_IOW(55, struct owlfb_mem_info)
+#define OWLFB_QUERY_MEM	              OWL_IOW(56, struct owlfb_mem_info)
+#define OWLFB_WAITFORVSYNC	          OWL_IOW(57,long long)
+#define OWLFB_MEMORY_READ	          OWL_IOR(58, struct owlfb_memory_read)
+#define OWLFB_GET_OVERLAY_COLORMODE   OWL_IOR(59, struct owlfb_ovl_colormode)
+#define OWLFB_WAITFORGO	              OWL_IO(60)
+#define OWLFB_SET_PAN_DISPLAY	      OWL_IOW(61, struct owlfb_disp_content_info)
+#define OWLFB_SET_TEARSYNC	          OWL_IOW(62, struct owlfb_tearsync_info)
+
+#define OWLFB_GET_MAIN_DISPLAY_RES	  OWL_IOR(63, struct owlfb_display_info)
+#define OWLFB_GET_HISTOGRAM_INFO	  OWL_IOR(64, struct owlfb_disp_histogram_info)
+#define OWLFB_SET_GAMMA_INFO	      OWL_IOW(65, struct owl_gamma_info)
+#define OWLFB_GET_GAMMA_INFO	      OWL_IOR(66, struct owl_gamma_info)
+#define OWLFB_VSYNC_EVENT_EN	      OWL_IOW(67, struct owlfb_sync_info)
+#define OWLFB_HDMI_SUPPORT_MODE       OWL_IOR(68, struct owlfb_hdmi_vid_info)
+#define OWLFB_HDMI_SET_MODE           OWL_IOW(69, struct owlfb_hdmi_vid_info)
+#define OWLFB_HDMI_ON                 OWL_IO(70)
+#define OWLFB_HDMI_OFF                OWL_IO(71)
+#define OWLFB_HDMI_DISABLE            OWL_IOW(72,int)
+#define OWLFB_LAYER_REQUEST           OWL_IOW(73,int)
+#define OWLFB_GET_DISPLAY_INFO		  OWL_IOW(74,struct owlfb_disp_device)
+#define OWLFB_SET_DISPLAY_INFO		  OWL_IOW(75,struct owlfb_disp_device)
+
+#define OWLFB_HDMI_GET_CABLE_STATUS	  OWL_IOR(76, int)
+#define OWLFB_HDMI_GET_VID			  OWL_IOR(77, int)
+#define OWLFB_CVBS_GET_VID			  OWL_IOR(78, int)
+#define OWLFB_CVBS_SET_VID			  OWL_IOR(79, int)
+#define OWLFB_CVBS_ENABLE			    OWL_IOR(80, int)
+#define OWLFB_CVBS_ON                 OWL_IO(81)
+#define OWLFB_CVBS_OFF                OWL_IO(82)
+
+#define OWLFB_CAPS_GENERIC_MASK	0x00000fff
+#define OWLFB_CAPS_LCDC_MASK		0x00fff000
+#define OWLFB_CAPS_PANEL_MASK		0xff000000
+
+#define OWLFB_CAPS_MANUAL_UPDATE	0x00001000
+#define OWLFB_CAPS_TEARSYNC		0x00002000
+#define OWLFB_CAPS_PLANE_RELOCATE_MEM	0x00004000
+#define OWLFB_CAPS_PLANE_SCALE		0x00008000
+#define OWLFB_CAPS_WINDOW_PIXEL_DOUBLE	0x00010000
+#define OWLFB_CAPS_WINDOW_SCALE	0x00020000
+#define OWLFB_CAPS_WINDOW_OVERLAY	0x00040000
+#define OWLFB_CAPS_WINDOW_ROTATE	0x00080000
+#define OWLFB_CAPS_SET_BACKLIGHT	0x01000000
+
+/* Values from DSP must map to lower 16-bits */
+#define OWLFB_FORMAT_MASK		0x00ff
+#define OWLFB_FORMAT_FLAG_DOUBLE	0x0100
+#define OWLFB_FORMAT_FLAG_TEARSYNC	0x0200
+#define OWLFB_FORMAT_FLAG_FORCE_VSYNC	0x0400
+#define OWLFB_FORMAT_FLAG_ENABLE_OVERLAY	0x0800
+#define OWLFB_FORMAT_FLAG_DISABLE_OVERLAY	0x1000
+
+#define OWLFB_MEMTYPE_SDRAM		0
+#define OWLFB_MEMTYPE_SRAM		1
+#define OWLFB_MEMTYPE_MAX		1
+
+#define OWLFB_MEM_IDX_ENABLED	0x80
+#define OWLFB_MEM_IDX_MASK	0x7f
+
+enum owlfb_color_format {
+	OWLFB_COLOR_RGB565 = 0,
+	OWLFB_COLOR_YUV420,
+	OWLFB_COLOR_YVU420,
+	OWLFB_COLOR_RGB444,
+	OWLFB_COLOR_YUV420SP,
+
+	OWLFB_COLOR_ARGB16,
+	OWLFB_COLOR_RGB24U,	/* RGB24, 32-bit container */
+	OWLFB_COLOR_RGB24P,	/* RGB24, 24-bit container */
+	OWLFB_COLOR_ARGB32,
+	OWLFB_COLOR_RGBA32,
+	OWLFB_COLOR_RGBX32,
+};
+
+
+enum owlfb_overlay_type {
+	OWLFB_OVERLAY_VIDEO = 1,
+	OWLFB_OVERLAY_CURSOR,	
+};
+
+struct owlfb_update_window {
+	__u32 x, y;
+	__u32 width, height;
+	__u32 format;
+	__u32 out_x, out_y;
+	__u32 out_width, out_height;
+	__u32 reserved[8];
+};
+
+struct owlfb_update_window_old {
+	__u32 x, y;
+	__u32 width, height;
+	__u32 format;
+};
+
+enum owlfb_plane {
+	OWLFB_PLANE_VID1,
+	OWLFB_PLANE_VID2,
+	OWLFB_PLANE_VID3,
+	OWLFB_PLANE_VID4,
+};
+
+enum owlfb_channel_out {
+	OWLFB_CHANNEL_OUT_LCD = 0,
+	OWLFB_CHANNEL_OUT_DIGIT,
+};
+
+struct owlfb_plane_info {
+	__u32 pos_x;
+	__u32 pos_y;
+	__u8  enabled;
+	__u8  channel_out;
+	__u8  mirror;
+	__u8  mem_idx;
+	__u32 out_width;
+	__u32 out_height;
+	__u32 reserved2[12];
+};
+
+struct owlfb_overlay_info {
+    __u32 mem_off;
+    __u32 mem_size;
+	
+	__u32 screen_width;	
+	enum owl_color_mode color_mode;		
+	__u32 img_width;
+	__u32 img_height;
+		
+	__u32 xoff;	
+	__u32 yoff;
+	__u32 width;
+	__u32 height;
+	
+	__u8 rotation;
+	
+	__u32 pos_x;
+	__u32 pos_y;
+	__u32 out_width;	/* if 0, out_width == width */
+	__u32 out_height;	/* if 0, out_height == height */
+	
+	__u8 lightness;
+	__u8 saturation;
+	__u8 contrast;
+	bool global_alpha_en;
+	__u8 global_alpha;
+	
+	bool pre_mult_alpha_en;	
+	__u8 zorder;
+};
+
+struct owlfb_mem_info {
+	__u32 size;
+	__u8  type;
+	__u8  reserved[3];
+};
+
+struct owlfb_caps {
+	__u32 ctrl;
+	__u32 plane_color;
+	__u32 wnd_color;
+};
+
+enum owlfb_color_key_type {
+	OWLFB_COLOR_KEY_DISABLED = 0,
+	OWLFB_COLOR_KEY_GFX_DST,
+	OWLFB_COLOR_KEY_VID_SRC,
+};
+
+struct owlfb_color_key {
+	__u8  channel_out;
+	__u32 background;
+	__u32 trans_key;
+	__u8  key_type;
+};
+
+enum owlfb_update_mode {
+	OWLFB_UPDATE_DISABLED = 0,
+	OWLFB_AUTO_UPDATE,
+	OWLFB_MANUAL_UPDATE
+};
+
+struct owlfb_memory_read {
+	__u16 x;
+	__u16 y;
+	__u16 w;
+	__u16 h;
+	size_t buffer_size;
+	void __user *buffer;
+};
+
+struct owlfb_overlay_args {
+	__u16 fb_id;
+	__u16 overlay_id;
+	__u16 overlay_type;
+	__u32 overlay_mem_base;
+	__u32 overlay_mem_size;
+	__u32 uintptr_overly_info;
+};
+
+struct owlfb_ovl_colormode {
+	__u8 overlay_idx;
+	__u8 mode_idx;
+	__u32 bits_per_pixel;
+	__u32 nonstd;
+	struct fb_bitfield red;
+	struct fb_bitfield green;
+	struct fb_bitfield blue;
+	struct fb_bitfield transp;
+};
+
+struct owlfb_disp_content_info {
+	struct owl_overlay_info overlay[4];
+};
+
+struct owlfb_disp_histogram_info {
+	__u32 hist[32];
+	__u32 totaly;
+};
+
+struct owlfb_sync_info {
+	__u8 enabled;
+	__u8 disp_id;
+	__u16 reserved2;
+};
+
+struct owlfb_display_info {
+	__u16 xres;
+	__u16 yres;
+	__u16 virtual_xres;
+	__u16 virtual_yres;
+	__u32 refresh_rate;
+	__u32 width;	/* phys width of the display in micrometers */
+	__u32 height;	/* phys height of the display in micrometers */
+	__u16 disp_type;
+	__u32 reserved[2];
+};
+
+
+struct owlfb_hdmi_vid_info {
+	__u8 vid;
+	__u8 mode;
+	__u16 reserved2;
+};
+#define MAX_PRIVATE_DATA_SIZE 40
+struct owlfb_disp_device{
+    __u32 mType;
+    __u32 mState;
+    __u32 mPluginState;
+    __u32 mWidth;
+    __u32 mHeight;
+    __u32 mRefreshRate;
+    __u32 mWidthScale;
+    __u32 mHeightScale;
+    __u32 mCmdMode;
+    __u32 mIcType;
+    __u32 mPrivateInfo[MAX_PRIVATE_DATA_SIZE];
+};
+
+struct display_private_info
+{
+	int LCD_TYPE;
+	int	LCD_LIGHTENESS;
+	int LCD_SATURATION;
+	int LCD_CONSTRAST;
+};
+
+enum CmdMode
+{
+    SET_LIGHTENESS = 0,
+    SET_SATURATION = 1,
+    SET_CONSTRAST = 2,
+	SET_DEFAULT = 3,
+
+};
+
+#endif /* __OWLFB_H */
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index a6dd21d..952cd2a 100755
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -29,6 +29,16 @@ config EARLYSUSPEND
 	---help---
 	  Call early suspend handlers when the user requested sleep state
 	  changes.
+
+config FB_EARLYSUSPEND
+	bool "FB Early suspend"
+	depends on EARLYSUSPEND
+	default n
+	select HAS_EARLYSUSPEND
+	---help---
+	  Call early suspend handlers when the user requested sleep state
+	  changes.
+
 config HIBERNATE_CALLBACKS
 	bool
 
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index ea00b9a..17f7075 100755
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -15,3 +15,4 @@ obj-$(CONFIG_PM_WAKELOCKS)	+= wakelock.o
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
 
 obj-$(CONFIG_EARLYSUSPEND)	+= earlysuspend.o
+obj-$(CONFIG_FB_EARLYSUSPEND)	+= fbearlysuspend.o
diff --git a/kernel/power/fbearlysuspend.c b/kernel/power/fbearlysuspend.c
new file mode 100755
index 0000000..1513765
--- /dev/null
+++ b/kernel/power/fbearlysuspend.c
@@ -0,0 +1,153 @@
+/* kernel/power/fbearlysuspend.c
+ *
+ * Copyright (C) 2005-2008 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/earlysuspend.h>
+#include <linux/module.h>
+#include <linux/wait.h>
+
+#include "power.h"
+
+static wait_queue_head_t fb_state_wq;
+static DEFINE_SPINLOCK(fb_state_lock);
+static enum {
+	FB_STATE_STOPPED_DRAWING,
+	FB_STATE_REQUEST_STOP_DRAWING,
+	FB_STATE_DRAWING_OK,
+} fb_state;
+
+/* tell userspace to stop drawing, wait for it to stop */
+static void stop_drawing_early_suspend(struct early_suspend *h)
+{
+	int ret;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	fb_state = FB_STATE_REQUEST_STOP_DRAWING;
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+
+	wake_up_all(&fb_state_wq);
+	ret = wait_event_timeout(fb_state_wq,
+				 fb_state == FB_STATE_STOPPED_DRAWING,
+				 HZ);
+	if (unlikely(fb_state != FB_STATE_STOPPED_DRAWING))
+		pr_warning("stop_drawing_early_suspend: timeout waiting for "
+			   "userspace to stop drawing\n");
+}
+
+/* tell userspace to start drawing */
+static void start_drawing_late_resume(struct early_suspend *h)
+{
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	fb_state = FB_STATE_DRAWING_OK;
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+	wake_up(&fb_state_wq);
+}
+
+static struct early_suspend stop_drawing_early_suspend_desc = {
+	.level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
+	.suspend = stop_drawing_early_suspend,
+	.resume = start_drawing_late_resume,
+};
+
+static ssize_t wait_for_fb_sleep_show(struct kobject *kobj,
+				      struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int ret;
+
+	ret = wait_event_interruptible(fb_state_wq,
+				       fb_state != FB_STATE_DRAWING_OK);
+	if (ret && fb_state == FB_STATE_DRAWING_OK)
+		return ret;
+	else
+		s += sprintf(buf, "sleeping");
+	return s - buf;
+}
+
+static ssize_t wait_for_fb_wake_show(struct kobject *kobj,
+				     struct kobj_attribute *attr, char *buf)
+{
+	char *s = buf;
+	int ret;
+	unsigned long irq_flags;
+
+	spin_lock_irqsave(&fb_state_lock, irq_flags);
+	if (fb_state == FB_STATE_REQUEST_STOP_DRAWING) {
+		fb_state = FB_STATE_STOPPED_DRAWING;
+		wake_up(&fb_state_wq);
+	}
+	spin_unlock_irqrestore(&fb_state_lock, irq_flags);
+
+	ret = wait_event_interruptible(fb_state_wq,
+				       fb_state == FB_STATE_DRAWING_OK);
+	if (ret && fb_state != FB_STATE_DRAWING_OK)
+		return ret;
+	else
+		s += sprintf(buf, "awake");
+
+	return s - buf;
+}
+
+#define power_ro_attr(_name) \
+static struct kobj_attribute _name##_attr = {	\
+	.attr	= {				\
+		.name = __stringify(_name),	\
+		.mode = 0444,			\
+	},					\
+	.show	= _name##_show,			\
+	.store	= NULL,		\
+}
+
+power_ro_attr(wait_for_fb_sleep);
+power_ro_attr(wait_for_fb_wake);
+
+static struct attribute *g[] = {
+	&wait_for_fb_sleep_attr.attr,
+	&wait_for_fb_wake_attr.attr,
+	NULL,
+};
+
+static struct attribute_group attr_group = {
+	.attrs = g,
+};
+
+static int __init android_power_init(void)
+{
+	int ret;
+
+	init_waitqueue_head(&fb_state_wq);
+	fb_state = FB_STATE_DRAWING_OK;
+
+	ret = sysfs_create_group(power_kobj, &attr_group);
+	if (ret) {
+		pr_err("android_power_init: sysfs_create_group failed\n");
+		return ret;
+	}
+
+	register_early_suspend(&stop_drawing_early_suspend_desc);
+	return 0;
+}
+
+static void  __exit android_power_exit(void)
+{
+	unregister_early_suspend(&stop_drawing_early_suspend_desc);
+	sysfs_remove_group(power_kobj, &attr_group);
+}
+
+module_init(android_power_init);
+module_exit(android_power_exit);
+
-- 
2.7.4



More information about the linux-yocto mailing list